1 /*
2 Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
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, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
23
24
25 #ifdef MYSQL_CLIENT
26
27 #include "sql_priv.h"
28 #include "mysqld_error.h"
29
30 #else
31
32 #include "binlog.h"
33 #include "sql_priv.h"
34 #include "unireg.h"
35 #include "my_global.h" // REQUIRED by log_event.h > m_string.h > my_bitmap.h
36 #include "log_event.h"
37 #include "sql_base.h" // close_thread_tables
38 #include "sql_cache.h" // QUERY_CACHE_FLAGS_SIZE
39 #include "sql_locale.h" // MY_LOCALE, my_locale_by_number, my_locale_en_US
40 #include "lock.h" // mysql_unlock_tables
41 #include "sql_parse.h" // mysql_test_parse_for_slave
42 #include "tztime.h" // struct Time_zone
43 #include "sql_load.h" // mysql_load
44 #include "sql_db.h" // load_db_opt_by_name
45 #include "rpl_slave.h"
46 #include "rpl_rli.h"
47 #include "rpl_mi.h"
48 #include "rpl_filter.h"
49 #include "rpl_record.h"
50 #include "transaction.h"
51 #include <my_dir.h>
52 #include "rpl_rli_pdb.h"
53 #include "sql_show.h" // append_identifier
54 #include "debug_sync.h" // debug_sync
55 #include <mysql/psi/mysql_statement.h>
56 #define window_size Log_throttle::LOG_THROTTLE_WINDOW_SIZE
57 Error_log_throttle
58 slave_ignored_err_throttle(window_size,
59 sql_print_warning,
60 "Error log throttle: %lu time(s) Error_code: 1237"
61 " \"Slave SQL thread ignored the query because of"
62 " replicate-*-table rules\" got suppressed.");
63 #endif /* MYSQL_CLIENT */
64
65 #include <base64.h>
66 #include <my_bitmap.h>
67 #include "rpl_utility.h"
68
69 #include "sql_digest.h"
70 #ifndef EMBEDDED_LIBRARY
71 #include "sql_connect.h" //update_global_user_stats
72 #endif
73
74 using std::min;
75 using std::max;
76
77 /* The number of event types need to be permuted. */
78 static const uint EVENT_TYPE_PERMUTATION_NUM= 23;
79
80 /**
81 BINLOG_CHECKSUM variable.
82 */
83 const char *binlog_checksum_type_names[]= {
84 "NONE",
85 "CRC32",
86 NullS
87 };
88
89 unsigned int binlog_checksum_type_length[]= {
90 sizeof("NONE") - 1,
91 sizeof("CRC32") - 1,
92 0
93 };
94
95 TYPELIB binlog_checksum_typelib=
96 {
97 array_elements(binlog_checksum_type_names) - 1, "",
98 binlog_checksum_type_names,
99 binlog_checksum_type_length
100 };
101
102
103 #define log_cs &my_charset_latin1
104
105 #define FLAGSTR(V,F) ((V)&(F)?#F" ":"")
106
107 /*
108 Size of buffer for printing a double in format %.<PREC>g
109
110 optional '-' + optional zero + '.' + PREC digits + 'e' + sign +
111 exponent digits + '\0'
112 */
113 #define FMT_G_BUFSIZE(PREC) (3 + (PREC) + 5 + 1)
114
115 /*
116 Explicit instantiation to unsigned int of template available_buffer
117 function.
118 */
119 template unsigned int available_buffer<unsigned int>(const char*,
120 const char*,
121 unsigned int);
122
123 /*
124 Explicit instantiation to unsigned int of template valid_buffer_range
125 function.
126 */
127 template bool valid_buffer_range<unsigned int>(unsigned int,
128 const char*,
129 const char*,
130 unsigned int);
131
132 /*
133 replication event checksum is introduced in the following "checksum-home" version.
134 The checksum-aware servers extract FD's version to decide whether the FD event
135 carries checksum info.
136 */
137 const uchar checksum_version_split[3]= {5, 6, 1};
138 const ulong checksum_version_product=
139 (checksum_version_split[0] * 256 + checksum_version_split[1]) * 256 +
140 checksum_version_split[2];
141
142 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
143 static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD* thd);
144
HA_ERR(int i)145 static const char *HA_ERR(int i)
146 {
147 /*
148 This function should only be called in case of an error
149 was detected
150 */
151 DBUG_ASSERT(i != 0);
152 switch (i) {
153 case HA_ERR_KEY_NOT_FOUND: return "HA_ERR_KEY_NOT_FOUND";
154 case HA_ERR_FOUND_DUPP_KEY: return "HA_ERR_FOUND_DUPP_KEY";
155 case HA_ERR_RECORD_CHANGED: return "HA_ERR_RECORD_CHANGED";
156 case HA_ERR_WRONG_INDEX: return "HA_ERR_WRONG_INDEX";
157 case HA_ERR_CRASHED: return "HA_ERR_CRASHED";
158 case HA_ERR_WRONG_IN_RECORD: return "HA_ERR_WRONG_IN_RECORD";
159 case HA_ERR_OUT_OF_MEM: return "HA_ERR_OUT_OF_MEM";
160 case HA_ERR_NOT_A_TABLE: return "HA_ERR_NOT_A_TABLE";
161 case HA_ERR_WRONG_COMMAND: return "HA_ERR_WRONG_COMMAND";
162 case HA_ERR_OLD_FILE: return "HA_ERR_OLD_FILE";
163 case HA_ERR_NO_ACTIVE_RECORD: return "HA_ERR_NO_ACTIVE_RECORD";
164 case HA_ERR_RECORD_DELETED: return "HA_ERR_RECORD_DELETED";
165 case HA_ERR_RECORD_FILE_FULL: return "HA_ERR_RECORD_FILE_FULL";
166 case HA_ERR_INDEX_FILE_FULL: return "HA_ERR_INDEX_FILE_FULL";
167 case HA_ERR_END_OF_FILE: return "HA_ERR_END_OF_FILE";
168 case HA_ERR_UNSUPPORTED: return "HA_ERR_UNSUPPORTED";
169 case HA_ERR_TO_BIG_ROW: return "HA_ERR_TO_BIG_ROW";
170 case HA_WRONG_CREATE_OPTION: return "HA_WRONG_CREATE_OPTION";
171 case HA_ERR_FOUND_DUPP_UNIQUE: return "HA_ERR_FOUND_DUPP_UNIQUE";
172 case HA_ERR_UNKNOWN_CHARSET: return "HA_ERR_UNKNOWN_CHARSET";
173 case HA_ERR_WRONG_MRG_TABLE_DEF: return "HA_ERR_WRONG_MRG_TABLE_DEF";
174 case HA_ERR_CRASHED_ON_REPAIR: return "HA_ERR_CRASHED_ON_REPAIR";
175 case HA_ERR_CRASHED_ON_USAGE: return "HA_ERR_CRASHED_ON_USAGE";
176 case HA_ERR_LOCK_WAIT_TIMEOUT: return "HA_ERR_LOCK_WAIT_TIMEOUT";
177 case HA_ERR_LOCK_TABLE_FULL: return "HA_ERR_LOCK_TABLE_FULL";
178 case HA_ERR_READ_ONLY_TRANSACTION: return "HA_ERR_READ_ONLY_TRANSACTION";
179 case HA_ERR_LOCK_DEADLOCK: return "HA_ERR_LOCK_DEADLOCK";
180 case HA_ERR_CANNOT_ADD_FOREIGN: return "HA_ERR_CANNOT_ADD_FOREIGN";
181 case HA_ERR_NO_REFERENCED_ROW: return "HA_ERR_NO_REFERENCED_ROW";
182 case HA_ERR_ROW_IS_REFERENCED: return "HA_ERR_ROW_IS_REFERENCED";
183 case HA_ERR_NO_SAVEPOINT: return "HA_ERR_NO_SAVEPOINT";
184 case HA_ERR_NON_UNIQUE_BLOCK_SIZE: return "HA_ERR_NON_UNIQUE_BLOCK_SIZE";
185 case HA_ERR_NO_SUCH_TABLE: return "HA_ERR_NO_SUCH_TABLE";
186 case HA_ERR_TABLE_EXIST: return "HA_ERR_TABLE_EXIST";
187 case HA_ERR_NO_CONNECTION: return "HA_ERR_NO_CONNECTION";
188 case HA_ERR_NULL_IN_SPATIAL: return "HA_ERR_NULL_IN_SPATIAL";
189 case HA_ERR_TABLE_DEF_CHANGED: return "HA_ERR_TABLE_DEF_CHANGED";
190 case HA_ERR_NO_PARTITION_FOUND: return "HA_ERR_NO_PARTITION_FOUND";
191 case HA_ERR_RBR_LOGGING_FAILED: return "HA_ERR_RBR_LOGGING_FAILED";
192 case HA_ERR_DROP_INDEX_FK: return "HA_ERR_DROP_INDEX_FK";
193 case HA_ERR_FOREIGN_DUPLICATE_KEY: return "HA_ERR_FOREIGN_DUPLICATE_KEY";
194 case HA_ERR_TABLE_NEEDS_UPGRADE: return "HA_ERR_TABLE_NEEDS_UPGRADE";
195 case HA_ERR_TABLE_READONLY: return "HA_ERR_TABLE_READONLY";
196 case HA_ERR_AUTOINC_READ_FAILED: return "HA_ERR_AUTOINC_READ_FAILED";
197 case HA_ERR_AUTOINC_ERANGE: return "HA_ERR_AUTOINC_ERANGE";
198 case HA_ERR_GENERIC: return "HA_ERR_GENERIC";
199 case HA_ERR_RECORD_IS_THE_SAME: return "HA_ERR_RECORD_IS_THE_SAME";
200 case HA_ERR_LOGGING_IMPOSSIBLE: return "HA_ERR_LOGGING_IMPOSSIBLE";
201 case HA_ERR_CORRUPT_EVENT: return "HA_ERR_CORRUPT_EVENT";
202 case HA_ERR_ROWS_EVENT_APPLY : return "HA_ERR_ROWS_EVENT_APPLY";
203 case HA_ERR_INNODB_READ_ONLY: return "HA_ERR_INNODB_READ_ONLY";
204 case HA_ERR_FTS_TOO_MANY_NESTED_EXP: return "HA_ERR_FTS_TOO_MANY_NESTED_EXP";
205 }
206 return "No Error!";
207 }
208
209 /**
210 Error reporting facility for Rows_log_event::do_apply_event
211
212 @param level error, warning or info
213 @param ha_error HA_ERR_ code
214 @param rli pointer to the active Relay_log_info instance
215 @param thd pointer to the slave thread's thd
216 @param table pointer to the event's table object
217 @param type the type of the event
218 @param log_name the master binlog file name
219 @param pos the master binlog file pos (the next after the event)
220
221 */
slave_rows_error_report(enum loglevel level,int ha_error,Relay_log_info const * rli,THD * thd,TABLE * table,const char * type,const char * log_name,ulong pos)222 static void inline slave_rows_error_report(enum loglevel level, int ha_error,
223 Relay_log_info const *rli, THD *thd,
224 TABLE *table, const char * type,
225 const char *log_name, ulong pos)
226 {
227 const char *handler_error= (ha_error ? HA_ERR(ha_error) : NULL);
228 char buff[MAX_SLAVE_ERRMSG], *slider;
229 const char *buff_end= buff + sizeof(buff);
230 uint len;
231 Diagnostics_area::Sql_condition_iterator it=
232 thd->get_stmt_da()->sql_conditions();
233 const Sql_condition *err;
234 buff[0]= 0;
235
236 for (err= it++, slider= buff; err && slider < buff_end - 1;
237 slider += len, err= it++)
238 {
239 len= my_snprintf(slider, buff_end - slider,
240 " %s, Error_code: %d;", err->get_message_text(),
241 err->get_sql_errno());
242 }
243
244 if (ha_error != 0)
245 rli->report(level, thd->is_error() ? thd->get_stmt_da()->sql_errno() : 0,
246 "Could not execute %s event on table %s.%s;"
247 "%s handler error %s; "
248 "the event's master log %s, end_log_pos %lu",
249 type, table->s->db.str, table->s->table_name.str,
250 buff, handler_error == NULL ? "<unknown>" : handler_error,
251 log_name, pos);
252 else
253 rli->report(level, thd->is_error() ? thd->get_stmt_da()->sql_errno() : 0,
254 "Could not execute %s event on table %s.%s;"
255 "%s the event's master log %s, end_log_pos %lu",
256 type, table->s->db.str, table->s->table_name.str,
257 buff, log_name, pos);
258 }
259
set_thd_db(THD * thd,const char * db,uint32 db_len)260 static void set_thd_db(THD *thd, const char *db, uint32 db_len)
261 {
262 char lcase_db_buf[NAME_LEN +1];
263 LEX_STRING new_db;
264 new_db.length= db_len;
265 if (lower_case_table_names == 1)
266 {
267 strmov(lcase_db_buf, db);
268 my_casedn_str(system_charset_info, lcase_db_buf);
269 new_db.str= lcase_db_buf;
270 }
271 else
272 new_db.str= (char*) db;
273
274 new_db.str= (char*) rpl_filter->get_rewrite_db(new_db.str,
275 &new_db.length);
276 thd->set_db(new_db.str, new_db.length);
277 }
278
279 #endif
280
281
282 /*
283 pretty_print_str()
284 */
285
286 #ifdef MYSQL_CLIENT
pretty_print_str(IO_CACHE * cache,const char * str,int len)287 static void pretty_print_str(IO_CACHE* cache, const char* str, int len)
288 {
289 const char* end = str + len;
290 my_b_printf(cache, "\'");
291 while (str < end)
292 {
293 char c;
294 switch ((c=*str++)) {
295 case '\n': my_b_printf(cache, "\\n"); break;
296 case '\r': my_b_printf(cache, "\\r"); break;
297 case '\\': my_b_printf(cache, "\\\\"); break;
298 case '\b': my_b_printf(cache, "\\b"); break;
299 case '\t': my_b_printf(cache, "\\t"); break;
300 case '\'': my_b_printf(cache, "\\'"); break;
301 case 0 : my_b_printf(cache, "\\0"); break;
302 default:
303 my_b_printf(cache, "%c", c);
304 break;
305 }
306 }
307 my_b_printf(cache, "\'");
308 }
309 #endif /* MYSQL_CLIENT */
310
311 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
312
clear_all_errors(THD * thd,Relay_log_info * rli)313 static void clear_all_errors(THD *thd, Relay_log_info *rli)
314 {
315 thd->is_slave_error = 0;
316 thd->clear_error();
317 rli->clear_error();
318 }
319
idempotent_error_code(int err_code)320 inline int idempotent_error_code(int err_code)
321 {
322 int ret= 0;
323
324 switch (err_code)
325 {
326 case 0:
327 ret= 1;
328 break;
329 /*
330 The following list of "idempotent" errors
331 means that an error from the list might happen
332 because of idempotent (more than once)
333 applying of a binlog file.
334 Notice, that binlog has a ddl operation its
335 second applying may cause
336
337 case HA_ERR_TABLE_DEF_CHANGED:
338 case HA_ERR_CANNOT_ADD_FOREIGN:
339
340 which are not included into to the list.
341
342 Note that HA_ERR_RECORD_DELETED is not in the list since
343 do_exec_row() should not return that error code.
344 */
345 case HA_ERR_RECORD_CHANGED:
346 case HA_ERR_KEY_NOT_FOUND:
347 case HA_ERR_END_OF_FILE:
348 case HA_ERR_FOUND_DUPP_KEY:
349 case HA_ERR_FOUND_DUPP_UNIQUE:
350 case HA_ERR_FOREIGN_DUPLICATE_KEY:
351 case HA_ERR_NO_REFERENCED_ROW:
352 case HA_ERR_ROW_IS_REFERENCED:
353 ret= 1;
354 break;
355 default:
356 ret= 0;
357 break;
358 }
359 return (ret);
360 }
361
362 /**
363 Ignore error code specified on command line.
364 */
365
ignored_error_code(int err_code)366 int ignored_error_code(int err_code)
367 {
368 #ifdef HAVE_NDB_BINLOG
369 /*
370 The following error codes are hard-coded and will always be ignored.
371 */
372 switch (err_code)
373 {
374 case ER_DB_CREATE_EXISTS:
375 case ER_DB_DROP_EXISTS:
376 return 1;
377 default:
378 /* Nothing to do */
379 break;
380 }
381 #endif
382 return ((err_code == ER_SLAVE_IGNORED_TABLE) ||
383 (use_slave_mask && bitmap_is_set(&slave_error_mask, err_code)));
384 }
385
386 /*
387 This function converts an engine's error to a server error.
388
389 If the thread does not have an error already reported, it tries to
390 define it by calling the engine's method print_error. However, if a
391 mapping is not found, it uses the ER_UNKNOWN_ERROR and prints out a
392 warning message.
393 */
convert_handler_error(int error,THD * thd,TABLE * table)394 int convert_handler_error(int error, THD* thd, TABLE *table)
395 {
396 uint actual_error= (thd->is_error() ? thd->get_stmt_da()->sql_errno() :
397 0);
398
399 if (actual_error == 0)
400 {
401 table->file->print_error(error, MYF(0));
402 actual_error= (thd->is_error() ? thd->get_stmt_da()->sql_errno() :
403 ER_UNKNOWN_ERROR);
404 if (actual_error == ER_UNKNOWN_ERROR)
405 if (log_warnings)
406 sql_print_warning("Unknown error detected %d in handler", error);
407 }
408
409 return (actual_error);
410 }
411
concurrency_error_code(int error)412 inline bool concurrency_error_code(int error)
413 {
414 switch (error)
415 {
416 case ER_LOCK_WAIT_TIMEOUT:
417 case ER_LOCK_DEADLOCK:
418 case ER_XA_RBDEADLOCK:
419 return TRUE;
420 default:
421 return (FALSE);
422 }
423 }
424
unexpected_error_code(int unexpected_error)425 inline bool unexpected_error_code(int unexpected_error)
426 {
427 switch (unexpected_error)
428 {
429 case ER_NET_READ_ERROR:
430 case ER_NET_ERROR_ON_WRITE:
431 case ER_QUERY_INTERRUPTED:
432 case ER_SERVER_SHUTDOWN:
433 case ER_NEW_ABORTING_CONNECTION:
434 return(TRUE);
435 default:
436 return(FALSE);
437 }
438 }
439
440 /*
441 pretty_print_str()
442 */
443
pretty_print_str(char * packet,const char * str,int len)444 static char *pretty_print_str(char *packet, const char *str, int len)
445 {
446 const char *end= str + len;
447 char *pos= packet;
448 *pos++= '\'';
449 while (str < end)
450 {
451 char c;
452 switch ((c=*str++)) {
453 case '\n': *pos++= '\\'; *pos++= 'n'; break;
454 case '\r': *pos++= '\\'; *pos++= 'r'; break;
455 case '\\': *pos++= '\\'; *pos++= '\\'; break;
456 case '\b': *pos++= '\\'; *pos++= 'b'; break;
457 case '\t': *pos++= '\\'; *pos++= 't'; break;
458 case '\'': *pos++= '\\'; *pos++= '\''; break;
459 case 0 : *pos++= '\\'; *pos++= '0'; break;
460 default:
461 *pos++= c;
462 break;
463 }
464 }
465 *pos++= '\'';
466 return pos;
467 }
468 #endif /* !MYSQL_CLIENT */
469
470
471 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
472
473 /**
474 Creates a temporary name for load data infile:.
475
476 @param buf Store new filename here
477 @param file_id File_id (part of file name)
478 @param event_server_id Event_id (part of file name)
479 @param ext Extension for file name
480
481 @return
482 Pointer to start of extension
483 */
484
slave_load_file_stem(char * buf,uint file_id,int event_server_id,const char * ext)485 static char *slave_load_file_stem(char *buf, uint file_id,
486 int event_server_id, const char *ext)
487 {
488 char *res;
489 fn_format(buf,PREFIX_SQL_LOAD,slave_load_tmpdir, "", MY_UNPACK_FILENAME);
490 to_unix_path(buf);
491
492 buf= strend(buf);
493 int appended_length= sprintf(buf, "%s-%d-", server_uuid, event_server_id);
494 buf+= appended_length;
495 res= int10_to_str(file_id, buf, 10);
496 strmov(res, ext); // Add extension last
497 return res; // Pointer to extension
498 }
499 #endif
500
501
502 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
503
504 /**
505 Delete all temporary files used for SQL_LOAD.
506 */
507
cleanup_load_tmpdir()508 static void cleanup_load_tmpdir()
509 {
510 MY_DIR *dirp;
511 FILEINFO *file;
512 uint i;
513 char fname[FN_REFLEN], prefbuf[TEMP_FILE_MAX_LEN], *p;
514
515 if (!(dirp=my_dir(slave_load_tmpdir,MYF(0))))
516 return;
517
518 /*
519 When we are deleting temporary files, we should only remove
520 the files associated with the server id of our server.
521 We don't use event_server_id here because since we've disabled
522 direct binlogging of Create_file/Append_file/Exec_load events
523 we cannot meet Start_log event in the middle of events from one
524 LOAD DATA.
525 */
526 p= strmake(prefbuf, STRING_WITH_LEN(PREFIX_SQL_LOAD));
527 sprintf(p,"%s-",server_uuid);
528
529 for (i=0 ; i < (uint)dirp->number_off_files; i++)
530 {
531 file=dirp->dir_entry+i;
532 if (is_prefix(file->name, prefbuf))
533 {
534 fn_format(fname,file->name,slave_load_tmpdir,"",MY_UNPACK_FILENAME);
535 mysql_file_delete(key_file_misc, fname, MYF(0));
536 }
537 }
538
539 my_dirend(dirp);
540 }
541 #endif
542
543
544 /*
545 Stores string to IO_CACHE file.
546
547 Writes str to file in the following format:
548 1. Stores length using only one byte (255 maximum value);
549 2. Stores complete str.
550 */
551
write_str_at_most_255_bytes(IO_CACHE * file,const char * str,uint length)552 static bool write_str_at_most_255_bytes(IO_CACHE *file, const char *str,
553 uint length)
554 {
555 uchar tmp[1];
556 tmp[0]= (uchar) length;
557 return (my_b_safe_write(file, tmp, sizeof(tmp)) ||
558 my_b_safe_write(file, (uchar*) str, length));
559 }
560
561
562 /*
563 Reads string from buf.
564
565 Reads str from buf in the following format:
566 1. Read length stored on buf first index, as it only has 1 byte values
567 bigger than 255 where lost.
568 2. Set str pointer to buf second index.
569 Despite str contains the complete stored string, when it is read until
570 len its value will be truncated if original length was bigger than 255.
571 */
572
read_str_at_most_255_bytes(const char ** buf,const char * buf_end,const char ** str,uint8 * len)573 static inline int read_str_at_most_255_bytes(const char **buf,
574 const char *buf_end,
575 const char **str,
576 uint8 *len)
577 {
578 if (*buf + ((uint) (uchar) **buf) >= buf_end)
579 return 1;
580 *len= (uint8) **buf;
581 *str= (*buf)+1;
582 (*buf)+= (uint) *len+1;
583 return 0;
584 }
585
586
587 /**
588 Transforms a string into "" or its expression in 0x... form.
589 */
590
str_to_hex(char * to,const char * from,uint len)591 char *str_to_hex(char *to, const char *from, uint len)
592 {
593 if (len)
594 {
595 *to++= '0';
596 *to++= 'x';
597 to= octet2hex(to, from, len);
598 }
599 else
600 to= strmov(to, "\"\"");
601 return to; // pointer to end 0 of 'to'
602 }
603
604 #ifndef MYSQL_CLIENT
605
606 /**
607 Append a version of the 'from' string suitable for use in a query to
608 the 'to' string. To generate a correct escaping, the character set
609 information in 'csinfo' is used.
610 */
611
612 int
append_query_string(THD * thd,const CHARSET_INFO * csinfo,String const * from,String * to)613 append_query_string(THD *thd, const CHARSET_INFO *csinfo,
614 String const *from, String *to)
615 {
616 char *beg, *ptr;
617 uint32 const orig_len= to->length();
618 if (to->reserve(orig_len + from->length()*2+3))
619 return 1;
620
621 beg= to->c_ptr_quick() + to->length();
622 ptr= beg;
623 if (csinfo->escape_with_backslash_is_dangerous)
624 ptr= str_to_hex(ptr, from->ptr(), from->length());
625 else
626 {
627 *ptr++= '\'';
628 if (!(thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES))
629 {
630 ptr+= escape_string_for_mysql(csinfo, ptr, 0,
631 from->ptr(), from->length());
632 }
633 else
634 {
635 const char *frm_str= from->ptr();
636
637 for (; frm_str < (from->ptr() + from->length()); frm_str++)
638 {
639 /* Using '' way to represent "'" */
640 if (*frm_str == '\'')
641 *ptr++= *frm_str;
642
643 *ptr++= *frm_str;
644 }
645 }
646
647 *ptr++= '\'';
648 }
649 to->length(orig_len + ptr - beg);
650 return 0;
651 }
652 #endif
653
654
655 /**
656 Prints a "session_var=value" string. Used by mysqlbinlog to print some SET
657 commands just before it prints a query.
658 */
659
660 #ifdef MYSQL_CLIENT
661
print_set_option(IO_CACHE * file,uint32 bits_changed,uint32 option,uint32 flags,const char * name,bool * need_comma)662 static void print_set_option(IO_CACHE* file, uint32 bits_changed,
663 uint32 option, uint32 flags, const char* name,
664 bool* need_comma)
665 {
666 if (bits_changed & option)
667 {
668 if (*need_comma)
669 my_b_printf(file,", ");
670 my_b_printf(file,"%s=%d", name, MY_TEST(flags & option));
671 *need_comma= 1;
672 }
673 }
674 #endif
675 /**************************************************************************
676 Log_event methods (= the parent class of all events)
677 **************************************************************************/
678
679 /**
680 @return
681 returns the human readable name of the event's type
682 */
683
get_type_str(Log_event_type type)684 const char* Log_event::get_type_str(Log_event_type type)
685 {
686 switch(type) {
687 case START_EVENT_V3: return "Start_v3";
688 case STOP_EVENT: return "Stop";
689 case QUERY_EVENT: return "Query";
690 case ROTATE_EVENT: return "Rotate";
691 case INTVAR_EVENT: return "Intvar";
692 case LOAD_EVENT: return "Load";
693 case NEW_LOAD_EVENT: return "New_load";
694 case CREATE_FILE_EVENT: return "Create_file";
695 case APPEND_BLOCK_EVENT: return "Append_block";
696 case DELETE_FILE_EVENT: return "Delete_file";
697 case EXEC_LOAD_EVENT: return "Exec_load";
698 case RAND_EVENT: return "RAND";
699 case XID_EVENT: return "Xid";
700 case USER_VAR_EVENT: return "User var";
701 case FORMAT_DESCRIPTION_EVENT: return "Format_desc";
702 case TABLE_MAP_EVENT: return "Table_map";
703 case PRE_GA_WRITE_ROWS_EVENT: return "Write_rows_event_old";
704 case PRE_GA_UPDATE_ROWS_EVENT: return "Update_rows_event_old";
705 case PRE_GA_DELETE_ROWS_EVENT: return "Delete_rows_event_old";
706 case WRITE_ROWS_EVENT_V1: return "Write_rows_v1";
707 case UPDATE_ROWS_EVENT_V1: return "Update_rows_v1";
708 case DELETE_ROWS_EVENT_V1: return "Delete_rows_v1";
709 case BEGIN_LOAD_QUERY_EVENT: return "Begin_load_query";
710 case EXECUTE_LOAD_QUERY_EVENT: return "Execute_load_query";
711 case INCIDENT_EVENT: return "Incident";
712 case IGNORABLE_LOG_EVENT: return "Ignorable";
713 case ROWS_QUERY_LOG_EVENT: return "Rows_query";
714 case WRITE_ROWS_EVENT: return "Write_rows";
715 case UPDATE_ROWS_EVENT: return "Update_rows";
716 case DELETE_ROWS_EVENT: return "Delete_rows";
717 case GTID_LOG_EVENT: return "Gtid";
718 case ANONYMOUS_GTID_LOG_EVENT: return "Anonymous_Gtid";
719 case PREVIOUS_GTIDS_LOG_EVENT: return "Previous_gtids";
720 case HEARTBEAT_LOG_EVENT: return "Heartbeat";
721 default: return "Unknown"; /* impossible */
722 }
723 }
724
get_type_str()725 const char* Log_event::get_type_str()
726 {
727 return get_type_str(get_type_code());
728 }
729
730
731 /*
732 Log_event::Log_event()
733 */
734
735 #ifndef MYSQL_CLIENT
Log_event(THD * thd_arg,uint16 flags_arg,enum_event_cache_type cache_type_arg,enum_event_logging_type logging_type_arg)736 Log_event::Log_event(THD* thd_arg, uint16 flags_arg,
737 enum_event_cache_type cache_type_arg,
738 enum_event_logging_type logging_type_arg)
739 :log_pos(0), temp_buf(0), exec_time(0), flags(flags_arg),
740 event_cache_type(cache_type_arg),
741 event_logging_type(logging_type_arg),
742 crc(0), thd(thd_arg), checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF)
743 {
744 server_id= thd->server_id;
745 unmasked_server_id= server_id;
746 when= thd->start_time;
747 }
748
749 /**
750 This minimal constructor is for when you are not even sure that there
751 is a valid THD. For example in the server when we are shutting down or
752 flushing logs after receiving a SIGHUP (then we must write a Rotate to
753 the binlog but we have no THD, so we need this minimal constructor).
754 */
755
Log_event(enum_event_cache_type cache_type_arg,enum_event_logging_type logging_type_arg)756 Log_event::Log_event(enum_event_cache_type cache_type_arg,
757 enum_event_logging_type logging_type_arg)
758 :temp_buf(0), exec_time(0), flags(0), event_cache_type(cache_type_arg),
759 event_logging_type(logging_type_arg), crc(0), thd(0),
760 checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF)
761 {
762 server_id= ::server_id;
763 unmasked_server_id= server_id;
764 /*
765 We can't call my_time() here as this would cause a call before
766 my_init() is called
767 */
768 when.tv_sec= 0;
769 when.tv_usec= 0;
770 log_pos= 0;
771 }
772 #endif /* !MYSQL_CLIENT */
773
774
775 /*
776 Log_event::Log_event()
777 */
778
Log_event(const char * buf,const Format_description_log_event * description_event)779 Log_event::Log_event(const char* buf,
780 const Format_description_log_event* description_event)
781 :temp_buf(0), exec_time(0),
782 event_cache_type(EVENT_INVALID_CACHE),
783 event_logging_type(EVENT_INVALID_LOGGING),
784 crc(0), checksum_alg(BINLOG_CHECKSUM_ALG_UNDEF)
785 {
786 #ifndef MYSQL_CLIENT
787 thd = 0;
788 #endif
789 when.tv_sec= uint4korr(buf);
790 when.tv_usec= 0;
791 server_id = uint4korr(buf + SERVER_ID_OFFSET);
792 unmasked_server_id = server_id;
793 /*
794 Mask out any irrelevant parts of the server_id
795 */
796 #ifdef HAVE_REPLICATION
797 server_id = unmasked_server_id & opt_server_id_mask;
798 #else
799 server_id = unmasked_server_id;
800 #endif
801 data_written= uint4korr(buf + EVENT_LEN_OFFSET);
802 if (description_event->binlog_version==1)
803 {
804 log_pos= 0;
805 flags= 0;
806 return;
807 }
808 /* 4.0 or newer */
809 log_pos= uint4korr(buf + LOG_POS_OFFSET);
810 /*
811 If the log is 4.0 (so here it can only be a 4.0 relay log read by
812 the SQL thread or a 4.0 master binlog read by the I/O thread),
813 log_pos is the beginning of the event: we transform it into the end
814 of the event, which is more useful.
815 But how do you know that the log is 4.0: you know it if
816 description_event is version 3 *and* you are not reading a
817 Format_desc (remember that mysqlbinlog starts by assuming that 5.0
818 logs are in 4.0 format, until it finds a Format_desc).
819 */
820 if (description_event->binlog_version==3 &&
821 buf[EVENT_TYPE_OFFSET]<FORMAT_DESCRIPTION_EVENT && log_pos)
822 {
823 /*
824 If log_pos=0, don't change it. log_pos==0 is a marker to mean
825 "don't change rli->group_master_log_pos" (see
826 inc_group_relay_log_pos()). As it is unreal log_pos, adding the
827 event len's is nonsense. For example, a fake Rotate event should
828 not have its log_pos (which is 0) changed or it will modify
829 Exec_master_log_pos in SHOW SLAVE STATUS, displaying a nonsense
830 value of (a non-zero offset which does not exist in the master's
831 binlog, so which will cause problems if the user uses this value
832 in CHANGE MASTER).
833 */
834 log_pos+= data_written; /* purecov: inspected */
835 }
836 DBUG_PRINT("info", ("log_pos: %lu", (ulong) log_pos));
837
838 flags= uint2korr(buf + FLAGS_OFFSET);
839 if ((buf[EVENT_TYPE_OFFSET] == FORMAT_DESCRIPTION_EVENT) ||
840 (buf[EVENT_TYPE_OFFSET] == ROTATE_EVENT))
841 {
842 /*
843 These events always have a header which stops here (i.e. their
844 header is FROZEN).
845 */
846 /*
847 Initialization to zero of all other Log_event members as they're
848 not specified. Currently there are no such members; in the future
849 there will be an event UID (but Format_description and Rotate
850 don't need this UID, as they are not propagated through
851 --log-slave-updates (remember the UID is used to not play a query
852 twice when you have two masters which are slaves of a 3rd master).
853 Then we are done.
854 */
855 return;
856 }
857 /* otherwise, go on with reading the header from buf (nothing now) */
858 }
859
860 #ifndef MYSQL_CLIENT
861 #ifdef HAVE_REPLICATION
do_apply_event_worker(Slave_worker * w)862 inline int Log_event::do_apply_event_worker(Slave_worker *w)
863 {
864 return do_apply_event(w);
865 }
866
do_update_pos(Relay_log_info * rli)867 int Log_event::do_update_pos(Relay_log_info *rli)
868 {
869 int error= 0;
870 DBUG_ASSERT(!rli->belongs_to_client());
871 /*
872 rli is null when (as far as I (Guilhem) know) the caller is
873 Load_log_event::do_apply_event *and* that one is called from
874 Execute_load_log_event::do_apply_event. In this case, we don't
875 do anything here ; Execute_load_log_event::do_apply_event will
876 call Log_event::do_apply_event again later with the proper rli.
877 Strictly speaking, if we were sure that rli is null only in the
878 case discussed above, 'if (rli)' is useless here. But as we are
879 not 100% sure, keep it for now.
880
881 Matz: I don't think we will need this check with this refactoring.
882 */
883
884 DBUG_ASSERT(!is_mts_worker(rli->info_thd));
885
886 if (rli)
887 error= rli->stmt_done(log_pos);
888 return error;
889 }
890
891
892 Log_event::enum_skip_reason
do_shall_skip(Relay_log_info * rli)893 Log_event::do_shall_skip(Relay_log_info *rli)
894 {
895 DBUG_PRINT("info", ("ev->server_id=%lu, ::server_id=%lu,"
896 " rli->replicate_same_server_id=%d,"
897 " rli->slave_skip_counter=%d",
898 (ulong) server_id, (ulong) ::server_id,
899 rli->replicate_same_server_id,
900 rli->slave_skip_counter));
901 if ((server_id == ::server_id && !rli->replicate_same_server_id) ||
902 (rli->slave_skip_counter == 1 && rli->is_in_group()))
903 return EVENT_SKIP_IGNORE;
904 else if (rli->slave_skip_counter > 0)
905 return EVENT_SKIP_COUNT;
906 else
907 return EVENT_SKIP_NOT;
908 }
909
910
911 /*
912 Log_event::pack_info()
913 */
914
pack_info(Protocol * protocol)915 int Log_event::pack_info(Protocol *protocol)
916 {
917 protocol->store("", &my_charset_bin);
918 return 0;
919 }
920
921
922 /**
923 Only called by SHOW BINLOG EVENTS
924 */
net_send(Protocol * protocol,const char * log_name,my_off_t pos)925 int Log_event::net_send(Protocol *protocol, const char* log_name, my_off_t pos)
926 {
927 const char *p= strrchr(log_name, FN_LIBCHAR);
928 const char *event_type;
929 if (p)
930 log_name = p + 1;
931
932 protocol->prepare_for_resend();
933 protocol->store(log_name, &my_charset_bin);
934 protocol->store((ulonglong) pos);
935 event_type = get_type_str();
936 protocol->store(event_type, strlen(event_type), &my_charset_bin);
937 protocol->store((uint32) server_id);
938 protocol->store((ulonglong) log_pos);
939 if (pack_info(protocol))
940 return 1;
941 return protocol->write();
942 }
943 #endif /* HAVE_REPLICATION */
944
945
946 /**
947 init_show_field_list() prepares the column names and types for the
948 output of SHOW BINLOG EVENTS; it is used only by SHOW BINLOG
949 EVENTS.
950 */
951
init_show_field_list(List<Item> * field_list)952 void Log_event::init_show_field_list(List<Item>* field_list)
953 {
954 field_list->push_back(new Item_empty_string("Log_name", 20));
955 field_list->push_back(new Item_return_int("Pos", MY_INT32_NUM_DECIMAL_DIGITS,
956 MYSQL_TYPE_LONGLONG));
957 field_list->push_back(new Item_empty_string("Event_type", 20));
958 field_list->push_back(new Item_return_int("Server_id", 10,
959 MYSQL_TYPE_LONG));
960 field_list->push_back(new Item_return_int("End_log_pos",
961 MY_INT32_NUM_DECIMAL_DIGITS,
962 MYSQL_TYPE_LONGLONG));
963 field_list->push_back(new Item_empty_string("Info", 20));
964 }
965
966 /**
967 A decider of whether to trigger checksum computation or not.
968 To be invoked in Log_event::write() stack.
969 The decision is positive
970
971 S,M) if it's been marked for checksumming with @c checksum_alg
972
973 M) otherwise, if @@global.binlog_checksum is not NONE and the event is
974 directly written to the binlog file.
975 The to-be-cached event decides at @c write_cache() time.
976
977 Otherwise the decision is negative.
978
979 @note A side effect of the method is altering Log_event::checksum_alg
980 it the latter was undefined at calling.
981
982 @return true (positive) or false (negative)
983 */
need_checksum()984 my_bool Log_event::need_checksum()
985 {
986 DBUG_ENTER("Log_event::need_checksum");
987 my_bool ret= FALSE;
988 /*
989 few callers of Log_event::write
990 (incl FD::write, FD constructing code on the slave side, Rotate relay log
991 and Stop event)
992 provides their checksum alg preference through Log_event::checksum_alg.
993 */
994 if (checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF)
995 ret= (checksum_alg != BINLOG_CHECKSUM_ALG_OFF);
996 else if (binlog_checksum_options != BINLOG_CHECKSUM_ALG_OFF &&
997 event_cache_type == Log_event::EVENT_NO_CACHE)
998 ret= binlog_checksum_options;
999 else
1000 ret= FALSE;
1001
1002 /*
1003 FD calls the methods before data_written has been calculated.
1004 The following invariant claims if the current is not the first
1005 call (and therefore data_written is not zero) then `ret' must be
1006 TRUE. It may not be null because FD is always checksummed.
1007 */
1008
1009 DBUG_ASSERT(get_type_code() != FORMAT_DESCRIPTION_EVENT || ret ||
1010 data_written == 0);
1011
1012 if (checksum_alg == BINLOG_CHECKSUM_ALG_UNDEF)
1013 checksum_alg= ret ? // calculated value stored
1014 binlog_checksum_options : (uint8) BINLOG_CHECKSUM_ALG_OFF;
1015
1016 DBUG_ASSERT(!ret ||
1017 ((checksum_alg == binlog_checksum_options ||
1018 /*
1019 Stop event closes the relay-log and its checksum alg
1020 preference is set by the caller can be different
1021 from the server's binlog_checksum_options.
1022 */
1023 get_type_code() == STOP_EVENT ||
1024 /*
1025 Rotate:s can be checksummed regardless of the server's
1026 binlog_checksum_options. That applies to both
1027 the local RL's Rotate and the master's Rotate
1028 which IO thread instantiates via queue_binlog_ver_3_event.
1029 */
1030 get_type_code() == ROTATE_EVENT ||
1031 /*
1032 The previous event has its checksum option defined
1033 according to the format description event.
1034 */
1035 get_type_code() == PREVIOUS_GTIDS_LOG_EVENT ||
1036 /* FD is always checksummed */
1037 get_type_code() == FORMAT_DESCRIPTION_EVENT) &&
1038 checksum_alg != BINLOG_CHECKSUM_ALG_OFF));
1039
1040 DBUG_ASSERT(checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF);
1041 DBUG_ASSERT(((get_type_code() != ROTATE_EVENT &&
1042 get_type_code() != STOP_EVENT) ||
1043 get_type_code() != FORMAT_DESCRIPTION_EVENT) ||
1044 event_cache_type == Log_event::EVENT_NO_CACHE);
1045
1046 DBUG_RETURN(ret);
1047 }
1048
wrapper_my_b_safe_write(IO_CACHE * file,const uchar * buf,ulong size)1049 bool Log_event::wrapper_my_b_safe_write(IO_CACHE* file, const uchar* buf, ulong size)
1050 {
1051 DBUG_EXECUTE_IF("simulate_temp_file_write_error",
1052 {
1053 file->write_pos = file->write_end;
1054 DBUG_SET("+d,simulate_file_write_error");
1055 });
1056 if (need_checksum() && size != 0)
1057 crc= my_checksum(crc, buf, size);
1058 bool ret = my_b_safe_write(file, buf, size);
1059 DBUG_EXECUTE_IF("simulate_temp_file_write_error",
1060 {
1061 DBUG_SET("-d,simulate_file_write_error");
1062 });
1063 return ret;
1064 }
1065
write_footer(IO_CACHE * file)1066 bool Log_event::write_footer(IO_CACHE* file)
1067 {
1068 /*
1069 footer contains the checksum-algorithm descriptor
1070 followed by the checksum value
1071 */
1072 if (need_checksum())
1073 {
1074 uchar buf[BINLOG_CHECKSUM_LEN];
1075 int4store(buf, crc);
1076 return (my_b_safe_write(file, (uchar*) buf, sizeof(buf)));
1077 }
1078 return 0;
1079 }
1080
1081 /*
1082 Log_event::write()
1083 */
1084
write_header(IO_CACHE * file,ulong event_data_length)1085 bool Log_event::write_header(IO_CACHE* file, ulong event_data_length)
1086 {
1087 uchar header[LOG_EVENT_HEADER_LEN];
1088 ulong now;
1089 bool ret;
1090 DBUG_ENTER("Log_event::write_header");
1091
1092 /* Store number of bytes that will be written by this event */
1093 data_written= event_data_length + sizeof(header);
1094
1095 if (need_checksum())
1096 {
1097 crc= my_checksum(0L, NULL, 0);
1098 data_written += BINLOG_CHECKSUM_LEN;
1099 }
1100
1101 /*
1102 log_pos != 0 if this is relay-log event. In this case we should not
1103 change the position
1104 */
1105
1106 if (is_artificial_event())
1107 {
1108 /*
1109 Artificial events are automatically generated and do not exist
1110 in master's binary log, so log_pos should be set to 0.
1111 */
1112 log_pos= 0;
1113 }
1114 else if (!log_pos)
1115 {
1116 /*
1117 Calculate position of end of event
1118
1119 Note that with a SEQ_READ_APPEND cache, my_b_tell() does not
1120 work well. So this will give slightly wrong positions for the
1121 Format_desc/Rotate/Stop events which the slave writes to its
1122 relay log. For example, the initial Format_desc will have
1123 end_log_pos=91 instead of 95. Because after writing the first 4
1124 bytes of the relay log, my_b_tell() still reports 0. Because
1125 my_b_append() does not update the counter which my_b_tell()
1126 later uses (one should probably use my_b_append_tell() to work
1127 around this). To get right positions even when writing to the
1128 relay log, we use the (new) my_b_safe_tell().
1129
1130 Note that this raises a question on the correctness of all these
1131 DBUG_ASSERT(my_b_tell()=rli->event_relay_log_pos).
1132
1133 If in a transaction, the log_pos which we calculate below is not
1134 very good (because then my_b_safe_tell() returns start position
1135 of the BEGIN, so it's like the statement was at the BEGIN's
1136 place), but it's not a very serious problem (as the slave, when
1137 it is in a transaction, does not take those end_log_pos into
1138 account (as it calls inc_event_relay_log_pos()). To be fixed
1139 later, so that it looks less strange. But not bug.
1140 */
1141
1142 log_pos= my_b_safe_tell(file)+data_written;
1143 }
1144
1145 now= (ulong) get_time(); // Query start time
1146 if (DBUG_EVALUATE_IF("inc_event_time_by_1_hour",1,0) &&
1147 DBUG_EVALUATE_IF("dec_event_time_by_1_hour",1,0))
1148 {
1149 /**
1150 This assertion guarantees that these debug flags are not
1151 used at the same time (they would cancel each other).
1152 */
1153 DBUG_ASSERT(0);
1154 }
1155 else
1156 {
1157 DBUG_EXECUTE_IF("inc_event_time_by_1_hour", now= now + 3600;);
1158 DBUG_EXECUTE_IF("dec_event_time_by_1_hour", now= now - 3600;);
1159 }
1160
1161 /*
1162 Header will be of size LOG_EVENT_HEADER_LEN for all events, except for
1163 FORMAT_DESCRIPTION_EVENT and ROTATE_EVENT, where it will be
1164 LOG_EVENT_MINIMAL_HEADER_LEN (remember these 2 have a frozen header,
1165 because we read them before knowing the format).
1166 */
1167
1168 int4store(header, now); // timestamp
1169 header[EVENT_TYPE_OFFSET]= get_type_code();
1170 int4store(header+ SERVER_ID_OFFSET, server_id);
1171 int4store(header+ EVENT_LEN_OFFSET, data_written);
1172 int4store(header+ LOG_POS_OFFSET, log_pos);
1173 /*
1174 recording checksum of FD event computed with dropped
1175 possibly active LOG_EVENT_BINLOG_IN_USE_F flag.
1176 Similar step at verication: the active flag is dropped before
1177 checksum computing.
1178 */
1179 if (header[EVENT_TYPE_OFFSET] != FORMAT_DESCRIPTION_EVENT ||
1180 !need_checksum() || !(flags & LOG_EVENT_BINLOG_IN_USE_F))
1181 {
1182 int2store(header+ FLAGS_OFFSET, flags);
1183 ret= wrapper_my_b_safe_write(file, header, sizeof(header)) != 0;
1184 }
1185 else
1186 {
1187 ret= (wrapper_my_b_safe_write(file, header, FLAGS_OFFSET) != 0);
1188 if (!ret)
1189 {
1190 flags &= ~LOG_EVENT_BINLOG_IN_USE_F;
1191 int2store(header + FLAGS_OFFSET, flags);
1192 crc= my_checksum(crc, header + FLAGS_OFFSET, sizeof(flags));
1193 flags |= LOG_EVENT_BINLOG_IN_USE_F;
1194 int2store(header + FLAGS_OFFSET, flags);
1195 ret= (my_b_safe_write(file, header + FLAGS_OFFSET, sizeof(flags)) != 0);
1196 }
1197 if (!ret)
1198 ret= (wrapper_my_b_safe_write(file, header + FLAGS_OFFSET + sizeof(flags),
1199 sizeof(header)
1200 - (FLAGS_OFFSET + sizeof(flags))) != 0);
1201 }
1202 DBUG_RETURN( ret);
1203 }
1204
1205
1206 /**
1207 This needn't be format-tolerant, because we only read
1208 LOG_EVENT_MINIMAL_HEADER_LEN (we just want to read the event's length).
1209 */
1210
read_log_event(IO_CACHE * file,String * packet,mysql_mutex_t * log_lock,uint8 checksum_alg_arg,const char * log_file_name_arg,bool * is_binlog_active)1211 int Log_event::read_log_event(IO_CACHE* file, String* packet,
1212 mysql_mutex_t* log_lock,
1213 uint8 checksum_alg_arg,
1214 const char *log_file_name_arg,
1215 bool* is_binlog_active)
1216 {
1217 ulong data_len;
1218 int result=0;
1219 char buf[LOG_EVENT_MINIMAL_HEADER_LEN];
1220 uchar ev_offset= packet->length();
1221 DBUG_ENTER("Log_event::read_log_event(IO_CACHE *, String *, mysql_mutex_t, uint8)");
1222
1223 if (log_lock)
1224 mysql_mutex_lock(log_lock);
1225
1226 if (log_file_name_arg)
1227 *is_binlog_active= mysql_bin_log.is_active(log_file_name_arg);
1228
1229 if (my_b_read(file, (uchar*) buf, sizeof(buf)))
1230 {
1231 /*
1232 If the read hits eof, we must report it as eof so the caller
1233 will know it can go into cond_wait to be woken up on the next
1234 update to the log.
1235 */
1236 DBUG_PRINT("error",("my_b_read failed. file->error: %d", file->error));
1237 if (!file->error)
1238 result= LOG_READ_EOF;
1239 else
1240 result= (file->error > 0 ? LOG_READ_TRUNC : LOG_READ_IO);
1241 goto end;
1242 }
1243 data_len= uint4korr(buf + EVENT_LEN_OFFSET);
1244 if (data_len < LOG_EVENT_MINIMAL_HEADER_LEN ||
1245 data_len > max(current_thd->variables.max_allowed_packet,
1246 opt_binlog_rows_event_max_size + MAX_LOG_EVENT_HEADER))
1247 {
1248 DBUG_PRINT("error",("data_len is out of bounds. data_len: %lu", data_len));
1249 result= ((data_len < LOG_EVENT_MINIMAL_HEADER_LEN) ? LOG_READ_BOGUS :
1250 LOG_READ_TOO_LARGE);
1251 goto end;
1252 }
1253
1254 /* Append the log event header to packet */
1255 if (packet->append(buf, sizeof(buf)))
1256 {
1257 DBUG_PRINT("info", ("first packet->append failed (out of memory)"));
1258 /* Failed to allocate packet */
1259 result= LOG_READ_MEM;
1260 goto end;
1261 }
1262 data_len-= LOG_EVENT_MINIMAL_HEADER_LEN;
1263 if (data_len)
1264 {
1265 /* Append rest of event, read directly from file into packet */
1266 if (packet->append(file, data_len))
1267 {
1268 /*
1269 Fatal error occured when appending rest of the event
1270 to packet, possible failures:
1271 1. EOF occured when reading from file, it's really an error
1272 as data_len is >=0 there's supposed to be more bytes available.
1273 file->error will have been set to number of bytes left to read
1274 2. Read was interrupted, file->error would normally be set to -1
1275 3. Failed to allocate memory for packet, my_errno
1276 will be ENOMEM(file->error shuold be 0, but since the
1277 memory allocation occurs before the call to read it might
1278 be uninitialized)
1279 */
1280 DBUG_PRINT("info", ("second packet->append failed (out of memory)"));
1281 result= (my_errno == ENOMEM ? LOG_READ_MEM :
1282 (file->error >= 0 ? LOG_READ_TRUNC: LOG_READ_IO));
1283 goto end;
1284 }
1285 else
1286 {
1287 /*
1288 Corrupt the event for Dump thread.
1289 We also need to exclude Previous_gtids_log_event and Gtid_log_event
1290 events from injected corruption to allow dump thread to move forward
1291 on binary log until the missing transactions from slave when
1292 MASTER_AUTO_POSITION= 1.
1293 */
1294 DBUG_EXECUTE_IF("corrupt_read_log_event",
1295 uchar *debug_event_buf_c = (uchar*) packet->ptr() + ev_offset;
1296 if (debug_event_buf_c[EVENT_TYPE_OFFSET] != FORMAT_DESCRIPTION_EVENT &&
1297 debug_event_buf_c[EVENT_TYPE_OFFSET] != PREVIOUS_GTIDS_LOG_EVENT &&
1298 debug_event_buf_c[EVENT_TYPE_OFFSET] != GTID_LOG_EVENT)
1299 {
1300 int debug_cor_pos = rand() % (data_len + sizeof(buf) - BINLOG_CHECKSUM_LEN);
1301 debug_event_buf_c[debug_cor_pos] =~ debug_event_buf_c[debug_cor_pos];
1302 DBUG_PRINT("info", ("Corrupt the event at Log_event::read_log_event: byte on position %d", debug_cor_pos));
1303 }
1304 );
1305 /*
1306 CRC verification of the Dump thread
1307 */
1308 if (opt_master_verify_checksum &&
1309 event_checksum_test((uchar*) packet->ptr() + ev_offset,
1310 data_len + sizeof(buf),
1311 checksum_alg_arg))
1312 {
1313 DBUG_PRINT("info", ("checksum test failed"));
1314 result= LOG_READ_CHECKSUM_FAILURE;
1315 goto end;
1316 }
1317 }
1318 }
1319
1320 end:
1321 if (log_lock)
1322 mysql_mutex_unlock(log_lock);
1323 DBUG_PRINT("info", ("read_log_event returns %d", result));
1324 DBUG_RETURN(result);
1325 }
1326 #endif /* !MYSQL_CLIENT */
1327
1328 #ifndef MYSQL_CLIENT
1329 #define UNLOCK_MUTEX if (log_lock) mysql_mutex_unlock(log_lock);
1330 #define LOCK_MUTEX if (log_lock) mysql_mutex_lock(log_lock);
1331 #else
1332 #define UNLOCK_MUTEX
1333 #define LOCK_MUTEX
1334 #endif
1335
1336 #ifndef MYSQL_CLIENT
1337 /**
1338 @note
1339 Allocates memory; The caller is responsible for clean-up.
1340 */
read_log_event(IO_CACHE * file,mysql_mutex_t * log_lock,const Format_description_log_event * description_event,my_bool crc_check)1341 Log_event* Log_event::read_log_event(IO_CACHE* file,
1342 mysql_mutex_t* log_lock,
1343 const Format_description_log_event
1344 *description_event,
1345 my_bool crc_check)
1346 #else
1347 Log_event* Log_event::read_log_event(IO_CACHE* file,
1348 const Format_description_log_event
1349 *description_event,
1350 my_bool crc_check)
1351 #endif
1352 {
1353 DBUG_ENTER("Log_event::read_log_event(IO_CACHE *[, mysql_mutex_t *], Format_description_log_event *, my_bool)");
1354 DBUG_ASSERT(description_event != 0);
1355 char head[LOG_EVENT_MINIMAL_HEADER_LEN];
1356 /*
1357 First we only want to read at most LOG_EVENT_MINIMAL_HEADER_LEN, just to
1358 check the event for sanity and to know its length; no need to really parse
1359 it. We say "at most" because this could be a 3.23 master, which has header
1360 of 13 bytes, whereas LOG_EVENT_MINIMAL_HEADER_LEN is 19 bytes (it's
1361 "minimal" over the set {MySQL >=4.0}).
1362 */
1363 uint header_size= min<uint>(description_event->common_header_len,
1364 LOG_EVENT_MINIMAL_HEADER_LEN);
1365
1366 LOCK_MUTEX;
1367 DBUG_PRINT("info", ("my_b_tell: %lu", (ulong) my_b_tell(file)));
1368 if (my_b_read(file, (uchar *) head, header_size))
1369 {
1370 DBUG_PRINT("info", ("Log_event::read_log_event(IO_CACHE*,Format_desc*) "
1371 "failed in my_b_read((IO_CACHE*)%p, (uchar*)%p, %u)",
1372 file, head, header_size));
1373 UNLOCK_MUTEX;
1374 /*
1375 No error here; it could be that we are at the file's end. However
1376 if the next my_b_read() fails (below), it will be an error as we
1377 were able to read the first bytes.
1378 */
1379 DBUG_RETURN(0);
1380 }
1381 ulong data_len = uint4korr(head + EVENT_LEN_OFFSET);
1382 char *buf= 0;
1383 const char *error= 0;
1384 Log_event *res= 0;
1385 #ifndef max_allowed_packet
1386 THD *thd=current_thd;
1387 ulong max_allowed_packet= thd ? slave_max_allowed_packet : ~(ulong)0;
1388 #endif
1389
1390 ulong const max_size=
1391 max<ulong>(max_allowed_packet,
1392 opt_binlog_rows_event_max_size + MAX_LOG_EVENT_HEADER);
1393 if (data_len > max_size)
1394 {
1395 error = "Event too big";
1396 goto err;
1397 }
1398
1399 if (data_len < header_size)
1400 {
1401 error = "Event too small";
1402 goto err;
1403 }
1404
1405 // some events use the extra byte to null-terminate strings
1406 if (!(buf = (char*) my_malloc(data_len+1, MYF(MY_WME))))
1407 {
1408 error = "Out of memory";
1409 goto err;
1410 }
1411 buf[data_len] = 0;
1412 memcpy(buf, head, header_size);
1413 if (my_b_read(file, (uchar*) buf + header_size, data_len - header_size))
1414 {
1415 error = "read error";
1416 goto err;
1417 }
1418 if ((res= read_log_event(buf, data_len, &error, description_event, crc_check)))
1419 res->register_temp_buf(buf);
1420
1421 err:
1422 UNLOCK_MUTEX;
1423 if (!res)
1424 {
1425 DBUG_ASSERT(error != 0);
1426 /* Don't log error if read_log_event invoked from SHOW BINLOG EVENTS */
1427 #ifdef MYSQL_SERVER
1428 THD *thd= current_thd;
1429 if (!(thd && thd->lex &&
1430 thd->lex->sql_command == SQLCOM_SHOW_BINLOG_EVENTS)) {
1431 #endif
1432 sql_print_error("Error in Log_event::read_log_event(): "
1433 "'%s', data_len: %lu, event_type: %d",
1434 error,data_len,head[EVENT_TYPE_OFFSET]);
1435 #ifdef MYSQL_SERVER
1436 }
1437 #endif
1438 my_free(buf);
1439 /*
1440 The SQL slave thread will check if file->error<0 to know
1441 if there was an I/O error. Even if there is no "low-level" I/O errors
1442 with 'file', any of the high-level above errors is worrying
1443 enough to stop the SQL thread now ; as we are skipping the current event,
1444 going on with reading and successfully executing other events can
1445 only corrupt the slave's databases. So stop.
1446 The file->error is also checked to record the position of
1447 the last valid event when master server recovers.
1448 */
1449 file->error= -1;
1450 }
1451 DBUG_RETURN(res);
1452 }
1453
1454
1455 /**
1456 Binlog format tolerance is in (buf, event_len, description_event)
1457 constructors.
1458 */
1459
read_log_event(const char * buf,uint event_len,const char ** error,const Format_description_log_event * description_event,my_bool crc_check)1460 Log_event* Log_event::read_log_event(const char* buf, uint event_len,
1461 const char **error,
1462 const Format_description_log_event *description_event,
1463 my_bool crc_check)
1464 {
1465 Log_event* ev;
1466 uint8 alg;
1467 DBUG_ENTER("Log_event::read_log_event(char *, uint, char **, Format_description_log_event *, my_bool)");
1468 DBUG_ASSERT(description_event != 0);
1469 DBUG_PRINT("info", ("binlog_version: %d", description_event->binlog_version));
1470 DBUG_DUMP("data", (unsigned char*) buf, event_len);
1471
1472 /* Check the integrity */
1473 if (event_len < EVENT_LEN_OFFSET ||
1474 (uint) event_len != uint4korr(buf+EVENT_LEN_OFFSET))
1475 {
1476 DBUG_PRINT("error", ("event_len=%u EVENT_LEN_OFFSET=%d "
1477 "buf[EVENT_TYPE_OFFSET]=%d ENUM_END_EVENT=%d "
1478 "uint4korr(buf+EVENT_LEN_OFFSET)=%d",
1479 event_len, EVENT_LEN_OFFSET,
1480 buf[EVENT_TYPE_OFFSET], ENUM_END_EVENT,
1481 uint4korr(buf+EVENT_LEN_OFFSET)));
1482 *error="Sanity check failed"; // Needed to free buffer
1483 DBUG_RETURN(NULL); // general sanity check - will fail on a partial read
1484 }
1485
1486 uint event_type= buf[EVENT_TYPE_OFFSET];
1487 // all following START events in the current file are without checksum
1488 if (event_type == START_EVENT_V3)
1489 (const_cast< Format_description_log_event *>(description_event))->checksum_alg= BINLOG_CHECKSUM_ALG_OFF;
1490 // Sanity check for Format description event
1491 if (event_type == FORMAT_DESCRIPTION_EVENT)
1492 {
1493 if (event_len < LOG_EVENT_MINIMAL_HEADER_LEN +
1494 ST_COMMON_HEADER_LEN_OFFSET)
1495 {
1496 *error= "Found invalid Format description event in binary log";
1497 DBUG_RETURN(0);
1498 }
1499 uint tmp_header_len= buf[LOG_EVENT_MINIMAL_HEADER_LEN + ST_COMMON_HEADER_LEN_OFFSET];
1500 if (event_len < tmp_header_len + ST_SERVER_VER_OFFSET + ST_SERVER_VER_LEN)
1501 {
1502 *error= "Found invalid Format description event in binary log";
1503 DBUG_RETURN(0);
1504 }
1505 }
1506 /*
1507 CRC verification by SQL and Show-Binlog-Events master side.
1508 The caller has to provide @description_event->checksum_alg to
1509 be the last seen FD's (A) descriptor.
1510 If event is FD the descriptor is in it.
1511 Notice, FD of the binlog can be only in one instance and therefore
1512 Show-Binlog-Events executing master side thread needs just to know
1513 the only FD's (A) value - whereas RL can contain more.
1514 In the RL case, the alg is kept in FD_e (@description_event) which is reset
1515 to the newer read-out event after its execution with possibly new alg descriptor.
1516 Therefore in a typical sequence of RL:
1517 {FD_s^0, FD_m, E_m^1} E_m^1
1518 will be verified with (A) of FD_m.
1519
1520 See legends definition on MYSQL_BIN_LOG::relay_log_checksum_alg docs
1521 lines (log.h).
1522
1523 Notice, a pre-checksum FD version forces alg := BINLOG_CHECKSUM_ALG_UNDEF.
1524 */
1525 alg= (event_type != FORMAT_DESCRIPTION_EVENT) ?
1526 description_event->checksum_alg : get_checksum_alg(buf, event_len);
1527 // Emulate the corruption during reading an event
1528 DBUG_EXECUTE_IF("corrupt_read_log_event_char",
1529 if (event_type != FORMAT_DESCRIPTION_EVENT)
1530 {
1531 char *debug_event_buf_c = (char *)buf;
1532 int debug_cor_pos = rand() % (event_len - BINLOG_CHECKSUM_LEN);
1533 debug_event_buf_c[debug_cor_pos] =~ debug_event_buf_c[debug_cor_pos];
1534 DBUG_PRINT("info", ("Corrupt the event at Log_event::read_log_event(char*,...): byte on position %d", debug_cor_pos));
1535 DBUG_SET("");
1536 }
1537 );
1538 if (crc_check &&
1539 event_checksum_test((uchar *) buf, event_len, alg) &&
1540 /* Skip the crc check when simulating an unknown ignorable log event. */
1541 !DBUG_EVALUATE_IF("simulate_unknown_ignorable_log_event", 1, 0))
1542 {
1543 *error= "Event crc check failed! Most likely there is event corruption.";
1544 #ifdef MYSQL_CLIENT
1545 if (force_opt)
1546 {
1547 ev= new Unknown_log_event(buf, description_event);
1548 DBUG_RETURN(ev);
1549 }
1550 #endif
1551 DBUG_RETURN(NULL);
1552 }
1553
1554 if (event_type > description_event->number_of_event_types &&
1555 event_type != FORMAT_DESCRIPTION_EVENT &&
1556 /*
1557 Skip the event type check when simulating an
1558 unknown ignorable log event.
1559 */
1560 !DBUG_EVALUATE_IF("simulate_unknown_ignorable_log_event", 1, 0))
1561 {
1562 /*
1563 It is unsafe to use the description_event if its post_header_len
1564 array does not include the event type.
1565 */
1566 DBUG_PRINT("error", ("event type %d found, but the current "
1567 "Format_description_log_event supports only %d event "
1568 "types", event_type,
1569 description_event->number_of_event_types));
1570 ev= NULL;
1571 }
1572 else
1573 {
1574 /*
1575 In some previuos versions (see comment in
1576 Format_description_log_event::Format_description_log_event(char*,...)),
1577 event types were assigned different id numbers than in the
1578 present version. In order to replicate from such versions to the
1579 present version, we must map those event type id's to our event
1580 type id's. The mapping is done with the event_type_permutation
1581 array, which was set up when the Format_description_log_event
1582 was read.
1583 */
1584 if (description_event->event_type_permutation)
1585 {
1586 uint new_event_type;
1587 if (event_type >= EVENT_TYPE_PERMUTATION_NUM)
1588 /* Safe guard for read out of bounds of event_type_permutation. */
1589 new_event_type= UNKNOWN_EVENT;
1590 else
1591 new_event_type= description_event->event_type_permutation[event_type];
1592
1593 DBUG_PRINT("info", ("converting event type %d to %d (%s)",
1594 event_type, new_event_type,
1595 get_type_str((Log_event_type)new_event_type)));
1596 event_type= new_event_type;
1597 }
1598
1599 if (alg != BINLOG_CHECKSUM_ALG_UNDEF &&
1600 (event_type == FORMAT_DESCRIPTION_EVENT ||
1601 alg != BINLOG_CHECKSUM_ALG_OFF))
1602 event_len= event_len - BINLOG_CHECKSUM_LEN;
1603
1604 switch(event_type) {
1605 case QUERY_EVENT:
1606 ev = new Query_log_event(buf, event_len, description_event, QUERY_EVENT);
1607 break;
1608 case LOAD_EVENT:
1609 ev = new Load_log_event(buf, event_len, description_event);
1610 break;
1611 case NEW_LOAD_EVENT:
1612 ev = new Load_log_event(buf, event_len, description_event);
1613 break;
1614 case ROTATE_EVENT:
1615 ev = new Rotate_log_event(buf, event_len, description_event);
1616 break;
1617 case CREATE_FILE_EVENT:
1618 ev = new Create_file_log_event(buf, event_len, description_event);
1619 break;
1620 case APPEND_BLOCK_EVENT:
1621 ev = new Append_block_log_event(buf, event_len, description_event);
1622 break;
1623 case DELETE_FILE_EVENT:
1624 ev = new Delete_file_log_event(buf, event_len, description_event);
1625 break;
1626 case EXEC_LOAD_EVENT:
1627 ev = new Execute_load_log_event(buf, event_len, description_event);
1628 break;
1629 case START_EVENT_V3: /* this is sent only by MySQL <=4.x */
1630 ev = new Start_log_event_v3(buf, event_len, description_event);
1631 break;
1632 case STOP_EVENT:
1633 ev = new Stop_log_event(buf, description_event);
1634 break;
1635 case INTVAR_EVENT:
1636 ev = new Intvar_log_event(buf, description_event);
1637 break;
1638 case XID_EVENT:
1639 ev = new Xid_log_event(buf, description_event);
1640 break;
1641 case RAND_EVENT:
1642 ev = new Rand_log_event(buf, description_event);
1643 break;
1644 case USER_VAR_EVENT:
1645 ev = new User_var_log_event(buf, event_len, description_event);
1646 break;
1647 case FORMAT_DESCRIPTION_EVENT:
1648 ev = new Format_description_log_event(buf, event_len, description_event);
1649 break;
1650 #if defined(HAVE_REPLICATION)
1651 case PRE_GA_WRITE_ROWS_EVENT:
1652 ev = new Write_rows_log_event_old(buf, event_len, description_event);
1653 break;
1654 case PRE_GA_UPDATE_ROWS_EVENT:
1655 ev = new Update_rows_log_event_old(buf, event_len, description_event);
1656 break;
1657 case PRE_GA_DELETE_ROWS_EVENT:
1658 ev = new Delete_rows_log_event_old(buf, event_len, description_event);
1659 break;
1660 case WRITE_ROWS_EVENT_V1:
1661 ev = new Write_rows_log_event(buf, event_len, description_event);
1662 break;
1663 case UPDATE_ROWS_EVENT_V1:
1664 ev = new Update_rows_log_event(buf, event_len, description_event);
1665 break;
1666 case DELETE_ROWS_EVENT_V1:
1667 ev = new Delete_rows_log_event(buf, event_len, description_event);
1668 break;
1669 case TABLE_MAP_EVENT:
1670 ev = new Table_map_log_event(buf, event_len, description_event);
1671 break;
1672 #endif
1673 case BEGIN_LOAD_QUERY_EVENT:
1674 ev = new Begin_load_query_log_event(buf, event_len, description_event);
1675 break;
1676 case EXECUTE_LOAD_QUERY_EVENT:
1677 ev= new Execute_load_query_log_event(buf, event_len, description_event);
1678 break;
1679 case INCIDENT_EVENT:
1680 ev = new Incident_log_event(buf, event_len, description_event);
1681 break;
1682 case ROWS_QUERY_LOG_EVENT:
1683 ev= new Rows_query_log_event(buf, event_len, description_event);
1684 break;
1685 case GTID_LOG_EVENT:
1686 case ANONYMOUS_GTID_LOG_EVENT:
1687 ev= new Gtid_log_event(buf, event_len, description_event);
1688 break;
1689 case PREVIOUS_GTIDS_LOG_EVENT:
1690 ev= new Previous_gtids_log_event(buf, event_len, description_event);
1691 break;
1692 #if defined(HAVE_REPLICATION)
1693 case WRITE_ROWS_EVENT:
1694 ev = new Write_rows_log_event(buf, event_len, description_event);
1695 break;
1696 case UPDATE_ROWS_EVENT:
1697 ev = new Update_rows_log_event(buf, event_len, description_event);
1698 break;
1699 case DELETE_ROWS_EVENT:
1700 ev = new Delete_rows_log_event(buf, event_len, description_event);
1701 break;
1702 #endif
1703 default:
1704 /*
1705 Create an object of Ignorable_log_event for unrecognized sub-class.
1706 So that SLAVE SQL THREAD will only update the position and continue.
1707 */
1708 if (uint2korr(buf + FLAGS_OFFSET) & LOG_EVENT_IGNORABLE_F)
1709 {
1710 ev= new Ignorable_log_event(buf, description_event);
1711 }
1712 else
1713 {
1714 DBUG_PRINT("error",("Unknown event code: %d",
1715 (int) buf[EVENT_TYPE_OFFSET]));
1716 ev= NULL;
1717 }
1718 break;
1719 }
1720 }
1721
1722 if (ev)
1723 {
1724 ev->checksum_alg= alg;
1725 if (ev->checksum_alg != BINLOG_CHECKSUM_ALG_OFF &&
1726 ev->checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF)
1727 ev->crc= uint4korr(buf + (event_len));
1728 }
1729
1730 DBUG_PRINT("read_event", ("%s(type_code: %d; event_len: %d)",
1731 ev ? ev->get_type_str() : "<unknown>",
1732 buf[EVENT_TYPE_OFFSET],
1733 event_len));
1734 /*
1735 is_valid() are small event-specific sanity tests which are
1736 important; for example there are some my_malloc() in constructors
1737 (e.g. Query_log_event::Query_log_event(char*...)); when these
1738 my_malloc() fail we can't return an error out of the constructor
1739 (because constructor is "void") ; so instead we leave the pointer we
1740 wanted to allocate (e.g. 'query') to 0 and we test it in is_valid().
1741 Same for Format_description_log_event, member 'post_header_len'.
1742
1743 SLAVE_EVENT is never used, so it should not be read ever.
1744 */
1745 if (!ev || !ev->is_valid() || (event_type == SLAVE_EVENT))
1746 {
1747 DBUG_PRINT("error",("Found invalid event in binary log"));
1748
1749 delete ev;
1750 #ifdef MYSQL_CLIENT
1751 if (!force_opt) /* then mysqlbinlog dies */
1752 {
1753 *error= "Found invalid event in binary log";
1754 DBUG_RETURN(0);
1755 }
1756 ev= new Unknown_log_event(buf, description_event);
1757 #else
1758 *error= "Found invalid event in binary log";
1759 DBUG_RETURN(0);
1760 #endif
1761 }
1762 DBUG_RETURN(ev);
1763 }
1764
1765 #ifdef MYSQL_CLIENT
1766
1767 /*
1768 Log_event::print_header()
1769 */
1770
print_header(IO_CACHE * file,PRINT_EVENT_INFO * print_event_info,bool is_more MY_ATTRIBUTE ((unused)))1771 void Log_event::print_header(IO_CACHE* file,
1772 PRINT_EVENT_INFO* print_event_info,
1773 bool is_more MY_ATTRIBUTE((unused)))
1774 {
1775 char llbuff[22];
1776 my_off_t hexdump_from= print_event_info->hexdump_from;
1777 DBUG_ENTER("Log_event::print_header");
1778
1779 my_b_printf(file, "#");
1780 print_timestamp(file, NULL);
1781 my_b_printf(file, " server id %lu end_log_pos %s ", (ulong) server_id,
1782 llstr(log_pos,llbuff));
1783
1784 /* print the checksum */
1785
1786 if (checksum_alg != BINLOG_CHECKSUM_ALG_OFF &&
1787 checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF)
1788 {
1789 char checksum_buf[BINLOG_CHECKSUM_LEN * 2 + 4]; // to fit to "0x%lx "
1790 size_t const bytes_written=
1791 my_snprintf(checksum_buf, sizeof(checksum_buf), "0x%08lx ", (ulong) crc);
1792 my_b_printf(file, "%s ", get_type(&binlog_checksum_typelib, checksum_alg));
1793 my_b_printf(file, checksum_buf, bytes_written);
1794 }
1795
1796 /* mysqlbinlog --hexdump */
1797 if (print_event_info->hexdump_from)
1798 {
1799 my_b_printf(file, "\n");
1800 uchar *ptr= (uchar*)temp_buf;
1801 my_off_t size=
1802 uint4korr(ptr + EVENT_LEN_OFFSET) - LOG_EVENT_MINIMAL_HEADER_LEN;
1803 my_off_t i;
1804
1805 /* Header len * 4 >= header len * (2 chars + space + extra space) */
1806 char *h, hex_string[49]= {0};
1807 char *c, char_string[16+1]= {0};
1808
1809 /* Pretty-print event common header if header is exactly 19 bytes */
1810 if (print_event_info->common_header_len == LOG_EVENT_MINIMAL_HEADER_LEN)
1811 {
1812 char emit_buf[256]; // Enough for storing one line
1813 my_b_printf(file, "# Position Timestamp Type Master ID "
1814 "Size Master Pos Flags \n");
1815 size_t const bytes_written=
1816 my_snprintf(emit_buf, sizeof(emit_buf),
1817 "# %8.8lx %02x %02x %02x %02x %02x "
1818 "%02x %02x %02x %02x %02x %02x %02x %02x "
1819 "%02x %02x %02x %02x %02x %02x\n",
1820 (unsigned long) hexdump_from,
1821 ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6],
1822 ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13],
1823 ptr[14], ptr[15], ptr[16], ptr[17], ptr[18]);
1824 DBUG_ASSERT(static_cast<size_t>(bytes_written) < sizeof(emit_buf));
1825 my_b_write(file, (uchar*) emit_buf, bytes_written);
1826 ptr += LOG_EVENT_MINIMAL_HEADER_LEN;
1827 hexdump_from += LOG_EVENT_MINIMAL_HEADER_LEN;
1828 }
1829
1830 /* Rest of event (without common header) */
1831 for (i= 0, c= char_string, h=hex_string;
1832 i < size;
1833 i++, ptr++)
1834 {
1835 my_snprintf(h, 4, (i % 16 <= 7) ? "%02x " : " %02x", *ptr);
1836 h += 3;
1837
1838 *c++= my_isalnum(&my_charset_bin, *ptr) ? *ptr : '.';
1839
1840 if (i % 16 == 15)
1841 {
1842 /*
1843 my_b_printf() does not support full printf() formats, so we
1844 have to do it this way.
1845
1846 TODO: Rewrite my_b_printf() to support full printf() syntax.
1847 */
1848 char emit_buf[256];
1849 size_t const bytes_written=
1850 my_snprintf(emit_buf, sizeof(emit_buf),
1851 "# %8.8lx %-48.48s |%16s|\n",
1852 (unsigned long) (hexdump_from + (i & 0xfffffff0)),
1853 hex_string, char_string);
1854 DBUG_ASSERT(static_cast<size_t>(bytes_written) < sizeof(emit_buf));
1855 my_b_write(file, (uchar*) emit_buf, bytes_written);
1856 hex_string[0]= 0;
1857 char_string[0]= 0;
1858 c= char_string;
1859 h= hex_string;
1860 }
1861 }
1862 *c= '\0';
1863 DBUG_ASSERT(hex_string[48] == 0);
1864
1865 if (hex_string[0])
1866 {
1867 char emit_buf[256];
1868 // Right-pad hex_string with spaces, up to 48 characters.
1869 memset(h, ' ', (sizeof(hex_string) -1) - (h - hex_string));
1870 size_t const bytes_written=
1871 my_snprintf(emit_buf, sizeof(emit_buf),
1872 "# %8.8lx %-48.48s |%s|\n",
1873 (unsigned long) (hexdump_from + (i & 0xfffffff0)),
1874 hex_string, char_string);
1875 DBUG_ASSERT(static_cast<size_t>(bytes_written) < sizeof(emit_buf));
1876 my_b_write(file, (uchar*) emit_buf, bytes_written);
1877 }
1878 /*
1879 need a # to prefix the rest of printouts for example those of
1880 Rows_log_event::print_helper().
1881 */
1882 my_b_write(file, reinterpret_cast<const uchar*>("# "), 2);
1883 }
1884 DBUG_VOID_RETURN;
1885 }
1886
1887
1888 /**
1889 Prints a quoted string to io cache.
1890 Control characters are displayed as hex sequence, e.g. \x00
1891
1892 @param[in] file IO cache
1893 @param[in] prt Pointer to string
1894 @param[in] length String length
1895 */
1896
1897 static void
my_b_write_quoted(IO_CACHE * file,const uchar * ptr,uint length)1898 my_b_write_quoted(IO_CACHE *file, const uchar *ptr, uint length)
1899 {
1900 const uchar *s;
1901 my_b_printf(file, "'");
1902 for (s= ptr; length > 0 ; s++, length--)
1903 {
1904 if (*s > 0x1F && *s != '\'' && *s != '\\')
1905 my_b_write(file, s, 1);
1906 else
1907 {
1908 uchar hex[10];
1909 size_t len= my_snprintf((char*) hex, sizeof(hex), "%s%02x", "\\x", *s);
1910 my_b_write(file, hex, len);
1911 }
1912 }
1913 my_b_printf(file, "'");
1914 }
1915
1916 /**
1917 Prints a bit string to io cache in format b'1010'.
1918
1919 @param[in] file IO cache
1920 @param[in] ptr Pointer to string
1921 @param[in] nbits Number of bits
1922 */
1923 static void
my_b_write_bit(IO_CACHE * file,const uchar * ptr,uint nbits)1924 my_b_write_bit(IO_CACHE *file, const uchar *ptr, uint nbits)
1925 {
1926 uint bitnum, nbits8= ((nbits + 7) / 8) * 8, skip_bits= nbits8 - nbits;
1927 my_b_printf(file, "b'");
1928 for (bitnum= skip_bits ; bitnum < nbits8; bitnum++)
1929 {
1930 int is_set= (ptr[(bitnum) / 8] >> (7 - bitnum % 8)) & 0x01;
1931 my_b_write(file, (const uchar*) (is_set ? "1" : "0"), 1);
1932 }
1933 my_b_printf(file, "'");
1934 }
1935
1936
1937 /**
1938 Prints a packed string to io cache.
1939 The string consists of length packed to 1 or 2 bytes,
1940 followed by string data itself.
1941
1942 @param[in] file IO cache
1943 @param[in] ptr Pointer to string
1944 @param[in] length String size
1945
1946 @retval - number of bytes scanned.
1947 */
1948 static size_t
my_b_write_quoted_with_length(IO_CACHE * file,const uchar * ptr,uint length)1949 my_b_write_quoted_with_length(IO_CACHE *file, const uchar *ptr, uint length)
1950 {
1951 if (length < 256)
1952 {
1953 length= *ptr;
1954 my_b_write_quoted(file, ptr + 1, length);
1955 return length + 1;
1956 }
1957 else
1958 {
1959 length= uint2korr(ptr);
1960 my_b_write_quoted(file, ptr + 2, length);
1961 return length + 2;
1962 }
1963 }
1964
1965
1966 /**
1967 Prints a 32-bit number in both signed and unsigned representation
1968
1969 @param[in] file IO cache
1970 @param[in] sl Signed number
1971 @param[in] ul Unsigned number
1972 */
1973 static void
my_b_write_sint32_and_uint32(IO_CACHE * file,int32 si,uint32 ui)1974 my_b_write_sint32_and_uint32(IO_CACHE *file, int32 si, uint32 ui)
1975 {
1976 my_b_printf(file, "%d", si);
1977 if (si < 0)
1978 my_b_printf(file, " (%u)", ui);
1979 }
1980
1981
1982 /**
1983 Print a packed value of the given SQL type into IO cache
1984
1985 @param[in] file IO cache
1986 @param[in] ptr Pointer to string
1987 @param[in] type Column type
1988 @param[in] meta Column meta information
1989 @param[out] typestr SQL type string buffer (for verbose output)
1990 @param[out] typestr_length Size of typestr
1991
1992 @retval - number of bytes scanned from ptr.
1993 */
1994 static size_t
log_event_print_value(IO_CACHE * file,const uchar * ptr,uint type,uint meta,char * typestr,size_t typestr_length)1995 log_event_print_value(IO_CACHE *file, const uchar *ptr,
1996 uint type, uint meta,
1997 char *typestr, size_t typestr_length)
1998 {
1999 uint32 length= 0;
2000
2001 if (type == MYSQL_TYPE_STRING)
2002 {
2003 if (meta >= 256)
2004 {
2005 uint byte0= meta >> 8;
2006 uint byte1= meta & 0xFF;
2007
2008 if ((byte0 & 0x30) != 0x30)
2009 {
2010 /* a long CHAR() field: see #37426 */
2011 length= byte1 | (((byte0 & 0x30) ^ 0x30) << 4);
2012 type= byte0 | 0x30;
2013 }
2014 else
2015 length = meta & 0xFF;
2016 }
2017 else
2018 length= meta;
2019 }
2020
2021 switch (type) {
2022 case MYSQL_TYPE_LONG:
2023 {
2024 int32 si= sint4korr(ptr);
2025 uint32 ui= uint4korr(ptr);
2026 my_b_write_sint32_and_uint32(file, si, ui);
2027 my_snprintf(typestr, typestr_length, "INT");
2028 return 4;
2029 }
2030
2031 case MYSQL_TYPE_TINY:
2032 {
2033 my_b_write_sint32_and_uint32(file, (int) (signed char) *ptr,
2034 (uint) (unsigned char) *ptr);
2035 my_snprintf(typestr, typestr_length, "TINYINT");
2036 return 1;
2037 }
2038
2039 case MYSQL_TYPE_SHORT:
2040 {
2041 int32 si= (int32) sint2korr(ptr);
2042 uint32 ui= (uint32) uint2korr(ptr);
2043 my_b_write_sint32_and_uint32(file, si, ui);
2044 my_snprintf(typestr, typestr_length, "SHORTINT");
2045 return 2;
2046 }
2047
2048 case MYSQL_TYPE_INT24:
2049 {
2050 int32 si= sint3korr(ptr);
2051 uint32 ui= uint3korr(ptr);
2052 my_b_write_sint32_and_uint32(file, si, ui);
2053 my_snprintf(typestr, typestr_length, "MEDIUMINT");
2054 return 3;
2055 }
2056
2057 case MYSQL_TYPE_LONGLONG:
2058 {
2059 char tmp[64];
2060 longlong si= sint8korr(ptr);
2061 longlong10_to_str(si, tmp, -10);
2062 my_b_printf(file, "%s", tmp);
2063 if (si < 0)
2064 {
2065 ulonglong ui= uint8korr(ptr);
2066 longlong10_to_str((longlong) ui, tmp, 10);
2067 my_b_printf(file, " (%s)", tmp);
2068 }
2069 my_snprintf(typestr, typestr_length, "LONGINT");
2070 return 8;
2071 }
2072
2073 case MYSQL_TYPE_NEWDECIMAL:
2074 {
2075 uint precision= meta >> 8;
2076 uint decimals= meta & 0xFF;
2077 uint bin_size= my_decimal_get_binary_size(precision, decimals);
2078 my_decimal dec;
2079 binary2my_decimal(E_DEC_FATAL_ERROR, (uchar*) ptr, &dec,
2080 precision, decimals);
2081 int len= DECIMAL_MAX_STR_LENGTH;
2082 char buff[DECIMAL_MAX_STR_LENGTH + 1];
2083 decimal2string(&dec,buff,&len, 0, 0, 0);
2084 my_b_printf(file, "%s", buff);
2085 my_snprintf(typestr, typestr_length, "DECIMAL(%d,%d)",
2086 precision, decimals);
2087 return bin_size;
2088 }
2089
2090 case MYSQL_TYPE_FLOAT:
2091 {
2092 float fl;
2093 float4get(fl, ptr);
2094 char tmp[320];
2095 sprintf(tmp, "%-20g", (double) fl);
2096 my_b_printf(file, "%s", tmp); /* my_snprintf doesn't support %-20g */
2097 my_snprintf(typestr, typestr_length, "FLOAT");
2098 return 4;
2099 }
2100
2101 case MYSQL_TYPE_DOUBLE:
2102 {
2103 double dbl;
2104 float8get(dbl, ptr);
2105 char tmp[320];
2106 sprintf(tmp, "%-.20g", dbl); /* my_snprintf doesn't support %-20g */
2107 my_b_printf(file, "%s", tmp);
2108 strcpy(typestr, "DOUBLE");
2109 return 8;
2110 }
2111
2112 case MYSQL_TYPE_BIT:
2113 {
2114 /* Meta-data: bit_len, bytes_in_rec, 2 bytes */
2115 uint nbits= ((meta >> 8) * 8) + (meta & 0xFF);
2116 length= (nbits + 7) / 8;
2117 my_b_write_bit(file, ptr, nbits);
2118 my_snprintf(typestr, typestr_length, "BIT(%d)", nbits);
2119 return length;
2120 }
2121
2122 case MYSQL_TYPE_TIMESTAMP:
2123 {
2124 uint32 i32= uint4korr(ptr);
2125 my_b_printf(file, "%d", i32);
2126 my_snprintf(typestr, typestr_length, "TIMESTAMP");
2127 return 4;
2128 }
2129
2130 case MYSQL_TYPE_TIMESTAMP2:
2131 {
2132 char buf[MAX_DATE_STRING_REP_LENGTH];
2133 struct timeval tm;
2134 my_timestamp_from_binary(&tm, ptr, meta);
2135 int buflen= my_timeval_to_str(&tm, buf, meta);
2136 my_b_write(file, buf, buflen);
2137 my_snprintf(typestr, typestr_length, "TIMESTAMP(%d)", meta);
2138 return my_timestamp_binary_length(meta);
2139 }
2140
2141 case MYSQL_TYPE_DATETIME:
2142 {
2143 size_t d, t;
2144 uint64 i64= uint8korr(ptr); /* YYYYMMDDhhmmss */
2145 d= i64 / 1000000;
2146 t= i64 % 1000000;
2147 my_b_printf(file, "%04d-%02d-%02d %02d:%02d:%02d",
2148 static_cast<int>(d / 10000),
2149 static_cast<int>(d % 10000) / 100,
2150 static_cast<int>(d % 100),
2151 static_cast<int>(t / 10000),
2152 static_cast<int>(t % 10000) / 100,
2153 static_cast<int>(t % 100));
2154 my_snprintf(typestr, typestr_length, "DATETIME");
2155 return 8;
2156 }
2157
2158 case MYSQL_TYPE_DATETIME2:
2159 {
2160 char buf[MAX_DATE_STRING_REP_LENGTH];
2161 MYSQL_TIME ltime;
2162 longlong packed= my_datetime_packed_from_binary(ptr, meta);
2163 TIME_from_longlong_datetime_packed(<ime, packed);
2164 int buflen= my_datetime_to_str(<ime, buf, meta);
2165 my_b_write_quoted(file, (uchar *) buf, buflen);
2166 my_snprintf(typestr, typestr_length, "DATETIME(%d)", meta);
2167 return my_datetime_binary_length(meta);
2168 }
2169
2170 case MYSQL_TYPE_TIME:
2171 {
2172 uint32 i32= uint3korr(ptr);
2173 my_b_printf(file, "'%02d:%02d:%02d'",
2174 i32 / 10000, (i32 % 10000) / 100, i32 % 100);
2175 my_snprintf(typestr, typestr_length, "TIME");
2176 return 3;
2177 }
2178
2179 case MYSQL_TYPE_TIME2:
2180 {
2181 char buf[MAX_DATE_STRING_REP_LENGTH];
2182 MYSQL_TIME ltime;
2183 longlong packed= my_time_packed_from_binary(ptr, meta);
2184 TIME_from_longlong_time_packed(<ime, packed);
2185 int buflen= my_time_to_str(<ime, buf, meta);
2186 my_b_write_quoted(file, (uchar *) buf, buflen);
2187 my_snprintf(typestr, typestr_length, "TIME(%d)", meta);
2188 return my_time_binary_length(meta);
2189 }
2190
2191 case MYSQL_TYPE_NEWDATE:
2192 {
2193 uint32 tmp= uint3korr(ptr);
2194 int part;
2195 char buf[11];
2196 char *pos= &buf[10]; // start from '\0' to the beginning
2197
2198 /* Copied from field.cc */
2199 *pos--=0; // End NULL
2200 part=(int) (tmp & 31);
2201 *pos--= (char) ('0'+part%10);
2202 *pos--= (char) ('0'+part/10);
2203 *pos--= ':';
2204 part=(int) (tmp >> 5 & 15);
2205 *pos--= (char) ('0'+part%10);
2206 *pos--= (char) ('0'+part/10);
2207 *pos--= ':';
2208 part=(int) (tmp >> 9);
2209 *pos--= (char) ('0'+part%10); part/=10;
2210 *pos--= (char) ('0'+part%10); part/=10;
2211 *pos--= (char) ('0'+part%10); part/=10;
2212 *pos= (char) ('0'+part);
2213 my_b_printf(file , "'%s'", buf);
2214 my_snprintf(typestr, typestr_length, "DATE");
2215 return 3;
2216 }
2217
2218 case MYSQL_TYPE_YEAR:
2219 {
2220 uint32 i32= *ptr;
2221 my_b_printf(file, "%04d", i32+ 1900);
2222 my_snprintf(typestr, typestr_length, "YEAR");
2223 return 1;
2224 }
2225
2226 case MYSQL_TYPE_ENUM:
2227 switch (meta & 0xFF) {
2228 case 1:
2229 my_b_printf(file, "%d", (int) *ptr);
2230 my_snprintf(typestr, typestr_length, "ENUM(1 byte)");
2231 return 1;
2232 case 2:
2233 {
2234 int32 i32= uint2korr(ptr);
2235 my_b_printf(file, "%d", i32);
2236 my_snprintf(typestr, typestr_length, "ENUM(2 bytes)");
2237 return 2;
2238 }
2239 default:
2240 my_b_printf(file, "!! Unknown ENUM packlen=%d", meta & 0xFF);
2241 return 0;
2242 }
2243 break;
2244
2245 case MYSQL_TYPE_SET:
2246 my_b_write_bit(file, ptr , (meta & 0xFF) * 8);
2247 my_snprintf(typestr, typestr_length, "SET(%d bytes)", meta & 0xFF);
2248 return meta & 0xFF;
2249
2250 case MYSQL_TYPE_BLOB:
2251 switch (meta) {
2252 case 1:
2253 length= *ptr;
2254 my_b_write_quoted(file, ptr + 1, length);
2255 my_snprintf(typestr, typestr_length, "TINYBLOB/TINYTEXT");
2256 return length + 1;
2257 case 2:
2258 length= uint2korr(ptr);
2259 my_b_write_quoted(file, ptr + 2, length);
2260 my_snprintf(typestr, typestr_length, "BLOB/TEXT");
2261 return length + 2;
2262 case 3:
2263 length= uint3korr(ptr);
2264 my_b_write_quoted(file, ptr + 3, length);
2265 my_snprintf(typestr, typestr_length, "MEDIUMBLOB/MEDIUMTEXT");
2266 return length + 3;
2267 case 4:
2268 length= uint4korr(ptr);
2269 my_b_write_quoted(file, ptr + 4, length);
2270 my_snprintf(typestr, typestr_length, "LONGBLOB/LONGTEXT");
2271 return length + 4;
2272 default:
2273 my_b_printf(file, "!! Unknown BLOB packlen=%d", length);
2274 return 0;
2275 }
2276
2277 case MYSQL_TYPE_VARCHAR:
2278 case MYSQL_TYPE_VAR_STRING:
2279 length= meta;
2280 my_snprintf(typestr, typestr_length, "VARSTRING(%d)", length);
2281 return my_b_write_quoted_with_length(file, ptr, length);
2282
2283 case MYSQL_TYPE_STRING:
2284 my_snprintf(typestr, typestr_length, "STRING(%d)", length);
2285 return my_b_write_quoted_with_length(file, ptr, length);
2286
2287 default:
2288 {
2289 char tmp[5];
2290 my_snprintf(tmp, sizeof(tmp), "%04x", meta);
2291 my_b_printf(file,
2292 "!! Don't know how to handle column type=%d meta=%d (%s)",
2293 type, meta, tmp);
2294 }
2295 break;
2296 }
2297 *typestr= 0;
2298 return 0;
2299 }
2300
2301
2302 /**
2303 Print a packed row into IO cache
2304
2305 @param[in] file IO cache
2306 @param[in] td Table definition
2307 @param[in] print_event_into Print parameters
2308 @param[in] cols_bitmap Column bitmaps.
2309 @param[in] value Pointer to packed row
2310 @param[in] prefix Row's SQL clause ("SET", "WHERE", etc)
2311
2312 @retval - number of bytes scanned.
2313 */
2314
2315
2316 size_t
print_verbose_one_row(IO_CACHE * file,table_def * td,PRINT_EVENT_INFO * print_event_info,MY_BITMAP * cols_bitmap,const uchar * value,const uchar * prefix)2317 Rows_log_event::print_verbose_one_row(IO_CACHE *file, table_def *td,
2318 PRINT_EVENT_INFO *print_event_info,
2319 MY_BITMAP *cols_bitmap,
2320 const uchar *value, const uchar *prefix)
2321 {
2322 const uchar *value0= value;
2323 const uchar *null_bits= value;
2324 uint null_bit_index= 0;
2325 char typestr[64]= "";
2326
2327 /*
2328 Skip metadata bytes which gives the information about nullabity of master
2329 columns. Master writes one bit for each affected column.
2330 */
2331 value+= (bitmap_bits_set(cols_bitmap) + 7) / 8;
2332
2333 my_b_printf(file, "%s", prefix);
2334
2335 for (size_t i= 0; i < td->size(); i ++)
2336 {
2337 int is_null= (null_bits[null_bit_index / 8]
2338 >> (null_bit_index % 8)) & 0x01;
2339
2340 if (bitmap_is_set(cols_bitmap, i) == 0)
2341 continue;
2342
2343 if (is_null)
2344 {
2345 my_b_printf(file, "### @%d=NULL", static_cast<int>(i + 1));
2346 }
2347 else
2348 {
2349 my_b_printf(file, "### @%d=", static_cast<int>(i + 1));
2350 size_t fsize= td->calc_field_size((uint)i, (uchar*) value);
2351 if (value + fsize > m_rows_end)
2352 {
2353 my_b_printf(file, "***Corrupted replication event was detected."
2354 " Not printing the value***\n");
2355 value+= fsize;
2356 return 0;
2357 }
2358 size_t size= log_event_print_value(file, value,
2359 td->type(i), td->field_metadata(i),
2360 typestr, sizeof(typestr));
2361 if (!size)
2362 return 0;
2363
2364 value+= size;
2365 }
2366
2367 if (print_event_info->verbose > 1)
2368 {
2369 my_b_printf(file, " /* ");
2370
2371 if (typestr[0])
2372 my_b_printf(file, "%s ", typestr);
2373 else
2374 my_b_printf(file, "type=%d ", td->type(i));
2375
2376 my_b_printf(file, "meta=%d nullable=%d is_null=%d ",
2377 td->field_metadata(i),
2378 td->maybe_null(i), is_null);
2379 my_b_printf(file, "*/");
2380 }
2381
2382 my_b_printf(file, "\n");
2383
2384 null_bit_index++;
2385 }
2386 return value - value0;
2387 }
2388
2389
2390 /**
2391 Print a row event into IO cache in human readable form (in SQL format)
2392
2393 @param[in] file IO cache
2394 @param[in] print_event_into Print parameters
2395 */
print_verbose(IO_CACHE * file,PRINT_EVENT_INFO * print_event_info)2396 void Rows_log_event::print_verbose(IO_CACHE *file,
2397 PRINT_EVENT_INFO *print_event_info)
2398 {
2399 // Quoted length of the identifier can be twice the original length
2400 char quoted_db[1 + NAME_LEN * 2 + 2];
2401 char quoted_table[1 + NAME_LEN * 2 + 2];
2402 int quoted_db_len, quoted_table_len;
2403 Table_map_log_event *map;
2404 table_def *td;
2405 const char *sql_command, *sql_clause1, *sql_clause2;
2406 Log_event_type general_type_code= get_general_type_code();
2407
2408 if (m_extra_row_data)
2409 {
2410 uint8 extra_data_len= m_extra_row_data[EXTRA_ROW_INFO_LEN_OFFSET];
2411 uint8 extra_payload_len= extra_data_len - EXTRA_ROW_INFO_HDR_BYTES;
2412 assert(extra_data_len >= EXTRA_ROW_INFO_HDR_BYTES);
2413
2414 my_b_printf(file, "### Extra row data format: %u, len: %u :",
2415 m_extra_row_data[EXTRA_ROW_INFO_FORMAT_OFFSET],
2416 extra_payload_len);
2417 if (extra_payload_len)
2418 {
2419 /*
2420 Buffer for hex view of string, including '0x' prefix,
2421 2 hex chars / byte and trailing 0
2422 */
2423 const int buff_len= 2 + (256 * 2) + 1;
2424 char buff[buff_len];
2425 str_to_hex(buff, (const char*) &m_extra_row_data[EXTRA_ROW_INFO_HDR_BYTES],
2426 extra_payload_len);
2427 my_b_printf(file, "%s", buff);
2428 }
2429 my_b_printf(file, "\n");
2430 }
2431
2432 switch (general_type_code) {
2433 case WRITE_ROWS_EVENT:
2434 sql_command= "INSERT INTO";
2435 sql_clause1= "### SET\n";
2436 sql_clause2= NULL;
2437 break;
2438 case DELETE_ROWS_EVENT:
2439 sql_command= "DELETE FROM";
2440 sql_clause1= "### WHERE\n";
2441 sql_clause2= NULL;
2442 break;
2443 case UPDATE_ROWS_EVENT:
2444 sql_command= "UPDATE";
2445 sql_clause1= "### WHERE\n";
2446 sql_clause2= "### SET\n";
2447 break;
2448 default:
2449 sql_command= sql_clause1= sql_clause2= NULL;
2450 DBUG_ASSERT(0); /* Not possible */
2451 }
2452
2453 if (!(map= print_event_info->m_table_map.get_table(m_table_id)) ||
2454 !(td= map->create_table_def()))
2455 {
2456 char llbuff[22];
2457 my_b_printf(file, "### Row event for unknown table #%s",
2458 llstr(m_table_id, llbuff));
2459 return;
2460 }
2461
2462 /* If the write rows event contained no values for the AI */
2463 if (((general_type_code == WRITE_ROWS_EVENT) && (m_rows_buf==m_rows_end)))
2464 {
2465 my_b_printf(file, "### INSERT INTO `%s`.`%s` VALUES ()\n",
2466 map->get_db_name(), map->get_table_name());
2467 goto end;
2468 }
2469
2470 for (const uchar *value= m_rows_buf; value < m_rows_end; )
2471 {
2472 size_t length;
2473 #ifdef MYSQL_SERVER
2474 quoted_db_len= my_strmov_quoted_identifier(this->thd, (char *) quoted_db,
2475 map->get_db_name(), 0);
2476 quoted_table_len= my_strmov_quoted_identifier(this->thd,
2477 (char *) quoted_table,
2478 map->get_table_name(), 0);
2479 #else
2480 quoted_db_len= my_strmov_quoted_identifier((char *) quoted_db,
2481 map->get_db_name());
2482 quoted_table_len= my_strmov_quoted_identifier((char *) quoted_table,
2483 map->get_table_name());
2484 #endif
2485 quoted_db[quoted_db_len]= '\0';
2486 quoted_table[quoted_table_len]= '\0';
2487 my_b_printf(file, "### %s %s.%s\n",
2488 sql_command,
2489 quoted_db, quoted_table);
2490 /* Print the first image */
2491 if (!(length= print_verbose_one_row(file, td, print_event_info,
2492 &m_cols, value,
2493 (const uchar*) sql_clause1)))
2494 goto end;
2495 value+= length;
2496
2497 /* Print the second image (for UPDATE only) */
2498 if (sql_clause2)
2499 {
2500 if (!(length= print_verbose_one_row(file, td, print_event_info,
2501 &m_cols_ai, value,
2502 (const uchar*) sql_clause2)))
2503 goto end;
2504 value+= length;
2505 }
2506 }
2507
2508 end:
2509 delete td;
2510 }
2511
2512 #ifdef MYSQL_CLIENT
free_table_map_log_event(Table_map_log_event * event)2513 void free_table_map_log_event(Table_map_log_event *event)
2514 {
2515 delete event;
2516 }
2517 #endif
2518
print_base64(IO_CACHE * file,PRINT_EVENT_INFO * print_event_info,bool more)2519 void Log_event::print_base64(IO_CACHE* file,
2520 PRINT_EVENT_INFO* print_event_info,
2521 bool more)
2522 {
2523 const uchar *ptr= (const uchar *)temp_buf;
2524 uint32 size= uint4korr(ptr + EVENT_LEN_OFFSET);
2525 DBUG_ENTER("Log_event::print_base64");
2526
2527 uint64 const tmp_str_sz= base64_needed_encoded_length((uint64) size);
2528 char *const tmp_str= (char *) my_malloc(tmp_str_sz, MYF(MY_WME));
2529 if (!tmp_str) {
2530 fprintf(stderr, "\nError: Out of memory. "
2531 "Could not print correct binlog event.\n");
2532 DBUG_VOID_RETURN;
2533 }
2534
2535 if (base64_encode(ptr, (size_t) size, tmp_str))
2536 {
2537 DBUG_ASSERT(0);
2538 }
2539
2540 if (print_event_info->base64_output_mode != BASE64_OUTPUT_DECODE_ROWS)
2541 {
2542 if (my_b_tell(file) == 0)
2543 my_b_printf(file, "\nBINLOG '\n");
2544
2545 my_b_printf(file, "%s\n", tmp_str);
2546
2547 if (!more)
2548 my_b_printf(file, "'%s\n", print_event_info->delimiter);
2549 }
2550
2551 if (print_event_info->verbose)
2552 {
2553 Rows_log_event *ev= NULL;
2554 Log_event_type et= (Log_event_type) ptr[EVENT_TYPE_OFFSET];
2555
2556 if (checksum_alg != BINLOG_CHECKSUM_ALG_UNDEF &&
2557 checksum_alg != BINLOG_CHECKSUM_ALG_OFF)
2558 size-= BINLOG_CHECKSUM_LEN; // checksum is displayed through the header
2559
2560 switch(et)
2561 {
2562 case TABLE_MAP_EVENT:
2563 {
2564 Table_map_log_event *map;
2565 map= new Table_map_log_event((const char*) ptr, size,
2566 glob_description_event);
2567 print_event_info->m_table_map.set_table(map->get_table_id(), map);
2568 break;
2569 }
2570 case WRITE_ROWS_EVENT:
2571 case WRITE_ROWS_EVENT_V1:
2572 {
2573 ev= new Write_rows_log_event((const char*) ptr, size,
2574 glob_description_event);
2575 break;
2576 }
2577 case DELETE_ROWS_EVENT:
2578 case DELETE_ROWS_EVENT_V1:
2579 {
2580 ev= new Delete_rows_log_event((const char*) ptr, size,
2581 glob_description_event);
2582 break;
2583 }
2584 case UPDATE_ROWS_EVENT:
2585 case UPDATE_ROWS_EVENT_V1:
2586 {
2587 ev= new Update_rows_log_event((const char*) ptr, size,
2588 glob_description_event);
2589 break;
2590 }
2591 default:
2592 break;
2593 }
2594
2595 if (ev)
2596 {
2597 ev->print_verbose(file, print_event_info);
2598 delete ev;
2599 }
2600 }
2601
2602 my_free(tmp_str);
2603 DBUG_VOID_RETURN;
2604 }
2605
2606
2607 /*
2608 Log_event::print_timestamp()
2609 */
2610
print_timestamp(IO_CACHE * file,time_t * ts)2611 void Log_event::print_timestamp(IO_CACHE* file, time_t *ts)
2612 {
2613 struct tm *res;
2614 /*
2615 In some Windows versions timeval.tv_sec is defined as "long",
2616 not as "time_t" and can be of a different size.
2617 Let's use a temporary time_t variable to execute localtime()
2618 with a correct argument type.
2619 */
2620 time_t ts_tmp= ts ? *ts : (ulong)when.tv_sec;
2621 DBUG_ENTER("Log_event::print_timestamp");
2622 struct tm tm_tmp;
2623 localtime_r(&ts_tmp, (res= &tm_tmp));
2624 my_b_printf(file,"%02d%02d%02d %2d:%02d:%02d",
2625 res->tm_year % 100,
2626 res->tm_mon+1,
2627 res->tm_mday,
2628 res->tm_hour,
2629 res->tm_min,
2630 res->tm_sec);
2631 DBUG_VOID_RETURN;
2632 }
2633
2634 #endif /* MYSQL_CLIENT */
2635
2636
2637 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
2638 inline Log_event::enum_skip_reason
continue_group(Relay_log_info * rli)2639 Log_event::continue_group(Relay_log_info *rli)
2640 {
2641 if (rli->slave_skip_counter == 1)
2642 return Log_event::EVENT_SKIP_IGNORE;
2643 return Log_event::do_shall_skip(rli);
2644 }
2645
2646 /**
2647 @param end_group_sets_max_dbs when true the group terminal event
2648 can carry partition info, see a note below.
2649 @return true in cases the current event
2650 carries partition data,
2651 false otherwise
2652
2653 @note Some events combination may force to adjust partition info.
2654 In particular BEGIN, BEGIN_LOAD_QUERY_EVENT, COMMIT
2655 where none of the events holds partitioning data
2656 causes the sequential applying of the group through
2657 assigning OVER_MAX_DBS_IN_EVENT_MTS to mts_accessed_dbs
2658 of COMMIT query event.
2659 */
contains_partition_info(bool end_group_sets_max_dbs)2660 bool Log_event::contains_partition_info(bool end_group_sets_max_dbs)
2661 {
2662 bool res;
2663
2664 switch (get_type_code()) {
2665 case TABLE_MAP_EVENT:
2666 case EXECUTE_LOAD_QUERY_EVENT:
2667 res= true;
2668
2669 break;
2670
2671 case QUERY_EVENT:
2672 if (ends_group() && end_group_sets_max_dbs)
2673 {
2674 res= true;
2675 static_cast<Query_log_event*>(this)->mts_accessed_dbs=
2676 OVER_MAX_DBS_IN_EVENT_MTS;
2677 }
2678 else
2679 res= (!ends_group() && !starts_group()) ? true : false;
2680
2681 break;
2682
2683 default:
2684 res= false;
2685 }
2686
2687 return res;
2688 }
2689
2690 /**
2691 The method maps the event to a Worker and return a pointer to it.
2692 As a part of the group, an event belongs to one of the following types:
2693
2694 B - beginning of a group of events (BEGIN query_log_event)
2695 g - mini-group representative event containing the partition info
2696 (any Table_map, a Query_log_event)
2697 p - a mini-group internal event that *p*receeding its g-parent
2698 (int_, rand_, user_ var:s)
2699 r - a mini-group internal "regular" event that follows its g-parent
2700 (Delete, Update, Write -rows)
2701 T - terminator of the group (XID, COMMIT, ROLLBACK, auto-commit query)
2702
2703 Only the first g-event computes the assigned Worker which once
2704 is determined remains to be for the rest of the group.
2705 That is the g-event solely carries partitioning info.
2706 For B-event the assigned Worker is NULL to indicate Coordinator
2707 has not yet decided. The same applies to p-event.
2708
2709 Notice, these is a special group consisting of optionally multiple p-events
2710 terminating with a g-event.
2711 Such case is caused by old master binlog and a few corner-cases of
2712 the current master version (todo: to fix).
2713
2714 In case of the event accesses more than OVER_MAX_DBS the method
2715 has to ensure sure previously assigned groups to all other workers are
2716 done.
2717
2718
2719 @note The function updates GAQ queue directly, updates APH hash
2720 plus relocates some temporary tables from Coordinator's list into
2721 involved entries of APH through @c map_db_to_worker.
2722 There's few memory allocations commented where to be freed.
2723
2724 @return a pointer to the Worker struct or NULL.
2725 */
2726
get_slave_worker(Relay_log_info * rli)2727 Slave_worker *Log_event::get_slave_worker(Relay_log_info *rli)
2728 {
2729 Slave_job_group group, *ptr_group= NULL;
2730 bool is_s_event;
2731 Slave_worker *ret_worker= NULL;
2732 char llbuff[22];
2733 #ifndef DBUG_OFF
2734 THD *thd= rli->info_thd;
2735 #endif
2736 Slave_committed_queue *gaq= rli->gaq;
2737
2738 /* checking partioning properties and perform corresponding actions */
2739
2740 // Beginning of a group designated explicitly with BEGIN or GTID
2741 if ((is_s_event= starts_group()) || is_gtid_event(this) ||
2742 // or DDL:s or autocommit queries possibly associated with own p-events
2743 (!rli->curr_group_seen_begin && !rli->curr_group_seen_gtid &&
2744 /*
2745 the following is a special case of B-free still multi-event group like
2746 { p_1,p_2,...,p_k, g }.
2747 In that case either GAQ is empty (the very first group is being
2748 assigned) or the last assigned group index points at one of
2749 mapped-to-a-worker.
2750 */
2751 (gaq->empty() ||
2752 gaq->get_job_group(rli->gaq->assigned_group_index)->
2753 worker_id != MTS_WORKER_UNDEF)))
2754 {
2755 if (!rli->curr_group_seen_gtid && !rli->curr_group_seen_begin)
2756 {
2757 ulong gaq_idx MY_ATTRIBUTE((unused));
2758 rli->mts_groups_assigned++;
2759
2760 rli->curr_group_isolated= FALSE;
2761 group.reset(log_pos, rli->mts_groups_assigned);
2762 // the last occupied GAQ's array index
2763 gaq_idx= gaq->assigned_group_index= gaq->en_queue((void *) &group);
2764
2765 DBUG_ASSERT(gaq_idx != MTS_WORKER_UNDEF && gaq_idx < gaq->size);
2766 DBUG_ASSERT(gaq->get_job_group(rli->gaq->assigned_group_index)->
2767 group_relay_log_name == NULL);
2768 DBUG_ASSERT(gaq_idx != MTS_WORKER_UNDEF); // gaq must have room
2769 DBUG_ASSERT(rli->last_assigned_worker == NULL);
2770
2771 if (is_s_event || is_gtid_event(this))
2772 {
2773 Log_event *ptr_curr_ev= this;
2774 // B-event is appended to the Deferred Array associated with GCAP
2775 insert_dynamic(&rli->curr_group_da,
2776 (uchar*) &ptr_curr_ev);
2777
2778 DBUG_ASSERT(rli->curr_group_da.elements == 1);
2779
2780 if (starts_group())
2781 {
2782 // mark the current group as started with explicit B-event
2783 rli->mts_end_group_sets_max_dbs= true;
2784 rli->curr_group_seen_begin= true;
2785 }
2786
2787 if (is_gtid_event(this))
2788 // mark the current group as started with explicit Gtid-event
2789 rli->curr_group_seen_gtid= true;
2790
2791 return ret_worker;
2792 }
2793 }
2794 else
2795 {
2796 Log_event *ptr_curr_ev= this;
2797 // B-event is appended to the Deferred Array associated with GCAP
2798 insert_dynamic(&rli->curr_group_da, (uchar*) &ptr_curr_ev);
2799 rli->curr_group_seen_begin= true;
2800 rli->mts_end_group_sets_max_dbs= true;
2801 DBUG_ASSERT(rli->curr_group_da.elements == 2);
2802 DBUG_ASSERT(starts_group());
2803 return ret_worker;
2804 }
2805 }
2806
2807 // mini-group representative
2808
2809 if (contains_partition_info(rli->mts_end_group_sets_max_dbs))
2810 {
2811 int i= 0;
2812 Mts_db_names mts_dbs;
2813
2814 get_mts_dbs(&mts_dbs);
2815 /*
2816 Bug 12982188 - MTS: SBR ABORTS WITH ERROR 1742 ON LOAD DATA
2817 Logging on master can create a group with no events holding
2818 the partition info.
2819 The following assert proves there's the only reason
2820 for such group.
2821 */
2822 DBUG_ASSERT(!ends_group() ||
2823 /*
2824 This is an empty group being processed due to gtids.
2825 */
2826 (rli->curr_group_seen_begin && rli->curr_group_seen_gtid &&
2827 ends_group()) ||
2828 (rli->mts_end_group_sets_max_dbs &&
2829 ((rli->curr_group_da.elements == 3 && rli->curr_group_seen_gtid) ||
2830 (rli->curr_group_da.elements == 2 && !rli->curr_group_seen_gtid)) &&
2831 ((*(Log_event **)
2832 dynamic_array_ptr(&rli->curr_group_da,
2833 rli->curr_group_da.elements - 1))->
2834 get_type_code() == BEGIN_LOAD_QUERY_EVENT)));
2835
2836 // partioning info is found which drops the flag
2837 rli->mts_end_group_sets_max_dbs= false;
2838 ret_worker= rli->last_assigned_worker;
2839 if (mts_dbs.num == OVER_MAX_DBS_IN_EVENT_MTS)
2840 {
2841 // Worker with id 0 to handle serial execution
2842 if (!ret_worker)
2843 ret_worker= *(Slave_worker**) dynamic_array_ptr(&rli->workers, 0);
2844 // No need to know a possible error out of synchronization call.
2845 (void) wait_for_workers_to_finish(rli, ret_worker);
2846 /*
2847 this marking is transferred further into T-event of the current group.
2848 */
2849 rli->curr_group_isolated= TRUE;
2850 }
2851
2852 /* One run of the loop in the case of over-max-db:s */
2853 for (i= 0; i < ((mts_dbs.num != OVER_MAX_DBS_IN_EVENT_MTS) ? mts_dbs.num : 1);
2854 i++)
2855 {
2856 /*
2857 The over max db:s case handled through passing to map_db_to_worker
2858 such "all" db as encoded as the "" empty string.
2859 Note, the empty string is allocated in a large buffer
2860 to satisfy hashcmp() implementation.
2861 */
2862 const char all_db[NAME_LEN]= {0};
2863 if (!(ret_worker=
2864 map_db_to_worker(mts_dbs.num == OVER_MAX_DBS_IN_EVENT_MTS ?
2865 all_db : mts_dbs.name[i], rli,
2866 &mts_assigned_partitions[i],
2867 /*
2868 todo: optimize it. Although pure
2869 rows- event load in insensetive to the flag value
2870 */
2871 TRUE,
2872 ret_worker)))
2873 {
2874 llstr(rli->get_event_relay_log_pos(), llbuff);
2875 my_error(ER_MTS_CANT_PARALLEL, MYF(0),
2876 get_type_str(), rli->get_event_relay_log_name(), llbuff,
2877 "could not distribute the event to a Worker");
2878 return ret_worker;
2879 }
2880 // all temporary tables are transferred from Coordinator in over-max case
2881 DBUG_ASSERT(mts_dbs.num != OVER_MAX_DBS_IN_EVENT_MTS || !thd->temporary_tables);
2882 DBUG_ASSERT(!strcmp(mts_assigned_partitions[i]->db,
2883 mts_dbs.num != OVER_MAX_DBS_IN_EVENT_MTS ?
2884 mts_dbs.name[i] : all_db));
2885 DBUG_ASSERT(ret_worker == mts_assigned_partitions[i]->worker);
2886 DBUG_ASSERT(mts_assigned_partitions[i]->usage >= 0);
2887 }
2888
2889 if ((ptr_group= gaq->get_job_group(rli->gaq->assigned_group_index))->
2890 worker_id == MTS_WORKER_UNDEF)
2891 {
2892 ptr_group->worker_id= ret_worker->id;
2893
2894 DBUG_ASSERT(ptr_group->group_relay_log_name == NULL);
2895 }
2896
2897 DBUG_ASSERT(i == mts_dbs.num || mts_dbs.num == OVER_MAX_DBS_IN_EVENT_MTS);
2898 }
2899 else
2900 {
2901 // a mini-group internal "regular" event
2902 if (rli->last_assigned_worker)
2903 {
2904 ret_worker= rli->last_assigned_worker;
2905
2906 DBUG_ASSERT(rli->curr_group_assigned_parts.elements > 0 ||
2907 ret_worker->id == 0);
2908 }
2909 else // int_, rand_, user_ var:s, load-data events
2910 {
2911 Log_event *ptr_curr_ev= this;
2912
2913 if (!(get_type_code() == INTVAR_EVENT ||
2914 get_type_code() == RAND_EVENT ||
2915 get_type_code() == USER_VAR_EVENT ||
2916 get_type_code() == BEGIN_LOAD_QUERY_EVENT ||
2917 get_type_code() == APPEND_BLOCK_EVENT ||
2918 is_ignorable_event()))
2919 {
2920 DBUG_ASSERT(!ret_worker);
2921
2922 llstr(rli->get_event_relay_log_pos(), llbuff);
2923 my_error(ER_MTS_CANT_PARALLEL, MYF(0),
2924 get_type_str(), rli->get_event_relay_log_name(), llbuff,
2925 "the event is a part of a group that is unsupported in "
2926 "the parallel execution mode");
2927
2928 return ret_worker;
2929 }
2930
2931 insert_dynamic(&rli->curr_group_da, (uchar*) &ptr_curr_ev);
2932
2933 DBUG_ASSERT(!ret_worker);
2934 return ret_worker;
2935 }
2936 }
2937
2938 DBUG_ASSERT(ret_worker);
2939
2940 /*
2941 Preparing event physical coordinates info for Worker before any
2942 event got scheduled so when Worker error-stopped at the first
2943 event it would be aware of where exactly in the event stream.
2944 */
2945 if (!ret_worker->master_log_change_notified)
2946 {
2947 if (!ptr_group)
2948 ptr_group= gaq->get_job_group(rli->gaq->assigned_group_index);
2949 ptr_group->group_master_log_name=
2950 my_strdup(rli->get_group_master_log_name(), MYF(MY_WME));
2951 ret_worker->master_log_change_notified= true;
2952
2953 DBUG_ASSERT(!ptr_group->notified);
2954 #ifndef DBUG_OFF
2955 ptr_group->notified= true;
2956 #endif
2957 }
2958
2959 // T-event: Commit, Xid, a DDL query or dml query of B-less group.
2960 if (ends_group() || !rli->curr_group_seen_begin)
2961 {
2962 rli->mts_group_status= Relay_log_info::MTS_END_GROUP;
2963 if (rli->curr_group_isolated)
2964 set_mts_isolate_group();
2965 if (!ptr_group)
2966 ptr_group= gaq->get_job_group(rli->gaq->assigned_group_index);
2967
2968 DBUG_ASSERT(ret_worker != NULL);
2969
2970 /*
2971 The following two blocks are executed if the worker has not been
2972 notified about new relay-log or a new checkpoints.
2973 Relay-log string is freed by Coordinator, Worker deallocates
2974 strings in the checkpoint block.
2975 However if the worker exits earlier reclaiming for both happens anyway at
2976 GAQ delete.
2977 */
2978 if (!ret_worker->relay_log_change_notified)
2979 {
2980 /*
2981 Prior this event, C rotated the relay log to drop each
2982 Worker's notified flag. Now group terminating event initiates
2983 the new relay-log (where the current event is from) name
2984 delivery to Worker that will receive it in commit_positions().
2985 */
2986 DBUG_ASSERT(ptr_group->group_relay_log_name == NULL);
2987
2988 ptr_group->group_relay_log_name= (char *)
2989 my_malloc(strlen(rli->
2990 get_group_relay_log_name()) + 1, MYF(MY_WME));
2991 strcpy(ptr_group->group_relay_log_name,
2992 rli->get_event_relay_log_name());
2993
2994 DBUG_ASSERT(ptr_group->group_relay_log_name != NULL);
2995
2996 ret_worker->relay_log_change_notified= TRUE;
2997 }
2998
2999 if (!ret_worker->checkpoint_notified)
3000 {
3001 if (!ptr_group)
3002 ptr_group= gaq->get_job_group(rli->gaq->assigned_group_index);
3003 ptr_group->checkpoint_log_name=
3004 my_strdup(rli->get_group_master_log_name(), MYF(MY_WME));
3005 ptr_group->checkpoint_log_pos= rli->get_group_master_log_pos();
3006 ptr_group->checkpoint_relay_log_name=
3007 my_strdup(rli->get_group_relay_log_name(), MYF(MY_WME));
3008 ptr_group->checkpoint_relay_log_pos= rli->get_group_relay_log_pos();
3009 ptr_group->shifted= ret_worker->bitmap_shifted;
3010 ret_worker->bitmap_shifted= 0;
3011 ret_worker->checkpoint_notified= TRUE;
3012 }
3013 ptr_group->checkpoint_seqno= rli->checkpoint_seqno;
3014 ptr_group->ts= when.tv_sec + (time_t) exec_time; // Seconds_behind_master related
3015 rli->checkpoint_seqno++;
3016 /*
3017 Coordinator should not use the main memroot however its not
3018 reset elsewhere either, so let's do it safe way.
3019 The main mem root is also reset by the SQL thread in at the end
3020 of applying which Coordinator does not do in this case.
3021 That concludes the memroot reset can't harm anything in SQL thread roles
3022 after Coordinator has finished its current scheduling.
3023 */
3024 free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
3025
3026 #ifndef DBUG_OFF
3027 w_rr++;
3028 #endif
3029
3030 }
3031
3032 return ret_worker;
3033 }
3034
3035 /**
3036 Scheduling event to execute in parallel or execute it directly.
3037 In MTS case the event gets associated with either Coordinator or a
3038 Worker. A special case of the association is NULL when the Worker
3039 can't be decided yet. In the single threaded sequential mode the
3040 event maps to SQL thread rli.
3041
3042 @note in case of MTS failure Coordinator destroys all gathered
3043 deferred events.
3044
3045 @return 0 as success, otherwise a failure.
3046 */
apply_event(Relay_log_info * rli)3047 int Log_event::apply_event(Relay_log_info *rli)
3048 {
3049 DBUG_ENTER("LOG_EVENT:apply_event");
3050 bool parallel= FALSE;
3051 enum enum_mts_event_exec_mode actual_exec_mode= EVENT_EXEC_PARALLEL;
3052 THD *thd= rli->info_thd;
3053
3054 worker= rli;
3055
3056 if (rli->is_mts_recovery())
3057 {
3058 bool skip=
3059 bitmap_is_set(&rli->recovery_groups, rli->mts_recovery_index) &&
3060 (get_mts_execution_mode(::server_id,
3061 rli->mts_group_status == Relay_log_info::MTS_IN_GROUP)
3062 == EVENT_EXEC_PARALLEL);
3063 if (skip)
3064 {
3065 DBUG_RETURN(0);
3066 }
3067 else
3068 {
3069 DBUG_RETURN(do_apply_event(rli));
3070 }
3071 }
3072
3073 if (!(parallel= rli->is_parallel_exec()) ||
3074 ((actual_exec_mode=
3075 get_mts_execution_mode(::server_id,
3076 rli->mts_group_status == Relay_log_info::MTS_IN_GROUP))
3077 != EVENT_EXEC_PARALLEL))
3078 {
3079 if (parallel)
3080 {
3081 /*
3082 There are two classes of events that Coordinator executes
3083 itself. One e.g the master Rotate requires all Workers to finish up
3084 their assignments. The other async class, e.g the slave Rotate,
3085 can't have this such synchronization because Worker might be waiting
3086 for terminal events to finish.
3087 */
3088
3089 if (actual_exec_mode != EVENT_EXEC_ASYNC)
3090 {
3091 /*
3092 this event does not split the current group but is indeed
3093 a separator beetwen two master's binlog therefore requiring
3094 Workers to sync.
3095 */
3096 if (rli->curr_group_da.elements > 0)
3097 {
3098 char llbuff[22];
3099 /*
3100 Possible reason is a old version binlog sequential event
3101 wrappped with BEGIN/COMMIT or preceeded by User|Int|Random- var.
3102 MTS has to stop to suggest restart in the permanent sequential mode.
3103 */
3104 llstr(rli->get_event_relay_log_pos(), llbuff);
3105 my_error(ER_MTS_CANT_PARALLEL, MYF(0),
3106 get_type_str(), rli->get_event_relay_log_name(), llbuff,
3107 "possible malformed group of events from an old master");
3108
3109 /* Coordinator cant continue, it marks MTS group status accordingly */
3110 rli->mts_group_status= Relay_log_info::MTS_KILLED_GROUP;
3111
3112 goto err;
3113 }
3114 /*
3115 Marking sure the event will be executed in sequential mode.
3116 */
3117 if (wait_for_workers_to_finish(rli) == -1)
3118 {
3119 // handle synchronization error
3120 rli->report(WARNING_LEVEL, 0,
3121 "Slave worker thread has failed to apply an event. As a "
3122 "consequence, the coordinator thread is stopping "
3123 "execution.");
3124 DBUG_RETURN(-1);
3125 }
3126 /*
3127 Given not in-group mark the event handler can invoke checkpoint
3128 update routine in the following course.
3129 */
3130 DBUG_ASSERT(rli->mts_group_status == Relay_log_info::MTS_NOT_IN_GROUP);
3131
3132 #ifndef DBUG_OFF
3133 /* all Workers are idle as done through wait_for_workers_to_finish */
3134 for (uint k= 0; k < rli->curr_group_da.elements; k++)
3135 {
3136 DBUG_ASSERT(!(*(Slave_worker **)
3137 dynamic_array_ptr(&rli->workers, k))->usage_partition);
3138 DBUG_ASSERT(!(*(Slave_worker **)
3139 dynamic_array_ptr(&rli->workers, k))->jobs.len);
3140 }
3141 #endif
3142 }
3143 else
3144 {
3145 DBUG_ASSERT(actual_exec_mode == EVENT_EXEC_ASYNC);
3146 }
3147 }
3148 DBUG_RETURN(do_apply_event(rli));
3149 }
3150
3151 DBUG_ASSERT(actual_exec_mode == EVENT_EXEC_PARALLEL);
3152 DBUG_ASSERT(!(rli->curr_group_seen_begin && ends_group()) ||
3153 /*
3154 This is an empty group being processed due to gtids.
3155 */
3156 (rli->curr_group_seen_begin && rli->curr_group_seen_gtid
3157 && ends_group()) ||
3158 rli->last_assigned_worker ||
3159 /*
3160 Begin_load_query can be logged w/o db info and within
3161 Begin/Commit. That's a pattern forcing sequential
3162 applying of LOAD-DATA.
3163 */
3164 (*(Log_event **)
3165 dynamic_array_ptr(&rli->curr_group_da,
3166 rli->curr_group_da.elements - 1))->
3167 get_type_code() == BEGIN_LOAD_QUERY_EVENT);
3168
3169 worker= NULL;
3170 rli->mts_group_status= Relay_log_info::MTS_IN_GROUP;
3171
3172 worker= (Relay_log_info*)
3173 (rli->last_assigned_worker= get_slave_worker(rli));
3174
3175 #ifndef DBUG_OFF
3176 if (rli->last_assigned_worker)
3177 DBUG_PRINT("mts", ("Assigning job to worker %lu",
3178 rli->last_assigned_worker->id));
3179 #endif
3180
3181 err:
3182 if (thd->is_error())
3183 {
3184 DBUG_ASSERT(!worker);
3185
3186 /*
3187 Destroy all deferred buffered events but the current prior to exit.
3188 The current one will be deleted as an event never destined/assigned
3189 to any Worker in Coordinator's regular execution path.
3190 */
3191 for (uint k= 0; k < rli->curr_group_da.elements; k++)
3192 {
3193 Log_event *ev_buf=
3194 *(Log_event**) dynamic_array_ptr(&rli->curr_group_da, k);
3195 if (this != ev_buf)
3196 delete ev_buf;
3197 }
3198 rli->curr_group_da.elements= 0;
3199 }
3200 else
3201 {
3202 DBUG_ASSERT(worker || rli->curr_group_assigned_parts.elements == 0);
3203 }
3204
3205 DBUG_RETURN((!thd->is_error() ||
3206 DBUG_EVALUATE_IF("fault_injection_get_slave_worker", 1, 0)) ?
3207 0 : -1);
3208 }
3209
3210 #endif
3211
3212 /**************************************************************************
3213 Query_log_event methods
3214 **************************************************************************/
3215
3216 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
3217
3218 /**
3219 This (which is used only for SHOW BINLOG EVENTS) could be updated to
3220 print SET @@session_var=. But this is not urgent, as SHOW BINLOG EVENTS is
3221 only an information, it does not produce suitable queries to replay (for
3222 example it does not print LOAD DATA INFILE).
3223 @todo
3224 show the catalog ??
3225 */
3226
pack_info(Protocol * protocol)3227 int Query_log_event::pack_info(Protocol *protocol)
3228 {
3229 // TODO: show the catalog ??
3230 String temp_buf;
3231 // Add use `DB` to the string if required
3232 if (!(flags & LOG_EVENT_SUPPRESS_USE_F)
3233 && db && db_len)
3234 {
3235 temp_buf.append("use ");
3236 append_identifier(this->thd, &temp_buf, db, db_len);
3237 temp_buf.append("; ");
3238 }
3239 // Add the query to the string
3240 if (query && q_len)
3241 temp_buf.append(query);
3242 // persist the buffer in protocol
3243 protocol->store(temp_buf.ptr(), temp_buf.length(), &my_charset_bin);
3244 return 0;
3245 }
3246 #endif
3247
3248 #ifndef MYSQL_CLIENT
3249
3250 /**
3251 Utility function for the next method (Query_log_event::write()) .
3252 */
write_str_with_code_and_len(uchar ** dst,const char * src,uint len,uint code)3253 static void write_str_with_code_and_len(uchar **dst, const char *src,
3254 uint len, uint code)
3255 {
3256 /*
3257 only 1 byte to store the length of catalog, so it should not
3258 surpass 255
3259 */
3260 DBUG_ASSERT(len <= 255);
3261 DBUG_ASSERT(src);
3262 *((*dst)++)= code;
3263 *((*dst)++)= (uchar) len;
3264 bmove(*dst, src, len);
3265 (*dst)+= len;
3266 }
3267
3268
3269 /**
3270 Query_log_event::write().
3271
3272 @note
3273 In this event we have to modify the header to have the correct
3274 EVENT_LEN_OFFSET as we don't yet know how many status variables we
3275 will print!
3276 */
3277
write(IO_CACHE * file)3278 bool Query_log_event::write(IO_CACHE* file)
3279 {
3280 uchar buf[QUERY_HEADER_LEN + MAX_SIZE_LOG_EVENT_STATUS];
3281 uchar *start, *start_of_status;
3282 ulong event_length;
3283
3284 if (!query)
3285 return 1; // Something wrong with event
3286
3287 /*
3288 We want to store the thread id:
3289 (- as an information for the user when he reads the binlog)
3290 - if the query uses temporary table: for the slave SQL thread to know to
3291 which master connection the temp table belongs.
3292 Now imagine we (write()) are called by the slave SQL thread (we are
3293 logging a query executed by this thread; the slave runs with
3294 --log-slave-updates). Then this query will be logged with
3295 thread_id=the_thread_id_of_the_SQL_thread. Imagine that 2 temp tables of
3296 the same name were created simultaneously on the master (in the master
3297 binlog you have
3298 CREATE TEMPORARY TABLE t; (thread 1)
3299 CREATE TEMPORARY TABLE t; (thread 2)
3300 ...)
3301 then in the slave's binlog there will be
3302 CREATE TEMPORARY TABLE t; (thread_id_of_the_slave_SQL_thread)
3303 CREATE TEMPORARY TABLE t; (thread_id_of_the_slave_SQL_thread)
3304 which is bad (same thread id!).
3305
3306 To avoid this, we log the thread's thread id EXCEPT for the SQL
3307 slave thread for which we log the original (master's) thread id.
3308 Now this moves the bug: what happens if the thread id on the
3309 master was 10 and when the slave replicates the query, a
3310 connection number 10 is opened by a normal client on the slave,
3311 and updates a temp table of the same name? We get a problem
3312 again. To avoid this, in the handling of temp tables (sql_base.cc)
3313 we use thread_id AND server_id. TODO when this is merged into
3314 4.1: in 4.1, slave_proxy_id has been renamed to pseudo_thread_id
3315 and is a session variable: that's to make mysqlbinlog work with
3316 temp tables. We probably need to introduce
3317
3318 SET PSEUDO_SERVER_ID
3319 for mysqlbinlog in 4.1. mysqlbinlog would print:
3320 SET PSEUDO_SERVER_ID=
3321 SET PSEUDO_THREAD_ID=
3322 for each query using temp tables.
3323 */
3324 int4store(buf + Q_THREAD_ID_OFFSET, slave_proxy_id);
3325 int4store(buf + Q_EXEC_TIME_OFFSET, exec_time);
3326 buf[Q_DB_LEN_OFFSET] = (char) db_len;
3327 int2store(buf + Q_ERR_CODE_OFFSET, error_code);
3328
3329 /*
3330 You MUST always write status vars in increasing order of code. This
3331 guarantees that a slightly older slave will be able to parse those he
3332 knows.
3333 */
3334 start_of_status= start= buf+QUERY_HEADER_LEN;
3335 if (flags2_inited)
3336 {
3337 *start++= Q_FLAGS2_CODE;
3338 int4store(start, flags2);
3339 start+= 4;
3340 }
3341 if (sql_mode_inited)
3342 {
3343 *start++= Q_SQL_MODE_CODE;
3344 int8store(start, sql_mode);
3345 start+= 8;
3346 }
3347 if (catalog_len) // i.e. this var is inited (false for 4.0 events)
3348 {
3349 write_str_with_code_and_len(&start,
3350 catalog, catalog_len, Q_CATALOG_NZ_CODE);
3351 /*
3352 In 5.0.x where x<4 masters we used to store the end zero here. This was
3353 a waste of one byte so we don't do it in x>=4 masters. We change code to
3354 Q_CATALOG_NZ_CODE, because re-using the old code would make x<4 slaves
3355 of this x>=4 master segfault (expecting a zero when there is
3356 none). Remaining compatibility problems are: the older slave will not
3357 find the catalog; but it is will not crash, and it's not an issue
3358 that it does not find the catalog as catalogs were not used in these
3359 older MySQL versions (we store it in binlog and read it from relay log
3360 but do nothing useful with it). What is an issue is that the older slave
3361 will stop processing the Q_* blocks (and jumps to the db/query) as soon
3362 as it sees unknown Q_CATALOG_NZ_CODE; so it will not be able to read
3363 Q_AUTO_INCREMENT*, Q_CHARSET and so replication will fail silently in
3364 various ways. Documented that you should not mix alpha/beta versions if
3365 they are not exactly the same version, with example of 5.0.3->5.0.2 and
3366 5.0.4->5.0.3. If replication is from older to new, the new will
3367 recognize Q_CATALOG_CODE and have no problem.
3368 */
3369 }
3370 if (auto_increment_increment != 1 || auto_increment_offset != 1)
3371 {
3372 *start++= Q_AUTO_INCREMENT;
3373 int2store(start, auto_increment_increment);
3374 int2store(start+2, auto_increment_offset);
3375 start+= 4;
3376 }
3377 if (charset_inited)
3378 {
3379 *start++= Q_CHARSET_CODE;
3380 memcpy(start, charset, 6);
3381 start+= 6;
3382 }
3383 if (time_zone_len)
3384 {
3385 /* In the TZ sys table, column Name is of length 64 so this should be ok */
3386 DBUG_ASSERT(time_zone_len <= MAX_TIME_ZONE_NAME_LENGTH);
3387 write_str_with_code_and_len(&start,
3388 time_zone_str, time_zone_len, Q_TIME_ZONE_CODE);
3389 }
3390 if (lc_time_names_number)
3391 {
3392 DBUG_ASSERT(lc_time_names_number <= 0xFFFF);
3393 *start++= Q_LC_TIME_NAMES_CODE;
3394 int2store(start, lc_time_names_number);
3395 start+= 2;
3396 }
3397 if (charset_database_number)
3398 {
3399 DBUG_ASSERT(charset_database_number <= 0xFFFF);
3400 *start++= Q_CHARSET_DATABASE_CODE;
3401 int2store(start, charset_database_number);
3402 start+= 2;
3403 }
3404 if (table_map_for_update)
3405 {
3406 *start++= Q_TABLE_MAP_FOR_UPDATE_CODE;
3407 int8store(start, table_map_for_update);
3408 start+= 8;
3409 }
3410 if (master_data_written != 0)
3411 {
3412 /*
3413 Q_MASTER_DATA_WRITTEN_CODE only exists in relay logs where the master
3414 has binlog_version<4 and the slave has binlog_version=4. See comment
3415 for master_data_written in log_event.h for details.
3416 */
3417 *start++= Q_MASTER_DATA_WRITTEN_CODE;
3418 int4store(start, master_data_written);
3419 start+= 4;
3420 }
3421
3422 if (thd && thd->need_binlog_invoker())
3423 {
3424 LEX_STRING user;
3425 LEX_STRING host;
3426 memset(&user, 0, sizeof(user));
3427 memset(&host, 0, sizeof(host));
3428
3429 if (thd->slave_thread && thd->has_invoker())
3430 {
3431 /* user will be null, if master is older than this patch */
3432 user= thd->get_invoker_user();
3433 host= thd->get_invoker_host();
3434 }
3435 else
3436 {
3437 Security_context *ctx= thd->security_ctx;
3438
3439 user.length= strlen(ctx->priv_user);
3440 user.str= ctx->priv_user;
3441 if (ctx->priv_host[0] != '\0')
3442 {
3443 host.str= ctx->priv_host;
3444 host.length= strlen(ctx->priv_host);
3445 }
3446 }
3447
3448 *start++= Q_INVOKER;
3449
3450 /*
3451 Store user length and user. The max length of use is 16, so 1 byte is
3452 enough to store the user's length.
3453 */
3454 *start++= (uchar)user.length;
3455 memcpy(start, user.str, user.length);
3456 start+= user.length;
3457
3458 /*
3459 Store host length and host. The max length of host is 60, so 1 byte is
3460 enough to store the host's length.
3461 */
3462 *start++= (uchar)host.length;
3463 memcpy(start, host.str, host.length);
3464 start+= host.length;
3465 }
3466
3467 if (thd && thd->get_binlog_accessed_db_names() != NULL)
3468 {
3469 uchar dbs;
3470 *start++= Q_UPDATED_DB_NAMES;
3471
3472 compile_time_assert(MAX_DBS_IN_EVENT_MTS <= OVER_MAX_DBS_IN_EVENT_MTS);
3473
3474 /*
3475 In case of the number of db:s exceeds MAX_DBS_IN_EVENT_MTS
3476 no db:s is written and event will require the sequential applying on slave.
3477 */
3478 dbs=
3479 (thd->get_binlog_accessed_db_names()->elements <= MAX_DBS_IN_EVENT_MTS) ?
3480 thd->get_binlog_accessed_db_names()->elements : OVER_MAX_DBS_IN_EVENT_MTS;
3481
3482 DBUG_ASSERT(dbs != 0);
3483
3484 if (dbs <= MAX_DBS_IN_EVENT_MTS)
3485 {
3486 List_iterator_fast<char> it(*thd->get_binlog_accessed_db_names());
3487 char *db_name= it++;
3488 /*
3489 the single "" db in the acccessed db list corresponds to the same as
3490 exceeds MAX_DBS_IN_EVENT_MTS case, so dbs is set to the over-max.
3491 */
3492 if (dbs == 1 && !strcmp(db_name, ""))
3493 dbs= OVER_MAX_DBS_IN_EVENT_MTS;
3494 *start++= dbs;
3495 if (dbs != OVER_MAX_DBS_IN_EVENT_MTS)
3496 do
3497 {
3498 strcpy((char*) start, db_name);
3499 start += strlen(db_name) + 1;
3500 } while ((db_name= it++));
3501 }
3502 else
3503 {
3504 *start++= dbs;
3505 }
3506 }
3507
3508 if (thd && thd->query_start_usec_used)
3509 {
3510 *start++= Q_MICROSECONDS;
3511 get_time();
3512 int3store(start, when.tv_usec);
3513 start+= 3;
3514 }
3515
3516 #ifndef DBUG_OFF
3517 if (thd && thd->variables.query_exec_time > 0)
3518 {
3519 *start++= Q_QUERY_EXEC_TIME;
3520 int8store(start, thd->variables.query_exec_time);
3521 start+= 8;
3522 }
3523 #endif
3524
3525 /*
3526 NOTE: When adding new status vars, please don't forget to update
3527 the MAX_SIZE_LOG_EVENT_STATUS in log_event.h and update the function
3528 code_name() in this file.
3529
3530 Here there could be code like
3531 if (command-line-option-which-says-"log_this_variable" && inited)
3532 {
3533 *start++= Q_THIS_VARIABLE_CODE;
3534 int4store(start, this_variable);
3535 start+= 4;
3536 }
3537 */
3538
3539 /* Store length of status variables */
3540 status_vars_len= (uint) (start-start_of_status);
3541 DBUG_ASSERT(status_vars_len <= MAX_SIZE_LOG_EVENT_STATUS);
3542 int2store(buf + Q_STATUS_VARS_LEN_OFFSET, status_vars_len);
3543
3544 /*
3545 Calculate length of whole event
3546 The "1" below is the \0 in the db's length
3547 */
3548 event_length= (uint) (start-buf) + get_post_header_size_for_derived() + db_len + 1 + q_len;
3549
3550 return (write_header(file, event_length) ||
3551 wrapper_my_b_safe_write(file, (uchar*) buf, QUERY_HEADER_LEN) ||
3552 write_post_header_for_derived(file) ||
3553 wrapper_my_b_safe_write(file, (uchar*) start_of_status,
3554 (uint) (start-start_of_status)) ||
3555 wrapper_my_b_safe_write(file, (db) ? (uchar*) db : (uchar*)"", db_len + 1) ||
3556 wrapper_my_b_safe_write(file, (uchar*) query, q_len) ||
3557 write_footer(file)) ? 1 : 0;
3558 }
3559
3560 /**
3561 The simplest constructor that could possibly work. This is used for
3562 creating static objects that have a special meaning and are invisible
3563 to the log.
3564 */
Query_log_event()3565 Query_log_event::Query_log_event()
3566 :Log_event(), data_buf(0)
3567 {
3568 memset(&user, 0, sizeof(user));
3569 memset(&host, 0, sizeof(host));
3570 }
3571
3572
3573 /**
3574 Creates a Query Log Event.
3575
3576 @param thd_arg Thread handle
3577 @param query_arg Array of char representing the query
3578 @param query_length Size of the 'query_arg' array
3579 @param using_trans Indicates that there are transactional changes.
3580 @param immediate After being written to the binary log, the event
3581 must be flushed immediately. This indirectly implies
3582 the stmt-cache.
3583 @param suppress_use Suppress the generation of 'USE' statements
3584 @param errcode The error code of the query
3585 @param ignore Ignore user's statement, i.e. lex information, while
3586 deciding which cache must be used.
3587 */
Query_log_event(THD * thd_arg,const char * query_arg,ulong query_length,bool using_trans,bool immediate,bool suppress_use,int errcode,bool ignore_cmd_internals)3588 Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
3589 ulong query_length, bool using_trans,
3590 bool immediate, bool suppress_use,
3591 int errcode, bool ignore_cmd_internals)
3592
3593 :Log_event(thd_arg,
3594 (thd_arg->thread_specific_used ? LOG_EVENT_THREAD_SPECIFIC_F :
3595 0) |
3596 (suppress_use ? LOG_EVENT_SUPPRESS_USE_F : 0),
3597 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
3598 Log_event::EVENT_STMT_CACHE,
3599 Log_event::EVENT_NORMAL_LOGGING),
3600 data_buf(0), query(query_arg), catalog(thd_arg->catalog),
3601 db(thd_arg->db), q_len((uint32) query_length),
3602 thread_id(thd_arg->thread_id),
3603 /* save the original thread id; we already know the server id */
3604 slave_proxy_id(thd_arg->variables.pseudo_thread_id),
3605 flags2_inited(1), sql_mode_inited(1), charset_inited(1),
3606 sql_mode(thd_arg->variables.sql_mode),
3607 auto_increment_increment(thd_arg->variables.auto_increment_increment),
3608 auto_increment_offset(thd_arg->variables.auto_increment_offset),
3609 lc_time_names_number(thd_arg->variables.lc_time_names->number),
3610 charset_database_number(0),
3611 table_map_for_update((ulonglong)thd_arg->table_map_for_update),
3612 master_data_written(0), mts_accessed_dbs(0)
3613 {
3614
3615 memset(&user, 0, sizeof(user));
3616 memset(&host, 0, sizeof(host));
3617
3618 error_code= errcode;
3619
3620 /*
3621 exec_time calculation has changed to use the same method that is used
3622 to fill out "thd_arg->start_time"
3623 */
3624
3625 struct timeval end_time;
3626 ulonglong micro_end_time= my_micro_time();
3627 my_micro_time_to_timeval(micro_end_time, &end_time);
3628
3629 exec_time= end_time.tv_sec - thd_arg->start_time.tv_sec;
3630
3631 /**
3632 @todo this means that if we have no catalog, then it is replicated
3633 as an existing catalog of length zero. is that safe? /sven
3634 */
3635 catalog_len = (catalog) ? (uint32) strlen(catalog) : 0;
3636 /* status_vars_len is set just before writing the event */
3637 db_len = (db) ? (uint32) strlen(db) : 0;
3638 if (thd_arg->variables.collation_database != thd_arg->db_charset)
3639 charset_database_number= thd_arg->variables.collation_database->number;
3640
3641 /*
3642 We only replicate over the bits of flags2 that we need: the rest
3643 are masked out by "& OPTIONS_WRITTEN_TO_BINLOG".
3644
3645 We also force AUTOCOMMIT=1. Rationale (cf. BUG#29288): After
3646 fixing BUG#26395, we always write BEGIN and COMMIT around all
3647 transactions (even single statements in autocommit mode). This is
3648 so that replication from non-transactional to transactional table
3649 and error recovery from XA to non-XA table should work as
3650 expected. The BEGIN/COMMIT are added in log.cc. However, there is
3651 one exception: MyISAM bypasses log.cc and writes directly to the
3652 binlog. So if autocommit is off, master has MyISAM, and slave has
3653 a transactional engine, then the slave will just see one long
3654 never-ending transaction. The only way to bypass explicit
3655 BEGIN/COMMIT in the binlog is by using a non-transactional table.
3656 So setting AUTOCOMMIT=1 will make this work as expected.
3657
3658 Note: explicitly replicate AUTOCOMMIT=1 from master. We do not
3659 assume AUTOCOMMIT=1 on slave; the slave still reads the state of
3660 the autocommit flag as written by the master to the binlog. This
3661 behavior may change after WL#4162 has been implemented.
3662 */
3663 flags2= (uint32) (thd_arg->variables.option_bits &
3664 (OPTIONS_WRITTEN_TO_BIN_LOG & ~OPTION_NOT_AUTOCOMMIT));
3665 DBUG_ASSERT(thd_arg->variables.character_set_client->number < 256*256);
3666 DBUG_ASSERT(thd_arg->variables.collation_connection->number < 256*256);
3667 DBUG_ASSERT(thd_arg->variables.collation_server->number < 256*256);
3668 DBUG_ASSERT(thd_arg->variables.character_set_client->mbminlen == 1);
3669 int2store(charset, thd_arg->variables.character_set_client->number);
3670 int2store(charset+2, thd_arg->variables.collation_connection->number);
3671 int2store(charset+4, thd_arg->variables.collation_server->number);
3672 if (thd_arg->time_zone_used)
3673 {
3674 /*
3675 Note that our event becomes dependent on the Time_zone object
3676 representing the time zone. Fortunately such objects are never deleted
3677 or changed during mysqld's lifetime.
3678 */
3679 time_zone_len= thd_arg->variables.time_zone->get_name()->length();
3680 time_zone_str= thd_arg->variables.time_zone->get_name()->ptr();
3681 }
3682 else
3683 time_zone_len= 0;
3684
3685 /*
3686 In what follows, we define in which cache, trx-cache or stmt-cache,
3687 this Query Log Event will be written to.
3688
3689 If ignore_cmd_internals is defined, we rely on the is_trans flag to
3690 choose the cache and this is done in the base class Log_event. False
3691 means that the stmt-cache will be used and upon statement commit/rollback
3692 the cache will be flushed to disk. True means that the trx-cache will
3693 be used and upon transaction commit/rollback the cache will be flushed
3694 to disk.
3695
3696 If set immediate cache is defined, for convenience, we automatically
3697 use the stmt-cache. This mean that the statement will be written
3698 to the stmt-cache and immediately flushed to disk without waiting
3699 for a commit/rollback notification.
3700
3701 For example, the cluster/ndb captures a request to execute a DDL
3702 statement and synchronously propagate it to all available MySQL
3703 servers. Unfortunately, the current protocol assumes that the
3704 generated events are immediately written to diks and does not check
3705 for commit/rollback.
3706
3707 Upon dropping a connection, DDLs (i.e. DROP TEMPORARY TABLE) are
3708 generated and in this case the statements have the immediate flag
3709 set because there is no commit/rollback.
3710
3711 If the immediate flag is not set, the decision on the cache is based
3712 on the current statement and the flag is_trans, which indicates if
3713 a transactional engine was updated.
3714
3715 Statements are classifed as row producers (i.e. can_generate_row_events())
3716 or non-row producers. Non-row producers, DDL in general, are treated
3717 as the immediate flag was set and for convenience are written to the
3718 stmt-cache and immediately flushed to disk.
3719
3720 Row producers are handled in general according to the is_trans flag.
3721 False means that the stmt-cache will be used and upon statement
3722 commit/rollback the cache will be flushed to disk. True means that the
3723 trx-cache will be used and upon transaction commit/rollback the cache
3724 will be flushed to disk.
3725
3726 Unfortunately, there are exceptions to this non-row and row producer
3727 rules:
3728
3729 . The SAVEPOINT, ROLLBACK TO SAVEPOINT, RELEASE SAVEPOINT does not
3730 have the flag is_trans set because there is no updated engine but
3731 must be written to the trx-cache.
3732
3733 . SET If auto-commit is on, it must not go through a cache.
3734
3735 . CREATE TABLE is classfied as non-row producer but CREATE TEMPORARY
3736 must be handled as row producer.
3737
3738 . DROP TABLE is classfied as non-row producer but DROP TEMPORARY
3739 must be handled as row producer.
3740
3741 Finally, some statements that does not have the flag is_trans set may
3742 be written to the trx-cache based on the following criteria:
3743
3744 . updated both a transactional and a non-transactional engine (i.e.
3745 stmt_has_updated_trans_table()).
3746
3747 . accessed both a transactional and a non-transactional engine and
3748 is classified as unsafe (i.e. is_mixed_stmt_unsafe()).
3749
3750 . is executed within a transaction and previously a transactional
3751 engine was updated and the flag binlog_direct_non_trans_update
3752 is set.
3753 */
3754 if (ignore_cmd_internals)
3755 return;
3756
3757 /*
3758 TRUE defines that the trx-cache must be used.
3759 */
3760 bool cmd_can_generate_row_events= FALSE;
3761 /*
3762 TRUE defines that the trx-cache must be used.
3763 */
3764 bool cmd_must_go_to_trx_cache= FALSE;
3765
3766 LEX *lex= thd->lex;
3767 if (!immediate)
3768 {
3769 switch (lex->sql_command)
3770 {
3771 case SQLCOM_DROP_TABLE:
3772 cmd_can_generate_row_events= lex->drop_temporary &&
3773 thd->in_multi_stmt_transaction_mode();
3774 break;
3775 case SQLCOM_CREATE_TABLE:
3776 cmd_must_go_to_trx_cache= lex->select_lex.item_list.elements &&
3777 thd->is_current_stmt_binlog_format_row();
3778 cmd_can_generate_row_events=
3779 ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
3780 thd->in_multi_stmt_transaction_mode()) || cmd_must_go_to_trx_cache;
3781 break;
3782 case SQLCOM_SET_OPTION:
3783 if (lex->autocommit)
3784 cmd_can_generate_row_events= cmd_must_go_to_trx_cache= FALSE;
3785 else
3786 cmd_can_generate_row_events= TRUE;
3787 break;
3788 case SQLCOM_RELEASE_SAVEPOINT:
3789 case SQLCOM_ROLLBACK_TO_SAVEPOINT:
3790 case SQLCOM_SAVEPOINT:
3791 cmd_can_generate_row_events= cmd_must_go_to_trx_cache= TRUE;
3792 break;
3793 default:
3794 cmd_can_generate_row_events=
3795 sqlcom_can_generate_row_events(thd->lex->sql_command);
3796 break;
3797 }
3798 }
3799
3800 if (cmd_can_generate_row_events)
3801 {
3802 cmd_must_go_to_trx_cache= cmd_must_go_to_trx_cache || using_trans;
3803 if (cmd_must_go_to_trx_cache ||
3804 stmt_has_updated_trans_table(thd->transaction.stmt.ha_list) ||
3805 thd->lex->is_mixed_stmt_unsafe(thd->in_multi_stmt_transaction_mode(),
3806 thd->variables.binlog_direct_non_trans_update,
3807 trans_has_updated_trans_table(thd),
3808 thd->tx_isolation) ||
3809 (!thd->variables.binlog_direct_non_trans_update && trans_has_updated_trans_table(thd)))
3810 {
3811 event_logging_type= Log_event::EVENT_NORMAL_LOGGING;
3812 event_cache_type= Log_event::EVENT_TRANSACTIONAL_CACHE;
3813 }
3814 else
3815 {
3816 event_logging_type= Log_event::EVENT_NORMAL_LOGGING;
3817 event_cache_type= Log_event::EVENT_STMT_CACHE;
3818 }
3819 }
3820 else
3821 {
3822 event_logging_type= Log_event::EVENT_IMMEDIATE_LOGGING;
3823 event_cache_type= Log_event::EVENT_STMT_CACHE;
3824 }
3825
3826 DBUG_ASSERT(event_cache_type != Log_event::EVENT_INVALID_CACHE);
3827 DBUG_ASSERT(event_logging_type != Log_event::EVENT_INVALID_LOGGING);
3828 DBUG_PRINT("info",("Query_log_event has flags2: %lu sql_mode: %llu",
3829 (ulong) flags2, sql_mode));
3830 }
3831 #endif /* MYSQL_CLIENT */
3832
3833
3834 /* 2 utility functions for the next method */
3835
3836 /**
3837 Read a string with length from memory.
3838
3839 This function reads the string-with-length stored at
3840 <code>src</code> and extract the length into <code>*len</code> and
3841 a pointer to the start of the string into <code>*dst</code>. The
3842 string can then be copied using <code>memcpy()</code> with the
3843 number of bytes given in <code>*len</code>.
3844
3845 @param src Pointer to variable holding a pointer to the memory to
3846 read the string from.
3847 @param dst Pointer to variable holding a pointer where the actual
3848 string starts. Starting from this position, the string
3849 can be copied using @c memcpy().
3850 @param len Pointer to variable where the length will be stored.
3851 @param end One-past-the-end of the memory where the string is
3852 stored.
3853
3854 @return Zero if the entire string can be copied successfully,
3855 @c UINT_MAX if the length could not be read from memory
3856 (that is, if <code>*src >= end</code>), otherwise the
3857 number of bytes that are missing to read the full
3858 string, which happends <code>*dst + *len >= end</code>.
3859 */
3860 static int
get_str_len_and_pointer(const Log_event::Byte ** src,const char ** dst,uint * len,const Log_event::Byte * end)3861 get_str_len_and_pointer(const Log_event::Byte **src,
3862 const char **dst,
3863 uint *len,
3864 const Log_event::Byte *end)
3865 {
3866 if (*src >= end)
3867 return -1; // Will be UINT_MAX in two-complement arithmetics
3868 uint length= **src;
3869 if (length > 0)
3870 {
3871 if (*src + length >= end)
3872 return *src + length - end + 1; // Number of bytes missing
3873 *dst= (char *)*src + 1; // Will be copied later
3874 }
3875 *len= length;
3876 *src+= length + 1;
3877 return 0;
3878 }
3879
copy_str_and_move(const char ** src,Log_event::Byte ** dst,uint len)3880 static void copy_str_and_move(const char **src,
3881 Log_event::Byte **dst,
3882 uint len)
3883 {
3884 memcpy(*dst, *src, len);
3885 *src= (const char *)*dst;
3886 (*dst)+= len;
3887 *(*dst)++= 0;
3888 }
3889
3890
3891 #ifndef DBUG_OFF
3892 static char const *
code_name(int code)3893 code_name(int code)
3894 {
3895 static char buf[255];
3896 switch (code) {
3897 case Q_FLAGS2_CODE: return "Q_FLAGS2_CODE";
3898 case Q_SQL_MODE_CODE: return "Q_SQL_MODE_CODE";
3899 case Q_CATALOG_CODE: return "Q_CATALOG_CODE";
3900 case Q_AUTO_INCREMENT: return "Q_AUTO_INCREMENT";
3901 case Q_CHARSET_CODE: return "Q_CHARSET_CODE";
3902 case Q_TIME_ZONE_CODE: return "Q_TIME_ZONE_CODE";
3903 case Q_CATALOG_NZ_CODE: return "Q_CATALOG_NZ_CODE";
3904 case Q_LC_TIME_NAMES_CODE: return "Q_LC_TIME_NAMES_CODE";
3905 case Q_CHARSET_DATABASE_CODE: return "Q_CHARSET_DATABASE_CODE";
3906 case Q_TABLE_MAP_FOR_UPDATE_CODE: return "Q_TABLE_MAP_FOR_UPDATE_CODE";
3907 case Q_MASTER_DATA_WRITTEN_CODE: return "Q_MASTER_DATA_WRITTEN_CODE";
3908 case Q_UPDATED_DB_NAMES: return "Q_UPDATED_DB_NAMES";
3909 case Q_MICROSECONDS: return "Q_MICROSECONDS";
3910 }
3911 sprintf(buf, "CODE#%d", code);
3912 return buf;
3913 }
3914 #endif
3915
3916 /**
3917 Macro to check that there is enough space to read from memory.
3918
3919 @param PTR Pointer to memory
3920 @param END End of memory
3921 @param CNT Number of bytes that should be read.
3922 */
3923 #define CHECK_SPACE(PTR,END,CNT) \
3924 do { \
3925 DBUG_PRINT("info", ("Read %s", code_name(pos[-1]))); \
3926 DBUG_ASSERT((PTR) + (CNT) <= (END)); \
3927 if ((PTR) + (CNT) > (END)) { \
3928 DBUG_PRINT("info", ("query= 0")); \
3929 query= 0; \
3930 DBUG_VOID_RETURN; \
3931 } \
3932 } while (0)
3933
3934
3935 /**
3936 This is used by the SQL slave thread to prepare the event before execution.
3937 */
Query_log_event(const char * buf,uint event_len,const Format_description_log_event * description_event,Log_event_type event_type)3938 Query_log_event::Query_log_event(const char* buf, uint event_len,
3939 const Format_description_log_event
3940 *description_event,
3941 Log_event_type event_type)
3942 :Log_event(buf, description_event), data_buf(0), query(NullS),
3943 db(NullS), catalog_len(0), status_vars_len(0),
3944 flags2_inited(0), sql_mode_inited(0), charset_inited(0),
3945 auto_increment_increment(1), auto_increment_offset(1),
3946 time_zone_len(0), lc_time_names_number(0), charset_database_number(0),
3947 table_map_for_update(0), master_data_written(0),
3948 mts_accessed_dbs(OVER_MAX_DBS_IN_EVENT_MTS)
3949 {
3950 ulong data_len;
3951 uint32 tmp;
3952 uint8 common_header_len, post_header_len;
3953 Log_event::Byte *start;
3954 const Log_event::Byte *end;
3955 bool catalog_nz= 1;
3956 DBUG_ENTER("Query_log_event::Query_log_event(char*,...)");
3957
3958 memset(&user, 0, sizeof(user));
3959 memset(&host, 0, sizeof(host));
3960 common_header_len= description_event->common_header_len;
3961 post_header_len= description_event->post_header_len[event_type-1];
3962 DBUG_PRINT("info",("event_len: %u common_header_len: %d post_header_len: %d",
3963 event_len, common_header_len, post_header_len));
3964
3965 /*
3966 We test if the event's length is sensible, and if so we compute data_len.
3967 We cannot rely on QUERY_HEADER_LEN here as it would not be format-tolerant.
3968 We use QUERY_HEADER_MINIMAL_LEN which is the same for 3.23, 4.0 & 5.0.
3969 */
3970 if (event_len < (uint)(common_header_len + post_header_len))
3971 DBUG_VOID_RETURN;
3972 data_len = event_len - (common_header_len + post_header_len);
3973 buf+= common_header_len;
3974
3975 slave_proxy_id= thread_id = uint4korr(buf + Q_THREAD_ID_OFFSET);
3976 exec_time = uint4korr(buf + Q_EXEC_TIME_OFFSET);
3977 db_len = (uchar)buf[Q_DB_LEN_OFFSET]; // TODO: add a check of all *_len vars
3978 error_code = uint2korr(buf + Q_ERR_CODE_OFFSET);
3979
3980 /*
3981 5.0 format starts here.
3982 Depending on the format, we may or not have affected/warnings etc
3983 The remnent post-header to be parsed has length:
3984 */
3985 tmp= post_header_len - QUERY_HEADER_MINIMAL_LEN;
3986 if (tmp)
3987 {
3988 status_vars_len= uint2korr(buf + Q_STATUS_VARS_LEN_OFFSET);
3989 /*
3990 Check if status variable length is corrupt and will lead to very
3991 wrong data. We could be even more strict and require data_len to
3992 be even bigger, but this will suffice to catch most corruption
3993 errors that can lead to a crash.
3994 */
3995 if (status_vars_len > min<ulong>(data_len, MAX_SIZE_LOG_EVENT_STATUS))
3996 {
3997 DBUG_PRINT("info", ("status_vars_len (%u) > data_len (%lu); query= 0",
3998 status_vars_len, data_len));
3999 query= 0;
4000 DBUG_VOID_RETURN;
4001 }
4002 data_len-= status_vars_len;
4003 DBUG_PRINT("info", ("Query_log_event has status_vars_len: %u",
4004 (uint) status_vars_len));
4005 tmp-= 2;
4006 }
4007 else
4008 {
4009 /*
4010 server version < 5.0 / binlog_version < 4 master's event is
4011 relay-logged with storing the original size of the event in
4012 Q_MASTER_DATA_WRITTEN_CODE status variable.
4013 The size is to be restored at reading Q_MASTER_DATA_WRITTEN_CODE-marked
4014 event from the relay log.
4015 */
4016 DBUG_ASSERT(description_event->binlog_version < 4);
4017 master_data_written= data_written;
4018 }
4019 /*
4020 We have parsed everything we know in the post header for QUERY_EVENT,
4021 the rest of post header is either comes from older version MySQL or
4022 dedicated to derived events (e.g. Execute_load_query...)
4023 */
4024
4025 /* variable-part: the status vars; only in MySQL 5.0 */
4026
4027 start= (Log_event::Byte*) (buf+post_header_len);
4028 end= (const Log_event::Byte*) (start+status_vars_len);
4029 for (const Log_event::Byte* pos= start; pos < end;)
4030 {
4031 switch (*pos++) {
4032 case Q_FLAGS2_CODE:
4033 CHECK_SPACE(pos, end, 4);
4034 flags2_inited= 1;
4035 flags2= uint4korr(pos);
4036 DBUG_PRINT("info",("In Query_log_event, read flags2: %lu", (ulong) flags2));
4037 pos+= 4;
4038 break;
4039 case Q_SQL_MODE_CODE:
4040 {
4041 #ifndef DBUG_OFF
4042 char buff[22];
4043 #endif
4044 CHECK_SPACE(pos, end, 8);
4045 sql_mode_inited= 1;
4046 sql_mode= uint8korr(pos);
4047 DBUG_PRINT("info",("In Query_log_event, read sql_mode: %s",
4048 llstr(sql_mode, buff)));
4049 pos+= 8;
4050 break;
4051 }
4052 case Q_CATALOG_NZ_CODE:
4053 DBUG_PRINT("info", ("case Q_CATALOG_NZ_CODE; pos: 0x%lx; end: 0x%lx",
4054 (ulong) pos, (ulong) end));
4055 if (get_str_len_and_pointer(&pos, &catalog, &catalog_len, end))
4056 {
4057 DBUG_PRINT("info", ("query= 0"));
4058 query= 0;
4059 DBUG_VOID_RETURN;
4060 }
4061 break;
4062 case Q_AUTO_INCREMENT:
4063 CHECK_SPACE(pos, end, 4);
4064 auto_increment_increment= uint2korr(pos);
4065 auto_increment_offset= uint2korr(pos+2);
4066 pos+= 4;
4067 break;
4068 case Q_CHARSET_CODE:
4069 {
4070 CHECK_SPACE(pos, end, 6);
4071 charset_inited= 1;
4072 memcpy(charset, pos, 6);
4073 pos+= 6;
4074 break;
4075 }
4076 case Q_TIME_ZONE_CODE:
4077 {
4078 if (get_str_len_and_pointer(&pos, &time_zone_str, &time_zone_len, end))
4079 {
4080 DBUG_PRINT("info", ("Q_TIME_ZONE_CODE: query= 0"));
4081 query= 0;
4082 DBUG_VOID_RETURN;
4083 }
4084 break;
4085 }
4086 case Q_CATALOG_CODE: /* for 5.0.x where 0<=x<=3 masters */
4087 CHECK_SPACE(pos, end, 1);
4088 if ((catalog_len= *pos))
4089 catalog= (char*) pos+1; // Will be copied later
4090 CHECK_SPACE(pos, end, catalog_len + 2);
4091 pos+= catalog_len+2; // leap over end 0
4092 catalog_nz= 0; // catalog has end 0 in event
4093 break;
4094 case Q_LC_TIME_NAMES_CODE:
4095 CHECK_SPACE(pos, end, 2);
4096 lc_time_names_number= uint2korr(pos);
4097 pos+= 2;
4098 break;
4099 case Q_CHARSET_DATABASE_CODE:
4100 CHECK_SPACE(pos, end, 2);
4101 charset_database_number= uint2korr(pos);
4102 pos+= 2;
4103 break;
4104 case Q_TABLE_MAP_FOR_UPDATE_CODE:
4105 CHECK_SPACE(pos, end, 8);
4106 table_map_for_update= uint8korr(pos);
4107 pos+= 8;
4108 break;
4109 case Q_MASTER_DATA_WRITTEN_CODE:
4110 CHECK_SPACE(pos, end, 4);
4111 data_written= master_data_written= uint4korr(pos);
4112 pos+= 4;
4113 break;
4114 case Q_MICROSECONDS:
4115 CHECK_SPACE(pos, end, 3);
4116 when.tv_usec= uint3korr(pos);
4117 pos+= 3;
4118 break;
4119 #if !defined(DBUG_OFF) && !defined(MYSQL_CLIENT)
4120 case Q_QUERY_EXEC_TIME:
4121 {
4122 THD *thd= current_thd;
4123 CHECK_SPACE(pos, end, 8);
4124 if (thd)
4125 thd->variables.query_exec_time= uint8korr(pos);
4126 pos+= 8;
4127 break;
4128 }
4129 #endif
4130 case Q_INVOKER:
4131 {
4132 CHECK_SPACE(pos, end, 1);
4133 user.length= *pos++;
4134 CHECK_SPACE(pos, end, user.length);
4135 user.str= (char *)pos;
4136 if (user.length == 0)
4137 user.str= (char *)"";
4138 pos+= user.length;
4139
4140 CHECK_SPACE(pos, end, 1);
4141 host.length= *pos++;
4142 CHECK_SPACE(pos, end, host.length);
4143 host.str= (char *)pos;
4144 if (host.length == 0)
4145 host.str= (char *)"";
4146 pos+= host.length;
4147 break;
4148 }
4149 case Q_UPDATED_DB_NAMES:
4150 {
4151 uchar i= 0;
4152 CHECK_SPACE(pos, end, 1);
4153 mts_accessed_dbs= *pos++;
4154 /*
4155 Notice, the following check is positive also in case of
4156 the master's MAX_DBS_IN_EVENT_MTS > the slave's one and the event
4157 contains e.g the master's MAX_DBS_IN_EVENT_MTS db:s.
4158 */
4159 if (mts_accessed_dbs > MAX_DBS_IN_EVENT_MTS)
4160 {
4161 mts_accessed_dbs= OVER_MAX_DBS_IN_EVENT_MTS;
4162 break;
4163 }
4164
4165 DBUG_ASSERT(mts_accessed_dbs != 0);
4166
4167 for (i= 0; i < mts_accessed_dbs && pos < start + status_vars_len; i++)
4168 {
4169 DBUG_EXECUTE_IF("query_log_event_mts_corrupt_db_names",
4170 {
4171 if (mts_accessed_dbs == 2)
4172 {
4173 DBUG_ASSERT(pos[sizeof("d?") - 1] == 0);
4174 ((char*) pos)[sizeof("d?") - 1]= 'a';
4175 }});
4176 strncpy(mts_accessed_db_names[i], (char*) pos,
4177 min<ulong>(NAME_LEN, start + status_vars_len - pos));
4178 mts_accessed_db_names[i][NAME_LEN - 1]= 0;
4179 pos+= 1 + strlen((const char*) pos);
4180 }
4181 if (i != mts_accessed_dbs || pos > start + status_vars_len)
4182 DBUG_VOID_RETURN;
4183 break;
4184 }
4185 default:
4186 /* That's why you must write status vars in growing order of code */
4187 DBUG_PRINT("info",("Query_log_event has unknown status vars (first has\
4188 code: %u), skipping the rest of them", (uint) *(pos-1)));
4189 pos= (const uchar*) end; // Break loop
4190 }
4191 }
4192
4193 /**
4194 Layout for the data buffer is as follows
4195 +--------+-----------+------+------+---------+----+-------+
4196 | catlog | time_zone | user | host | db name | \0 | Query |
4197 +--------+-----------+------+------+---------+----+-------+
4198
4199 To support the query cache we append the following buffer to the above
4200 +-------+----------------------------------------+-------+
4201 |db len | uninitiatlized space of size of db len | FLAGS |
4202 +-------+----------------------------------------+-------+
4203
4204 The area of buffer starting from Query field all the way to the end belongs
4205 to the Query buffer and its structure is described in alloc_query() in
4206 sql_parse.cc
4207 */
4208
4209 #if !defined(MYSQL_CLIENT) && defined(HAVE_QUERY_CACHE)
4210 if (!(start= data_buf = (Log_event::Byte*) my_malloc(catalog_len + 1
4211 + time_zone_len + 1
4212 + user.length + 1
4213 + host.length + 1
4214 + data_len + 1
4215 + sizeof(size_t)//for db_len
4216 + db_len + 1
4217 + QUERY_CACHE_FLAGS_SIZE,
4218 MYF(MY_WME))))
4219 #else
4220 if (!(start= data_buf = (Log_event::Byte*) my_malloc(catalog_len + 1
4221 + time_zone_len + 1
4222 + user.length + 1
4223 + host.length + 1
4224 + data_len + 1,
4225 MYF(MY_WME))))
4226 #endif
4227 DBUG_VOID_RETURN;
4228 if (catalog_len) // If catalog is given
4229 {
4230 /**
4231 @todo we should clean up and do only copy_str_and_move; it
4232 works for both cases. Then we can remove the catalog_nz
4233 flag. /sven
4234 */
4235 if (likely(catalog_nz)) // true except if event comes from 5.0.0|1|2|3.
4236 copy_str_and_move(&catalog, &start, catalog_len);
4237 else
4238 {
4239 memcpy(start, catalog, catalog_len+1); // copy end 0
4240 catalog= (const char *)start;
4241 start+= catalog_len+1;
4242 }
4243 }
4244 if (time_zone_len)
4245 copy_str_and_move(&time_zone_str, &start, time_zone_len);
4246
4247 if (user.length > 0)
4248 copy_str_and_move((const char **)&(user.str), &start, user.length);
4249 if (host.length > 0)
4250 copy_str_and_move((const char **)&(host.str), &start, host.length);
4251
4252 /**
4253 if time_zone_len or catalog_len are 0, then time_zone and catalog
4254 are uninitialized at this point. shouldn't they point to the
4255 zero-length null-terminated strings we allocated space for in the
4256 my_alloc call above? /sven
4257 */
4258
4259 /* A 2nd variable part; this is common to all versions */
4260 memcpy((char*) start, end, data_len); // Copy db and query
4261 start[data_len]= '\0'; // End query with \0 (For safetly)
4262 db= (char *)start;
4263 query= (char *)(start + db_len + 1);
4264 q_len= data_len - db_len -1;
4265
4266 if (data_len && (data_len < db_len ||
4267 data_len < q_len ||
4268 data_len != (db_len + q_len + 1)))
4269 {
4270 q_len= 0;
4271 query= NULL;
4272 DBUG_VOID_RETURN;
4273 }
4274
4275 unsigned int max_length;
4276 max_length= (event_len - ((const char*)(end + db_len + 1) -
4277 (buf - common_header_len)));
4278 if (q_len != max_length)
4279 {
4280 q_len= 0;
4281 query= NULL;
4282 DBUG_VOID_RETURN;
4283 }
4284 /**
4285 Append the db length at the end of the buffer. This will be used by
4286 Query_cache::send_result_to_client() in case the query cache is On.
4287 */
4288 #if !defined(MYSQL_CLIENT) && defined(HAVE_QUERY_CACHE)
4289 size_t db_length= (size_t)db_len;
4290 memcpy(start + data_len + 1, &db_length, sizeof(size_t));
4291 #endif
4292 DBUG_VOID_RETURN;
4293 }
4294
4295
4296 #ifdef MYSQL_CLIENT
4297 /**
4298 Query_log_event::print().
4299
4300 @todo
4301 print the catalog ??
4302 */
print_query_header(IO_CACHE * file,PRINT_EVENT_INFO * print_event_info)4303 void Query_log_event::print_query_header(IO_CACHE* file,
4304 PRINT_EVENT_INFO* print_event_info)
4305 {
4306 // TODO: print the catalog ??
4307 char buff[48], *end; // Enough for "SET TIMESTAMP=1305535348.123456"
4308 char quoted_id[1+ 2*FN_REFLEN+ 2];
4309 int quoted_len= 0;
4310 bool different_db= 1;
4311 uint32 tmp;
4312
4313 if (!print_event_info->short_form)
4314 {
4315 print_header(file, print_event_info, FALSE);
4316 my_b_printf(file, "\t%s\tthread_id=%lu\texec_time=%lu\terror_code=%d\n",
4317 get_type_str(), (ulong) thread_id, (ulong) exec_time,
4318 error_code);
4319 }
4320
4321 if ((flags & LOG_EVENT_SUPPRESS_USE_F))
4322 {
4323 if (!is_trans_keyword())
4324 print_event_info->db[0]= '\0';
4325 }
4326 else if (db)
4327 {
4328 #ifdef MYSQL_SERVER
4329 quoted_len= my_strmov_quoted_identifier(this->thd, (char*)quoted_id, db, 0);
4330 #else
4331 quoted_len= my_strmov_quoted_identifier((char*)quoted_id, db);
4332 #endif
4333 quoted_id[quoted_len]= '\0';
4334 different_db= memcmp(print_event_info->db, db, db_len + 1);
4335 if (different_db)
4336 memcpy(print_event_info->db, db, db_len + 1);
4337 if (db[0] && different_db)
4338 my_b_printf(file, "use %s%s\n", quoted_id, print_event_info->delimiter);
4339 }
4340
4341 end=int10_to_str((long) when.tv_sec, strmov(buff,"SET TIMESTAMP="),10);
4342 if (when.tv_usec)
4343 end+= sprintf(end, ".%06d", (int) when.tv_usec);
4344 end= strmov(end, print_event_info->delimiter);
4345 *end++='\n';
4346 DBUG_ASSERT(end < buff + sizeof(buff));
4347 my_b_write(file, (uchar*) buff, (uint) (end-buff));
4348 if ((!print_event_info->thread_id_printed ||
4349 ((flags & LOG_EVENT_THREAD_SPECIFIC_F) &&
4350 thread_id != print_event_info->thread_id)))
4351 {
4352 // If --short-form, print deterministic value instead of pseudo_thread_id.
4353 my_b_printf(file,"SET @@session.pseudo_thread_id=%lu%s\n",
4354 short_form ? 999999999 : (ulong)thread_id,
4355 print_event_info->delimiter);
4356 print_event_info->thread_id= thread_id;
4357 print_event_info->thread_id_printed= 1;
4358 }
4359
4360 /*
4361 If flags2_inited==0, this is an event from 3.23 or 4.0; nothing to
4362 print (remember we don't produce mixed relay logs so there cannot be
4363 5.0 events before that one so there is nothing to reset).
4364 */
4365 if (likely(flags2_inited)) /* likely as this will mainly read 5.0 logs */
4366 {
4367 /* tmp is a bitmask of bits which have changed. */
4368 if (likely(print_event_info->flags2_inited))
4369 /* All bits which have changed */
4370 tmp= (print_event_info->flags2) ^ flags2;
4371 else /* that's the first Query event we read */
4372 {
4373 print_event_info->flags2_inited= 1;
4374 tmp= ~((uint32)0); /* all bits have changed */
4375 }
4376
4377 if (unlikely(tmp)) /* some bits have changed */
4378 {
4379 bool need_comma= 0;
4380 my_b_printf(file, "SET ");
4381 print_set_option(file, tmp, OPTION_NO_FOREIGN_KEY_CHECKS, ~flags2,
4382 "@@session.foreign_key_checks", &need_comma);
4383 print_set_option(file, tmp, OPTION_AUTO_IS_NULL, flags2,
4384 "@@session.sql_auto_is_null", &need_comma);
4385 print_set_option(file, tmp, OPTION_RELAXED_UNIQUE_CHECKS, ~flags2,
4386 "@@session.unique_checks", &need_comma);
4387 print_set_option(file, tmp, OPTION_NOT_AUTOCOMMIT, ~flags2,
4388 "@@session.autocommit", &need_comma);
4389 my_b_printf(file,"%s\n", print_event_info->delimiter);
4390 print_event_info->flags2= flags2;
4391 }
4392 }
4393
4394 /*
4395 Now the session variables;
4396 it's more efficient to pass SQL_MODE as a number instead of a
4397 comma-separated list.
4398 FOREIGN_KEY_CHECKS, SQL_AUTO_IS_NULL, UNIQUE_CHECKS are session-only
4399 variables (they have no global version; they're not listed in
4400 sql_class.h), The tests below work for pure binlogs or pure relay
4401 logs. Won't work for mixed relay logs but we don't create mixed
4402 relay logs (that is, there is no relay log with a format change
4403 except within the 3 first events, which mysqlbinlog handles
4404 gracefully). So this code should always be good.
4405 */
4406
4407 if (likely(sql_mode_inited) &&
4408 (unlikely(print_event_info->sql_mode != sql_mode ||
4409 !print_event_info->sql_mode_inited)))
4410 {
4411 my_b_printf(file,"SET @@session.sql_mode=%lu%s\n",
4412 (ulong)sql_mode, print_event_info->delimiter);
4413 print_event_info->sql_mode= sql_mode;
4414 print_event_info->sql_mode_inited= 1;
4415 }
4416 if (print_event_info->auto_increment_increment != auto_increment_increment ||
4417 print_event_info->auto_increment_offset != auto_increment_offset)
4418 {
4419 my_b_printf(file,"SET @@session.auto_increment_increment=%lu, @@session.auto_increment_offset=%lu%s\n",
4420 auto_increment_increment,auto_increment_offset,
4421 print_event_info->delimiter);
4422 print_event_info->auto_increment_increment= auto_increment_increment;
4423 print_event_info->auto_increment_offset= auto_increment_offset;
4424 }
4425
4426 /* TODO: print the catalog when we feature SET CATALOG */
4427
4428 if (likely(charset_inited) &&
4429 (unlikely(!print_event_info->charset_inited ||
4430 memcmp(print_event_info->charset, charset, 6))))
4431 {
4432 char *charset_p= charset; // Avoid type-punning warning.
4433 CHARSET_INFO *cs_info= get_charset(uint2korr(charset_p), MYF(MY_WME));
4434 if (cs_info)
4435 {
4436 /* for mysql client */
4437 my_b_printf(file, "/*!\\C %s */%s\n",
4438 cs_info->csname, print_event_info->delimiter);
4439 }
4440 my_b_printf(file,"SET "
4441 "@@session.character_set_client=%d,"
4442 "@@session.collation_connection=%d,"
4443 "@@session.collation_server=%d"
4444 "%s\n",
4445 uint2korr(charset_p),
4446 uint2korr(charset+2),
4447 uint2korr(charset+4),
4448 print_event_info->delimiter);
4449 memcpy(print_event_info->charset, charset, 6);
4450 print_event_info->charset_inited= 1;
4451 }
4452 if (time_zone_len)
4453 {
4454 if (memcmp(print_event_info->time_zone_str,
4455 time_zone_str, time_zone_len+1))
4456 {
4457 my_b_printf(file,"SET @@session.time_zone='%s'%s\n",
4458 time_zone_str, print_event_info->delimiter);
4459 memcpy(print_event_info->time_zone_str, time_zone_str, time_zone_len+1);
4460 }
4461 }
4462 if (lc_time_names_number != print_event_info->lc_time_names_number)
4463 {
4464 my_b_printf(file, "SET @@session.lc_time_names=%d%s\n",
4465 lc_time_names_number, print_event_info->delimiter);
4466 print_event_info->lc_time_names_number= lc_time_names_number;
4467 }
4468 if (charset_database_number != print_event_info->charset_database_number)
4469 {
4470 if (charset_database_number)
4471 my_b_printf(file, "SET @@session.collation_database=%d%s\n",
4472 charset_database_number, print_event_info->delimiter);
4473 else
4474 my_b_printf(file, "SET @@session.collation_database=DEFAULT%s\n",
4475 print_event_info->delimiter);
4476 print_event_info->charset_database_number= charset_database_number;
4477 }
4478 }
4479
4480
print(FILE * file,PRINT_EVENT_INFO * print_event_info)4481 void Query_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
4482 {
4483 IO_CACHE *const head= &print_event_info->head_cache;
4484
4485 /**
4486 reduce the size of io cache so that the write function is called
4487 for every call to my_b_write().
4488 */
4489 DBUG_EXECUTE_IF ("simulate_file_write_error",
4490 {head->write_pos= head->write_end- 500;});
4491 print_query_header(head, print_event_info);
4492 my_b_write(head, (uchar*) query, q_len);
4493 my_b_printf(head, "\n%s\n", print_event_info->delimiter);
4494 }
4495 #endif /* MYSQL_CLIENT */
4496
4497 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
4498
4499 /**
4500 Associating slave Worker thread to a subset of temporary tables
4501 belonging to db-partitions the event accesses.
4502 The pointer if all entries is cleaned.
4503
4504 @param thd THD instance pointer
4505 */
attach_temp_tables_worker(THD * thd)4506 void Query_log_event::attach_temp_tables_worker(THD *thd)
4507 {
4508 if (!is_mts_worker(thd) || (ends_group() || starts_group()))
4509 return;
4510
4511 // in over max-db:s case just one special partition is locked
4512 int parts= ((mts_accessed_dbs == OVER_MAX_DBS_IN_EVENT_MTS) ?
4513 1 : mts_accessed_dbs);
4514
4515 DBUG_ASSERT(!thd->temporary_tables);
4516
4517 for (int i= 0; i < parts; i++)
4518 {
4519 mts_move_temp_tables_to_thd(thd,
4520 mts_assigned_partitions[i]->temporary_tables);
4521 mts_assigned_partitions[i]->temporary_tables= NULL;
4522 }
4523 }
4524
4525 /**
4526 Dissociating slave Worker thread from its thd->temporary_tables
4527 to possibly update the involved entries of db-to-worker hash
4528 with new values of temporary_tables.
4529
4530 @param thd THD instance pointer
4531 */
detach_temp_tables_worker(THD * thd)4532 void Query_log_event::detach_temp_tables_worker(THD *thd)
4533 {
4534 if (!is_mts_worker(thd))
4535 return;
4536
4537 int parts= ((mts_accessed_dbs == OVER_MAX_DBS_IN_EVENT_MTS) ?
4538 1 : mts_accessed_dbs);
4539 /*
4540 todo: optimize for a case of
4541
4542 a. one db
4543 Only detaching temporary_tables from thd to entry would require
4544 instead of the double-loop below.
4545
4546 b. unchanged thd->temporary_tables.
4547 In such case the involved entries would continue to hold the
4548 unmodified lists provided that the attach_ method does not
4549 destroy references to them.
4550 */
4551 for (int i= 0; i < parts; i++)
4552 {
4553 mts_assigned_partitions[i]->temporary_tables= NULL;
4554 }
4555
4556 for (TABLE *table= thd->temporary_tables; table;)
4557 {
4558 int i;
4559 char *db_name= NULL;
4560
4561 // find which entry to go
4562 for (i= 0; i < parts; i++)
4563 {
4564 db_name= mts_accessed_db_names[i];
4565
4566 if (!strlen(db_name))
4567 break;
4568
4569 // Only default database is rewritten.
4570 if (!rpl_filter->is_rewrite_empty() && !strcmp(get_db(), db_name))
4571 {
4572 size_t dummy_len;
4573 const char *db_filtered= rpl_filter->get_rewrite_db(db_name, &dummy_len);
4574 // db_name != db_filtered means that db_name is rewritten.
4575 if (strcmp(db_name, db_filtered))
4576 db_name= (char*)db_filtered;
4577 }
4578
4579 if (strcmp(table->s->db.str, db_name) < 0)
4580 continue;
4581 else
4582 {
4583 // When rewrite db rules are used we can not rely on
4584 // mts_accessed_db_names elements order.
4585 if (!rpl_filter->is_rewrite_empty() &&
4586 strcmp(table->s->db.str, db_name))
4587 continue;
4588 else
4589 break;
4590 }
4591 }
4592
4593 DBUG_ASSERT(db_name && (
4594 !strcmp(table->s->db.str, db_name) ||
4595 !strlen(db_name))
4596 );
4597 DBUG_ASSERT(i < mts_accessed_dbs);
4598
4599 // table pointer is shifted inside the function
4600 table= mts_move_temp_table_to_entry(table, thd, mts_assigned_partitions[i]);
4601 }
4602
4603 DBUG_ASSERT(!thd->temporary_tables);
4604 #ifndef DBUG_OFF
4605 for (int i= 0; i < parts; i++)
4606 {
4607 DBUG_ASSERT(!mts_assigned_partitions[i]->temporary_tables ||
4608 !mts_assigned_partitions[i]->temporary_tables->prev);
4609 }
4610 #endif
4611 }
4612
4613 /*
4614 Query_log_event::do_apply_event()
4615 */
do_apply_event(Relay_log_info const * rli)4616 int Query_log_event::do_apply_event(Relay_log_info const *rli)
4617 {
4618 return do_apply_event(rli, query, q_len);
4619 }
4620
4621 /*
4622 is_silent_error
4623
4624 Return true if the thread has an error which should be
4625 handled silently
4626 */
4627
is_silent_error(THD * thd)4628 static bool is_silent_error(THD* thd)
4629 {
4630 DBUG_ENTER("is_silent_error");
4631 Diagnostics_area::Sql_condition_iterator it=
4632 thd->get_stmt_da()->sql_conditions();
4633 const Sql_condition *err;
4634 while ((err= it++))
4635 {
4636 DBUG_PRINT("info", ("has condition %d %s", err->get_sql_errno(),
4637 err->get_message_text()));
4638 switch (err->get_sql_errno())
4639 {
4640 case ER_SLAVE_SILENT_RETRY_TRANSACTION:
4641 {
4642 DBUG_RETURN(true);
4643 }
4644 default:
4645 break;
4646 }
4647 }
4648 DBUG_RETURN(false);
4649 }
4650
4651 /**
4652 @todo
4653 Compare the values of "affected rows" around here. Something
4654 like:
4655 @code
4656 if ((uint32) affected_in_event != (uint32) affected_on_slave)
4657 {
4658 sql_print_error("Slave: did not get the expected number of affected \
4659 rows running query from master - expected %d, got %d (this numbers \
4660 should have matched modulo 4294967296).", 0, ...);
4661 thd->query_error = 1;
4662 }
4663 @endcode
4664 We may also want an option to tell the slave to ignore "affected"
4665 mismatch. This mismatch could be implemented with a new ER_ code, and
4666 to ignore it you would use --slave-skip-errors...
4667 */
do_apply_event(Relay_log_info const * rli,const char * query_arg,uint32 q_len_arg)4668 int Query_log_event::do_apply_event(Relay_log_info const *rli,
4669 const char *query_arg, uint32 q_len_arg)
4670 {
4671 DBUG_ENTER("Query_log_event::do_apply_event");
4672 int expected_error,actual_error= 0;
4673 HA_CREATE_INFO db_options;
4674
4675 /*
4676 Colleagues: please never free(thd->catalog) in MySQL. This would
4677 lead to bugs as here thd->catalog is a part of an alloced block,
4678 not an entire alloced block (see
4679 Query_log_event::do_apply_event()). Same for thd->db. Thank
4680 you.
4681 */
4682 thd->catalog= catalog_len ? (char *) catalog : (char *)"";
4683
4684 size_t valid_len;
4685 bool len_error;
4686 bool is_invalid_db_name= validate_string(system_charset_info, db, db_len,
4687 &valid_len, &len_error);
4688
4689 DBUG_PRINT("debug",("is_invalid_db_name= %s, valid_len=%zu, len_error=%s",
4690 is_invalid_db_name ? "true" : "false",
4691 valid_len,
4692 len_error ? "true" : "false"));
4693
4694 if (is_invalid_db_name || len_error)
4695 {
4696 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
4697 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
4698 "Invalid database name in Query event.");
4699 thd->is_slave_error= true;
4700 goto end;
4701 }
4702
4703 set_thd_db(thd, db, db_len);
4704
4705 /*
4706 Setting the character set and collation of the current database thd->db.
4707 */
4708 load_db_opt_by_name(thd, thd->db, &db_options);
4709 if (db_options.default_table_charset)
4710 thd->db_charset= db_options.default_table_charset;
4711 thd->variables.auto_increment_increment= auto_increment_increment;
4712 thd->variables.auto_increment_offset= auto_increment_offset;
4713
4714 /*
4715 InnoDB internally stores the master log position it has executed so far,
4716 i.e. the position just after the COMMIT event.
4717 When InnoDB will want to store, the positions in rli won't have
4718 been updated yet, so group_master_log_* will point to old BEGIN
4719 and event_master_log* will point to the beginning of current COMMIT.
4720 But log_pos of the COMMIT Query event is what we want, i.e. the pos of the
4721 END of the current log event (COMMIT). We save it in rli so that InnoDB can
4722 access it.
4723 */
4724 const_cast<Relay_log_info*>(rli)->set_future_group_master_log_pos(log_pos);
4725 DBUG_PRINT("info", ("log_pos: %lu", (ulong) log_pos));
4726
4727 /*
4728 todo: such cleanup should not be specific to Query event and therefore
4729 is preferable at a common with other event pre-execution point
4730 */
4731 clear_all_errors(thd, const_cast<Relay_log_info*>(rli));
4732 if (strcmp("COMMIT", query) == 0 && rli->tables_to_lock != NULL)
4733 {
4734 /*
4735 Cleaning-up the last statement context:
4736 the terminal event of the current statement flagged with
4737 STMT_END_F got filtered out in ndb circular replication.
4738 */
4739 int error;
4740 char llbuff[22];
4741 if ((error= rows_event_stmt_cleanup(const_cast<Relay_log_info*>(rli), thd)))
4742 {
4743 const_cast<Relay_log_info*>(rli)->report(ERROR_LEVEL, error,
4744 "Error in cleaning up after an event preceeding the commit; "
4745 "the group log file/position: %s %s",
4746 const_cast<Relay_log_info*>(rli)->get_group_master_log_name(),
4747 llstr(const_cast<Relay_log_info*>(rli)->get_group_master_log_pos(),
4748 llbuff));
4749 }
4750 /*
4751 Executing a part of rli->stmt_done() logics that does not deal
4752 with group position change. The part is redundant now but is
4753 future-change-proof addon, e.g if COMMIT handling will start checking
4754 invariants like IN_STMT flag must be off at committing the transaction.
4755 */
4756 const_cast<Relay_log_info*>(rli)->inc_event_relay_log_pos();
4757 const_cast<Relay_log_info*>(rli)->clear_flag(Relay_log_info::IN_STMT);
4758 }
4759 else
4760 {
4761 const_cast<Relay_log_info*>(rli)->slave_close_thread_tables(thd);
4762 }
4763
4764 /*
4765 Note: We do not need to execute reset_one_shot_variables() if this
4766 db_ok() test fails.
4767 Reason: The db stored in binlog events is the same for SET and for
4768 its companion query. If the SET is ignored because of
4769 db_ok(), the companion query will also be ignored, and if
4770 the companion query is ignored in the db_ok() test of
4771 ::do_apply_event(), then the companion SET also have so
4772 we don't need to reset_one_shot_variables().
4773 */
4774 {
4775 thd->set_time(&when);
4776 thd->set_query_and_id((char*)query_arg, q_len_arg,
4777 thd->charset(), next_query_id());
4778 thd->set_query_for_display(query_arg, q_len_arg);
4779 thd->variables.pseudo_thread_id= thread_id; // for temp tables
4780 attach_temp_tables_worker(thd);
4781 DBUG_PRINT("query",("%s", thd->query()));
4782
4783 if (ignored_error_code((expected_error= error_code)) ||
4784 !unexpected_error_code(expected_error))
4785 {
4786 if (flags2_inited)
4787 /*
4788 all bits of thd->variables.option_bits which are 1 in OPTIONS_WRITTEN_TO_BIN_LOG
4789 must take their value from flags2.
4790 */
4791 thd->variables.option_bits= flags2|(thd->variables.option_bits & ~OPTIONS_WRITTEN_TO_BIN_LOG);
4792 /*
4793 else, we are in a 3.23/4.0 binlog; we previously received a
4794 Rotate_log_event which reset thd->variables.option_bits and sql_mode etc, so
4795 nothing to do.
4796 */
4797 /*
4798 We do not replicate MODE_NO_DIR_IN_CREATE. That is, if the master is a
4799 slave which runs with SQL_MODE=MODE_NO_DIR_IN_CREATE, this should not
4800 force us to ignore the dir too. Imagine you are a ring of machines, and
4801 one has a disk problem so that you temporarily need
4802 MODE_NO_DIR_IN_CREATE on this machine; you don't want it to propagate
4803 elsewhere (you don't want all slaves to start ignoring the dirs).
4804 */
4805 if (sql_mode_inited)
4806 thd->variables.sql_mode=
4807 (sql_mode_t) ((thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE) |
4808 (sql_mode & ~(ulonglong) MODE_NO_DIR_IN_CREATE));
4809 if (charset_inited)
4810 {
4811 if (rli->cached_charset_compare(charset))
4812 {
4813 char *charset_p= charset; // Avoid type-punning warning.
4814 /* Verify that we support the charsets found in the event. */
4815 if (!(thd->variables.character_set_client=
4816 get_charset(uint2korr(charset_p), MYF(MY_WME))) ||
4817 !(thd->variables.collation_connection=
4818 get_charset(uint2korr(charset+2), MYF(MY_WME))) ||
4819 !(thd->variables.collation_server=
4820 get_charset(uint2korr(charset+4), MYF(MY_WME))))
4821 {
4822 /*
4823 We updated the thd->variables with nonsensical values (0). Let's
4824 set them to something safe (i.e. which avoids crash), and we'll
4825 stop with EE_UNKNOWN_CHARSET in compare_errors (unless set to
4826 ignore this error).
4827 */
4828 set_slave_thread_default_charset(thd, rli);
4829 goto compare_errors;
4830 }
4831 thd->update_charset(); // for the charset change to take effect
4832 /*
4833 Reset thd->query_string.cs to the newly set value.
4834 Note, there is a small flaw here. For a very short time frame
4835 if the new charset is different from the old charset and
4836 if another thread executes "SHOW PROCESSLIST" after
4837 the above thd->set_query_and_id() and before this thd->set_query(),
4838 and if the current query has some non-ASCII characters,
4839 the another thread may see some '?' marks in the PROCESSLIST
4840 result. This should be acceptable now. This is a reminder
4841 to fix this if any refactoring happens here sometime.
4842 */
4843 thd->set_query((char*) query_arg, q_len_arg, thd->charset());
4844 thd->reset_query_for_display();
4845 }
4846 }
4847 if (time_zone_len)
4848 {
4849 String tmp(time_zone_str, time_zone_len, &my_charset_bin);
4850 if (!(thd->variables.time_zone= my_tz_find(thd, &tmp)))
4851 {
4852 my_error(ER_UNKNOWN_TIME_ZONE, MYF(0), tmp.c_ptr());
4853 thd->variables.time_zone= global_system_variables.time_zone;
4854 goto compare_errors;
4855 }
4856 }
4857 if (lc_time_names_number)
4858 {
4859 if (!(thd->variables.lc_time_names=
4860 my_locale_by_number(lc_time_names_number)))
4861 {
4862 my_printf_error(ER_UNKNOWN_ERROR,
4863 "Unknown locale: '%d'", MYF(0), lc_time_names_number);
4864 thd->variables.lc_time_names= &my_locale_en_US;
4865 goto compare_errors;
4866 }
4867 }
4868 else
4869 thd->variables.lc_time_names= &my_locale_en_US;
4870 if (charset_database_number)
4871 {
4872 CHARSET_INFO *cs;
4873 if (!(cs= get_charset(charset_database_number, MYF(0))))
4874 {
4875 char buf[20];
4876 int10_to_str((int) charset_database_number, buf, -10);
4877 my_error(ER_UNKNOWN_COLLATION, MYF(0), buf);
4878 goto compare_errors;
4879 }
4880 thd->variables.collation_database= cs;
4881 }
4882 else
4883 thd->variables.collation_database= thd->db_charset;
4884
4885 {
4886 const CHARSET_INFO *cs= thd->charset();
4887 /*
4888 We cannot ask for parsing a statement using a character set
4889 without state_maps (parser internal data).
4890 */
4891 if (!cs->state_map)
4892 {
4893 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
4894 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
4895 "character_set cannot be parsed");
4896 thd->is_slave_error= true;
4897 goto end;
4898 }
4899 }
4900
4901 thd->table_map_for_update= (table_map)table_map_for_update;
4902 thd->set_invoker(&user, &host);
4903 /*
4904 Flag if we need to rollback the statement transaction on
4905 slave if it by chance succeeds.
4906 If we expected a non-zero error code and get nothing and,
4907 it is a concurrency issue or ignorable issue, effects
4908 of the statement should be rolled back.
4909 */
4910 if (expected_error &&
4911 (ignored_error_code(expected_error) ||
4912 concurrency_error_code(expected_error)))
4913 {
4914 thd->variables.option_bits|= OPTION_MASTER_SQL_ERROR;
4915 }
4916 /* Execute the query (note that we bypass dispatch_command()) */
4917 Parser_state parser_state;
4918 if (!parser_state.init(thd, thd->query(), thd->query_length()))
4919 {
4920 DBUG_ASSERT(thd->m_digest == NULL);
4921 thd->m_digest= & thd->m_digest_state;
4922 DBUG_ASSERT(thd->m_statement_psi == NULL);
4923 thd->m_statement_psi= MYSQL_START_STATEMENT(&thd->m_statement_state,
4924 stmt_info_rpl.m_key,
4925 thd->db, thd->db_length,
4926 thd->charset());
4927 THD_STAGE_INFO(thd, stage_init);
4928 if (thd->m_digest != NULL)
4929 thd->m_digest->reset(thd->m_token_array, max_digest_length);
4930
4931 mysql_parse(thd, thd->query(), thd->query_length(),
4932 &parser_state, true);
4933 /* Finalize server status flags after executing a statement. */
4934 thd->update_server_status();
4935 log_slow_statement(thd);
4936 }
4937
4938 thd->variables.option_bits&= ~OPTION_MASTER_SQL_ERROR;
4939
4940 /*
4941 Resetting the enable_slow_log thd variable.
4942
4943 We need to reset it back to the opt_log_slow_slave_statements
4944 value after the statement execution (and slow logging
4945 is done). It might have changed if the statement was an
4946 admin statement (in which case, down in mysql_parse execution
4947 thd->enable_slow_log is set to the value of
4948 opt_log_slow_admin_statements).
4949 */
4950 thd->enable_slow_log= TRUE;
4951 }
4952 else
4953 {
4954 /*
4955 The query got a really bad error on the master (thread killed etc),
4956 which could be inconsistent. Parse it to test the table names: if the
4957 replicate-*-do|ignore-table rules say "this query must be ignored" then
4958 we exit gracefully; otherwise we warn about the bad error and tell DBA
4959 to check/fix it.
4960 */
4961 if (mysql_test_parse_for_slave(thd, thd->query(), thd->query_length()))
4962 clear_all_errors(thd, const_cast<Relay_log_info*>(rli)); /* Can ignore query */
4963 else
4964 {
4965 rli->report(ERROR_LEVEL, expected_error,
4966 "\
4967 Query partially completed on the master (error on master: %d) \
4968 and was aborted. There is a chance that your master is inconsistent at this \
4969 point. If you are sure that your master is ok, run this query manually on the \
4970 slave and then restart the slave with SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; \
4971 START SLAVE; . Query: '%s'", expected_error, thd->query());
4972 thd->is_slave_error= 1;
4973 }
4974 goto end;
4975 }
4976
4977 /* If the query was not ignored, it is printed to the general log */
4978 if (!thd->is_error() || thd->get_stmt_da()->sql_errno() != ER_SLAVE_IGNORED_TABLE)
4979 {
4980 /* log the rewritten query if the query was rewritten
4981 and the option to log raw was not set.
4982
4983 There is an assumption here. We assume that query log
4984 events can never have multi-statement queries, thus the
4985 parsed statement is the same as the raw one.
4986 */
4987 if (opt_log_raw || thd->rewritten_query.length() == 0)
4988 general_log_write(thd, COM_QUERY, thd->query(), thd->query_length());
4989 else
4990 general_log_write(thd, COM_QUERY, thd->rewritten_query.c_ptr_safe(),
4991 thd->rewritten_query.length());
4992 }
4993
4994 compare_errors:
4995 /*
4996 In the slave thread, we may sometimes execute some DROP / * 40005
4997 TEMPORARY * / TABLE that come from parts of binlogs (likely if we
4998 use RESET SLAVE or CHANGE MASTER TO), while the temporary table
4999 has already been dropped. To ignore such irrelevant "table does
5000 not exist errors", we silently clear the error if TEMPORARY was used.
5001 */
5002 if (thd->lex->sql_command == SQLCOM_DROP_TABLE && thd->lex->drop_temporary &&
5003 thd->is_error() && thd->get_stmt_da()->sql_errno() == ER_BAD_TABLE_ERROR &&
5004 !expected_error)
5005 thd->get_stmt_da()->reset_diagnostics_area();
5006 /*
5007 If we expected a non-zero error code, and we don't get the same error
5008 code, and it should be ignored or is related to a concurrency issue.
5009 */
5010 actual_error= thd->is_error() ? thd->get_stmt_da()->sql_errno() : 0;
5011 DBUG_PRINT("info",("expected_error: %d sql_errno: %d",
5012 expected_error, actual_error));
5013
5014 /*
5015 If a statement with expected error is received on slave and if the
5016 statement is not filtered on the slave, only then compare the expected
5017 error with the actual error that happened on slave.
5018 */
5019 if ((expected_error && rpl_filter->db_ok(thd->db) &&
5020 expected_error != actual_error &&
5021 !concurrency_error_code(expected_error)) &&
5022 !ignored_error_code(actual_error) &&
5023 !ignored_error_code(expected_error))
5024 {
5025 rli->report(ERROR_LEVEL, 0,
5026 "\
5027 Query caused different errors on master and slave. \
5028 Error on master: message (format)='%s' error code=%d ; \
5029 Error on slave: actual message='%s', error code=%d. \
5030 Default database: '%s'. Query: '%s'",
5031 ER_SAFE(expected_error),
5032 expected_error,
5033 actual_error ? thd->get_stmt_da()->message() : "no error",
5034 actual_error,
5035 print_slave_db_safe(db), query_arg);
5036 thd->is_slave_error= 1;
5037 }
5038 /*
5039 If we get the same error code as expected and it is not a concurrency
5040 issue, or should be ignored.
5041 */
5042 else if ((expected_error == actual_error &&
5043 !concurrency_error_code(expected_error)) ||
5044 ignored_error_code(actual_error))
5045 {
5046 DBUG_PRINT("info",("error ignored"));
5047 if (actual_error && log_warnings > 1 && ignored_error_code(actual_error))
5048 {
5049 if (actual_error == ER_SLAVE_IGNORED_TABLE)
5050 {
5051 if (!slave_ignored_err_throttle.log(thd))
5052 rli->report(WARNING_LEVEL, actual_error,
5053 "Could not execute %s event. Detailed error: %s;"
5054 " Error log throttle is enabled. This error will not be"
5055 " displayed for next %lu secs. It will be suppressed",
5056 get_type_str(), thd->get_stmt_da()->message(),
5057 (window_size / 1000000));
5058 }
5059 else
5060 rli->report(WARNING_LEVEL, actual_error,
5061 "Could not execute %s event. Detailed error: %s;",
5062 get_type_str(), thd->get_stmt_da()->message());
5063 }
5064 clear_all_errors(thd, const_cast<Relay_log_info*>(rli));
5065 thd->killed= THD::NOT_KILLED;
5066 }
5067 /*
5068 Other cases: mostly we expected no error and get one.
5069 */
5070 else if (thd->is_slave_error || thd->is_fatal_error)
5071 {
5072 if (!is_silent_error(thd))
5073 {
5074 rli->report(ERROR_LEVEL, actual_error,
5075 "Error '%s' on query. Default database: '%s'. Query: '%s'",
5076 (actual_error ? thd->get_stmt_da()->message() :
5077 "unexpected success or fatal error"),
5078 print_slave_db_safe(thd->db), query_arg);
5079 }
5080 thd->is_slave_error= 1;
5081 }
5082
5083 /*
5084 TODO: compare the values of "affected rows" around here. Something
5085 like:
5086 if ((uint32) affected_in_event != (uint32) affected_on_slave)
5087 {
5088 sql_print_error("Slave: did not get the expected number of affected \
5089 rows running query from master - expected %d, got %d (this numbers \
5090 should have matched modulo 4294967296).", 0, ...);
5091 thd->is_slave_error = 1;
5092 }
5093 We may also want an option to tell the slave to ignore "affected"
5094 mismatch. This mismatch could be implemented with a new ER_ code, and
5095 to ignore it you would use --slave-skip-errors...
5096
5097 To do the comparison we need to know the value of "affected" which the
5098 above mysql_parse() computed. And we need to know the value of
5099 "affected" in the master's binlog. Both will be implemented later. The
5100 important thing is that we now have the format ready to log the values
5101 of "affected" in the binlog. So we can release 5.0.0 before effectively
5102 logging "affected" and effectively comparing it.
5103 */
5104 } /* End of if (db_ok(... */
5105
5106 {
5107 /**
5108 The following failure injecion works in cooperation with tests
5109 setting @@global.debug= 'd,stop_slave_middle_group'.
5110 The sql thread receives the killed status and will proceed
5111 to shutdown trying to finish incomplete events group.
5112 */
5113
5114 // TODO: address the middle-group killing in MTS case
5115
5116 DBUG_EXECUTE_IF("stop_slave_middle_group",
5117 if (strcmp("COMMIT", query) != 0 &&
5118 strcmp("BEGIN", query) != 0)
5119 {
5120 if (thd->transaction.all.cannot_safely_rollback())
5121 const_cast<Relay_log_info*>(rli)->abort_slave= 1;
5122 };);
5123 }
5124
5125 end:
5126
5127 if (thd->temporary_tables)
5128 detach_temp_tables_worker(thd);
5129 /*
5130 Probably we have set thd->query, thd->db, thd->catalog to point to places
5131 in the data_buf of this event. Now the event is going to be deleted
5132 probably, so data_buf will be freed, so the thd->... listed above will be
5133 pointers to freed memory.
5134 So we must set them to 0, so that those bad pointers values are not later
5135 used. Note that "cleanup" queries like automatic DROP TEMPORARY TABLE
5136 don't suffer from these assignments to 0 as DROP TEMPORARY
5137 TABLE uses the db.table syntax.
5138 */
5139 thd->catalog= 0;
5140 thd->set_db(NULL, 0); /* will free the current database */
5141 thd->reset_query();
5142 thd->lex->sql_command= SQLCOM_END;
5143 DBUG_PRINT("info", ("end: query= 0"));
5144
5145 /* Mark the statement completed. */
5146 MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da());
5147 thd->m_statement_psi= NULL;
5148 thd->m_digest= NULL;
5149
5150 /*
5151 As a disk space optimization, future masters will not log an event for
5152 LAST_INSERT_ID() if that function returned 0 (and thus they will be able
5153 to replace the THD::stmt_depends_on_first_successful_insert_id_in_prev_stmt
5154 variable by (THD->first_successful_insert_id_in_prev_stmt > 0) ; with the
5155 resetting below we are ready to support that.
5156 */
5157 thd->first_successful_insert_id_in_prev_stmt_for_binlog= 0;
5158 thd->first_successful_insert_id_in_prev_stmt= 0;
5159 thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
5160 free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
5161 DBUG_RETURN(thd->is_slave_error);
5162 }
5163
do_update_pos(Relay_log_info * rli)5164 int Query_log_event::do_update_pos(Relay_log_info *rli)
5165 {
5166 /*
5167 Note that we will not increment group* positions if we are just
5168 after a SET ONE_SHOT, because SET ONE_SHOT should not be separated
5169 from its following updating query.
5170 */
5171 int ret= 0;
5172 if (thd->one_shot_set)
5173 {
5174 rli->inc_event_relay_log_pos();
5175 }
5176 else
5177 ret= Log_event::do_update_pos(rli);
5178
5179 DBUG_EXECUTE_IF("crash_after_commit_and_update_pos",
5180 if (!strcmp("COMMIT", query))
5181 {
5182 sql_print_information("Crashing crash_after_commit_and_update_pos.");
5183 rli->flush_info(true);
5184 ha_flush_logs(0);
5185 DBUG_SUICIDE();
5186 }
5187 );
5188
5189 return ret;
5190 }
5191
5192
5193 Log_event::enum_skip_reason
do_shall_skip(Relay_log_info * rli)5194 Query_log_event::do_shall_skip(Relay_log_info *rli)
5195 {
5196 DBUG_ENTER("Query_log_event::do_shall_skip");
5197 DBUG_PRINT("debug", ("query: %s; q_len: %d", query, q_len));
5198 DBUG_ASSERT(query && q_len > 0);
5199
5200 if (rli->slave_skip_counter > 0)
5201 {
5202 if (strcmp("BEGIN", query) == 0)
5203 {
5204 thd->variables.option_bits|= OPTION_BEGIN;
5205 DBUG_RETURN(Log_event::continue_group(rli));
5206 }
5207
5208 if (strcmp("COMMIT", query) == 0 || strcmp("ROLLBACK", query) == 0)
5209 {
5210 thd->variables.option_bits&= ~OPTION_BEGIN;
5211 DBUG_RETURN(Log_event::EVENT_SKIP_COUNT);
5212 }
5213 }
5214 DBUG_RETURN(Log_event::do_shall_skip(rli));
5215 }
5216
5217 #endif
5218
5219
5220 /**************************************************************************
5221 Start_log_event_v3 methods
5222 **************************************************************************/
5223
5224 #ifndef MYSQL_CLIENT
Start_log_event_v3()5225 Start_log_event_v3::Start_log_event_v3()
5226 :Log_event(), created(0), binlog_version(BINLOG_VERSION),
5227 dont_set_created(0)
5228 {
5229 memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
5230 }
5231 #endif
5232
5233 /*
5234 Start_log_event_v3::pack_info()
5235 */
5236
5237 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
pack_info(Protocol * protocol)5238 int Start_log_event_v3::pack_info(Protocol *protocol)
5239 {
5240 char buf[12 + ST_SERVER_VER_LEN + 14 + 22], *pos;
5241 pos= strmov(buf, "Server ver: ");
5242 pos= strmov(pos, server_version);
5243 pos= strmov(pos, ", Binlog ver: ");
5244 pos= int10_to_str(binlog_version, pos, 10);
5245 protocol->store(buf, (uint) (pos-buf), &my_charset_bin);
5246 return 0;
5247 }
5248 #endif
5249
5250
5251 /*
5252 Start_log_event_v3::print()
5253 */
5254
5255 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)5256 void Start_log_event_v3::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
5257 {
5258 DBUG_ENTER("Start_log_event_v3::print");
5259
5260 IO_CACHE *const head= &print_event_info->head_cache;
5261
5262 if (!print_event_info->short_form)
5263 {
5264 print_header(head, print_event_info, FALSE);
5265 my_b_printf(head, "\tStart: binlog v %d, server v %s created ",
5266 binlog_version, server_version);
5267 print_timestamp(head, NULL);
5268 if (created)
5269 my_b_printf(head," at startup");
5270 my_b_printf(head, "\n");
5271 if (flags & LOG_EVENT_BINLOG_IN_USE_F)
5272 my_b_printf(head, "# Warning: this binlog is either in use or was not "
5273 "closed properly.\n");
5274 }
5275 if (!is_artificial_event() && created)
5276 {
5277 #ifdef WHEN_WE_HAVE_THE_RESET_CONNECTION_SQL_COMMAND
5278 /*
5279 This is for mysqlbinlog: like in replication, we want to delete the stale
5280 tmp files left by an unclean shutdown of mysqld (temporary tables)
5281 and rollback unfinished transaction.
5282 Probably this can be done with RESET CONNECTION (syntax to be defined).
5283 */
5284 my_b_printf(head,"RESET CONNECTION%s\n", print_event_info->delimiter);
5285 #else
5286 my_b_printf(head,"ROLLBACK%s\n", print_event_info->delimiter);
5287 if (print_event_info->is_gtid_next_set)
5288 print_event_info->is_gtid_next_valid= false;
5289 #endif
5290 }
5291 // set gtid_next=automatic if we have previously set it to uuid:number
5292 if (!print_event_info->is_gtid_next_valid)
5293 {
5294 my_b_printf(head, "%sAUTOMATIC'%s\n",
5295 Gtid_log_event::SET_STRING_PREFIX,
5296 print_event_info->delimiter);
5297 print_event_info->is_gtid_next_set= false;
5298 print_event_info->is_gtid_next_valid= true;
5299 }
5300 if (temp_buf &&
5301 print_event_info->base64_output_mode != BASE64_OUTPUT_NEVER &&
5302 !print_event_info->short_form)
5303 {
5304 if (print_event_info->base64_output_mode != BASE64_OUTPUT_DECODE_ROWS)
5305 my_b_printf(head, "BINLOG '\n");
5306 print_base64(head, print_event_info, FALSE);
5307 print_event_info->printed_fd_event= TRUE;
5308 }
5309 DBUG_VOID_RETURN;
5310 }
5311 #endif /* MYSQL_CLIENT */
5312
5313 /*
5314 Start_log_event_v3::Start_log_event_v3()
5315 */
5316
Start_log_event_v3(const char * buf,uint event_len,const Format_description_log_event * description_event)5317 Start_log_event_v3::Start_log_event_v3(const char* buf, uint event_len,
5318 const Format_description_log_event
5319 *description_event)
5320 :Log_event(buf, description_event), binlog_version(BINLOG_VERSION)
5321 {
5322 if (event_len < (uint)description_event->common_header_len +
5323 ST_COMMON_HEADER_LEN_OFFSET)
5324 {
5325 server_version[0]= 0;
5326 return;
5327 }
5328 buf+= description_event->common_header_len;
5329 binlog_version= uint2korr(buf+ST_BINLOG_VER_OFFSET);
5330 memcpy(server_version, buf+ST_SERVER_VER_OFFSET,
5331 ST_SERVER_VER_LEN);
5332 // prevent overrun if log is corrupted on disk
5333 server_version[ST_SERVER_VER_LEN-1]= 0;
5334 created= uint4korr(buf+ST_CREATED_OFFSET);
5335 dont_set_created= 1;
5336 }
5337
5338
5339 /*
5340 Start_log_event_v3::write()
5341 */
5342
5343 #ifndef MYSQL_CLIENT
write(IO_CACHE * file)5344 bool Start_log_event_v3::write(IO_CACHE* file)
5345 {
5346 char buff[START_V3_HEADER_LEN];
5347 int2store(buff + ST_BINLOG_VER_OFFSET,binlog_version);
5348 memcpy(buff + ST_SERVER_VER_OFFSET,server_version,ST_SERVER_VER_LEN);
5349 if (!dont_set_created)
5350 created= get_time();
5351 int4store(buff + ST_CREATED_OFFSET,created);
5352 return (write_header(file, sizeof(buff)) ||
5353 wrapper_my_b_safe_write(file, (uchar*) buff, sizeof(buff)) ||
5354 write_footer(file));
5355 }
5356 #endif
5357
5358
5359 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
5360
5361 /**
5362 Start_log_event_v3::do_apply_event() .
5363 The master started
5364
5365 IMPLEMENTATION
5366 - To handle the case where the master died without having time to write
5367 DROP TEMPORARY TABLE, DO RELEASE_LOCK (prepared statements' deletion is
5368 TODO), we clean up all temporary tables that we got, if we are sure we
5369 can (see below).
5370
5371 @todo
5372 - Remove all active user locks.
5373 Guilhem 2003-06: this is true but not urgent: the worst it can cause is
5374 the use of a bit of memory for a user lock which will not be used
5375 anymore. If the user lock is later used, the old one will be released. In
5376 other words, no deadlock problem.
5377 */
5378
do_apply_event(Relay_log_info const * rli)5379 int Start_log_event_v3::do_apply_event(Relay_log_info const *rli)
5380 {
5381 DBUG_ENTER("Start_log_event_v3::do_apply_event");
5382 int error= 0;
5383 switch (binlog_version)
5384 {
5385 case 3:
5386 case 4:
5387 /*
5388 This can either be 4.x (then a Start_log_event_v3 is only at master
5389 startup so we are sure the master has restarted and cleared his temp
5390 tables; the event always has 'created'>0) or 5.0 (then we have to test
5391 'created').
5392 */
5393 if (created)
5394 {
5395 error= close_temporary_tables(thd);
5396 cleanup_load_tmpdir();
5397 }
5398 else
5399 {
5400 /*
5401 Set all temporary tables thread references to the current thread
5402 as they may point to the "old" SQL slave thread in case of its
5403 restart.
5404 */
5405 TABLE *table;
5406 for (table= thd->temporary_tables; table; table= table->next)
5407 table->in_use= thd;
5408 }
5409 break;
5410
5411 /*
5412 Now the older formats; in that case load_tmpdir is cleaned up by the I/O
5413 thread.
5414 */
5415 case 1:
5416 if (strncmp(rli->get_rli_description_event()->server_version,
5417 "3.23.57",7) >= 0 && created)
5418 {
5419 /*
5420 Can distinguish, based on the value of 'created': this event was
5421 generated at master startup.
5422 */
5423 error= close_temporary_tables(thd);
5424 }
5425 /*
5426 Otherwise, can't distinguish a Start_log_event generated at
5427 master startup and one generated by master FLUSH LOGS, so cannot
5428 be sure temp tables have to be dropped. So do nothing.
5429 */
5430 break;
5431 default:
5432 /*
5433 This case is not expected. It can be either an event corruption or an
5434 unsupported binary log version.
5435 */
5436 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
5437 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
5438 "Binlog version not supported");
5439 DBUG_RETURN(1);
5440 }
5441 DBUG_RETURN(error);
5442 }
5443 #endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
5444
5445 /***************************************************************************
5446 Format_description_log_event methods
5447 ****************************************************************************/
5448
5449 /**
5450 Format_description_log_event 1st ctor.
5451
5452 Ctor. Can be used to create the event to write to the binary log (when the
5453 server starts or when FLUSH LOGS), or to create artificial events to parse
5454 binlogs from MySQL 3.23 or 4.x.
5455 When in a client, only the 2nd use is possible.
5456
5457 @param binlog_version the binlog version for which we want to build
5458 an event. Can be 1 (=MySQL 3.23), 3 (=4.0.x
5459 x>=2 and 4.1) or 4 (MySQL 5.0). Note that the
5460 old 4.0 (binlog version 2) is not supported;
5461 it should not be used for replication with
5462 5.0.
5463 @param server_ver a string containing the server version.
5464 */
5465
5466 Format_description_log_event::
Format_description_log_event(uint8 binlog_ver,const char * server_ver)5467 Format_description_log_event(uint8 binlog_ver, const char* server_ver)
5468 :Start_log_event_v3(), event_type_permutation(0)
5469 {
5470 binlog_version= binlog_ver;
5471 switch (binlog_ver) {
5472 case 4: /* MySQL 5.0 */
5473 memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
5474 DBUG_EXECUTE_IF("pretend_version_50034_in_binlog",
5475 strmov(server_version, "5.0.34"););
5476 common_header_len= LOG_EVENT_HEADER_LEN;
5477 number_of_event_types= LOG_EVENT_TYPES;
5478 /* we'll catch my_malloc() error in is_valid() */
5479 post_header_len=(uint8*) my_malloc(number_of_event_types*sizeof(uint8)
5480 + BINLOG_CHECKSUM_ALG_DESC_LEN,
5481 MYF(0));
5482 /*
5483 This long list of assignments is not beautiful, but I see no way to
5484 make it nicer, as the right members are #defines, not array members, so
5485 it's impossible to write a loop.
5486 */
5487 if (post_header_len)
5488 {
5489 #ifndef DBUG_OFF
5490 // Allows us to sanity-check that all events initialized their
5491 // events (see the end of this 'if' block).
5492 memset(post_header_len, 255, number_of_event_types*sizeof(uint8));
5493 #endif
5494
5495 /* Note: all event types must explicitly fill in their lengths here. */
5496 post_header_len[START_EVENT_V3-1]= START_V3_HEADER_LEN;
5497 post_header_len[QUERY_EVENT-1]= QUERY_HEADER_LEN;
5498 post_header_len[STOP_EVENT-1]= STOP_HEADER_LEN;
5499 post_header_len[ROTATE_EVENT-1]= ROTATE_HEADER_LEN;
5500 post_header_len[INTVAR_EVENT-1]= INTVAR_HEADER_LEN;
5501 post_header_len[LOAD_EVENT-1]= LOAD_HEADER_LEN;
5502 post_header_len[SLAVE_EVENT-1]= 0; /* Unused because the code for Slave log event was removed. (15th Oct. 2010) */
5503 post_header_len[CREATE_FILE_EVENT-1]= CREATE_FILE_HEADER_LEN;
5504 post_header_len[APPEND_BLOCK_EVENT-1]= APPEND_BLOCK_HEADER_LEN;
5505 post_header_len[EXEC_LOAD_EVENT-1]= EXEC_LOAD_HEADER_LEN;
5506 post_header_len[DELETE_FILE_EVENT-1]= DELETE_FILE_HEADER_LEN;
5507 post_header_len[NEW_LOAD_EVENT-1]= NEW_LOAD_HEADER_LEN;
5508 post_header_len[RAND_EVENT-1]= RAND_HEADER_LEN;
5509 post_header_len[USER_VAR_EVENT-1]= USER_VAR_HEADER_LEN;
5510 post_header_len[FORMAT_DESCRIPTION_EVENT-1]= FORMAT_DESCRIPTION_HEADER_LEN;
5511 post_header_len[XID_EVENT-1]= XID_HEADER_LEN;
5512 post_header_len[BEGIN_LOAD_QUERY_EVENT-1]= BEGIN_LOAD_QUERY_HEADER_LEN;
5513 post_header_len[EXECUTE_LOAD_QUERY_EVENT-1]= EXECUTE_LOAD_QUERY_HEADER_LEN;
5514 /*
5515 The PRE_GA events are never be written to any binlog, but
5516 their lengths are included in Format_description_log_event.
5517 Hence, we need to be assign some value here, to avoid reading
5518 uninitialized memory when the array is written to disk.
5519 */
5520 post_header_len[PRE_GA_WRITE_ROWS_EVENT-1] = 0;
5521 post_header_len[PRE_GA_UPDATE_ROWS_EVENT-1] = 0;
5522 post_header_len[PRE_GA_DELETE_ROWS_EVENT-1] = 0;
5523
5524 post_header_len[TABLE_MAP_EVENT-1]= TABLE_MAP_HEADER_LEN;
5525 post_header_len[WRITE_ROWS_EVENT_V1-1]= ROWS_HEADER_LEN_V1;
5526 post_header_len[UPDATE_ROWS_EVENT_V1-1]= ROWS_HEADER_LEN_V1;
5527 post_header_len[DELETE_ROWS_EVENT_V1-1]= ROWS_HEADER_LEN_V1;
5528 /*
5529 We here have the possibility to simulate a master of before we changed
5530 the table map id to be stored in 6 bytes: when it was stored in 4
5531 bytes (=> post_header_len was 6). This is used to test backward
5532 compatibility.
5533 This code can be removed after a few months (today is Dec 21st 2005),
5534 when we know that the 4-byte masters are not deployed anymore (check
5535 with Tomas Ulin first!), and the accompanying test (rpl_row_4_bytes)
5536 too.
5537 */
5538 DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master",
5539 post_header_len[TABLE_MAP_EVENT-1]=
5540 post_header_len[WRITE_ROWS_EVENT_V1-1]=
5541 post_header_len[UPDATE_ROWS_EVENT_V1-1]=
5542 post_header_len[DELETE_ROWS_EVENT_V1-1]= 6;);
5543 post_header_len[INCIDENT_EVENT-1]= INCIDENT_HEADER_LEN;
5544 post_header_len[HEARTBEAT_LOG_EVENT-1]= 0;
5545 post_header_len[IGNORABLE_LOG_EVENT-1]= IGNORABLE_HEADER_LEN;
5546 post_header_len[ROWS_QUERY_LOG_EVENT-1]= IGNORABLE_HEADER_LEN;
5547 post_header_len[WRITE_ROWS_EVENT-1]= ROWS_HEADER_LEN_V2;
5548 post_header_len[UPDATE_ROWS_EVENT-1]= ROWS_HEADER_LEN_V2;
5549 post_header_len[DELETE_ROWS_EVENT-1]= ROWS_HEADER_LEN_V2;
5550 post_header_len[GTID_LOG_EVENT-1]=
5551 post_header_len[ANONYMOUS_GTID_LOG_EVENT-1]=
5552 Gtid_log_event::POST_HEADER_LENGTH;
5553 post_header_len[PREVIOUS_GTIDS_LOG_EVENT-1]= IGNORABLE_HEADER_LEN;
5554
5555 // Sanity-check that all post header lengths are initialized.
5556 int i;
5557 for (i=0; i<number_of_event_types; i++)
5558 DBUG_ASSERT(post_header_len[i] != 255);
5559 }
5560 break;
5561
5562 case 1: /* 3.23 */
5563 case 3: /* 4.0.x x>=2 */
5564 /*
5565 We build an artificial (i.e. not sent by the master) event, which
5566 describes what those old master versions send.
5567 */
5568 if (binlog_ver==1)
5569 strmov(server_version, server_ver ? server_ver : "3.23");
5570 else
5571 strmov(server_version, server_ver ? server_ver : "4.0");
5572 common_header_len= binlog_ver==1 ? OLD_HEADER_LEN :
5573 LOG_EVENT_MINIMAL_HEADER_LEN;
5574 /*
5575 The first new event in binlog version 4 is Format_desc. So any event type
5576 after that does not exist in older versions. We use the events known by
5577 version 3, even if version 1 had only a subset of them (this is not a
5578 problem: it uses a few bytes for nothing but unifies code; it does not
5579 make the slave detect less corruptions).
5580 */
5581 number_of_event_types= FORMAT_DESCRIPTION_EVENT - 1;
5582 post_header_len=(uint8*) my_malloc(number_of_event_types*sizeof(uint8),
5583 MYF(0));
5584 if (post_header_len)
5585 {
5586 post_header_len[START_EVENT_V3-1]= START_V3_HEADER_LEN;
5587 post_header_len[QUERY_EVENT-1]= QUERY_HEADER_MINIMAL_LEN;
5588 post_header_len[STOP_EVENT-1]= 0;
5589 post_header_len[ROTATE_EVENT-1]= (binlog_ver==1) ? 0 : ROTATE_HEADER_LEN;
5590 post_header_len[INTVAR_EVENT-1]= 0;
5591 post_header_len[LOAD_EVENT-1]= LOAD_HEADER_LEN;
5592 post_header_len[SLAVE_EVENT-1]= 0; /* Unused because the code for Slave log event was removed. (15th Oct. 2010) */
5593 post_header_len[CREATE_FILE_EVENT-1]= CREATE_FILE_HEADER_LEN;
5594 post_header_len[APPEND_BLOCK_EVENT-1]= APPEND_BLOCK_HEADER_LEN;
5595 post_header_len[EXEC_LOAD_EVENT-1]= EXEC_LOAD_HEADER_LEN;
5596 post_header_len[DELETE_FILE_EVENT-1]= DELETE_FILE_HEADER_LEN;
5597 post_header_len[NEW_LOAD_EVENT-1]= post_header_len[LOAD_EVENT-1];
5598 post_header_len[RAND_EVENT-1]= 0;
5599 post_header_len[USER_VAR_EVENT-1]= 0;
5600 }
5601 break;
5602 default: /* Includes binlog version 2 i.e. 4.0.x x<=1 */
5603 post_header_len= 0; /* will make is_valid() fail */
5604 break;
5605 }
5606 calc_server_version_split();
5607 checksum_alg= (uint8) BINLOG_CHECKSUM_ALG_UNDEF;
5608 }
5609
5610
5611 /**
5612 The problem with this constructor is that the fixed header may have a
5613 length different from this version, but we don't know this length as we
5614 have not read the Format_description_log_event which says it, yet. This
5615 length is in the post-header of the event, but we don't know where the
5616 post-header starts.
5617
5618 So this type of event HAS to:
5619 - either have the header's length at the beginning (in the header, at a
5620 fixed position which will never be changed), not in the post-header. That
5621 would make the header be "shifted" compared to other events.
5622 - or have a header of size LOG_EVENT_MINIMAL_HEADER_LEN (19), in all future
5623 versions, so that we know for sure.
5624
5625 I (Guilhem) chose the 2nd solution. Rotate has the same constraint (because
5626 it is sent before Format_description_log_event).
5627 */
5628
5629 Format_description_log_event::
Format_description_log_event(const char * buf,uint event_len,const Format_description_log_event * description_event)5630 Format_description_log_event(const char* buf,
5631 uint event_len,
5632 const
5633 Format_description_log_event*
5634 description_event)
5635 :Start_log_event_v3(buf, event_len, description_event),
5636 common_header_len(0), post_header_len(NULL), event_type_permutation(0)
5637 {
5638 ulong ver_calc;
5639 DBUG_ENTER("Format_description_log_event::Format_description_log_event(char*,...)");
5640 if (!Start_log_event_v3::is_valid())
5641 DBUG_VOID_RETURN; /* sanity check */
5642 buf+= LOG_EVENT_MINIMAL_HEADER_LEN;
5643 if ((common_header_len=buf[ST_COMMON_HEADER_LEN_OFFSET]) < OLD_HEADER_LEN)
5644 DBUG_VOID_RETURN; /* sanity check */
5645 number_of_event_types=
5646 event_len - (LOG_EVENT_MINIMAL_HEADER_LEN + ST_COMMON_HEADER_LEN_OFFSET + 1);
5647 DBUG_PRINT("info", ("common_header_len=%d number_of_event_types=%d",
5648 common_header_len, number_of_event_types));
5649 /* If alloc fails, we'll detect it in is_valid() */
5650
5651 post_header_len= (uint8*) my_memdup((uchar*)buf+ST_COMMON_HEADER_LEN_OFFSET+1,
5652 number_of_event_types*
5653 sizeof(*post_header_len),
5654 MYF(0));
5655 calc_server_version_split();
5656 if ((ver_calc= get_version_product()) >= checksum_version_product)
5657 {
5658 /* the last bytes are the checksum alg desc and value (or value's room) */
5659 number_of_event_types -= BINLOG_CHECKSUM_ALG_DESC_LEN;
5660 /*
5661 FD from the checksum-home version server (ver_calc ==
5662 checksum_version_product) must have
5663 number_of_event_types == LOG_EVENT_TYPES.
5664 */
5665 DBUG_ASSERT(ver_calc != checksum_version_product ||
5666 number_of_event_types == LOG_EVENT_TYPES);
5667 checksum_alg= post_header_len[number_of_event_types];
5668 }
5669 else
5670 {
5671 checksum_alg= (uint8) BINLOG_CHECKSUM_ALG_UNDEF;
5672 }
5673
5674 /*
5675 In some previous versions, the events were given other event type
5676 id numbers than in the present version. When replicating from such
5677 a version, we therefore set up an array that maps those id numbers
5678 to the id numbers of the present server.
5679
5680 If post_header_len is null, it means malloc failed, and is_valid
5681 will fail, so there is no need to do anything.
5682
5683 The trees in which events have wrong id's are:
5684
5685 mysql-5.1-wl1012.old mysql-5.1-wl2325-5.0-drop6p13-alpha
5686 mysql-5.1-wl2325-5.0-drop6 mysql-5.1-wl2325-5.0
5687 mysql-5.1-wl2325-no-dd
5688
5689 (this was found by grepping for two lines in sequence where the
5690 first matches "FORMAT_DESCRIPTION_EVENT," and the second matches
5691 "TABLE_MAP_EVENT," in log_event.h in all trees)
5692
5693 In these trees, the following server_versions existed since
5694 TABLE_MAP_EVENT was introduced:
5695
5696 5.1.1-a_drop5p3 5.1.1-a_drop5p4 5.1.1-alpha
5697 5.1.2-a_drop5p10 5.1.2-a_drop5p11 5.1.2-a_drop5p12
5698 5.1.2-a_drop5p13 5.1.2-a_drop5p14 5.1.2-a_drop5p15
5699 5.1.2-a_drop5p16 5.1.2-a_drop5p16b 5.1.2-a_drop5p16c
5700 5.1.2-a_drop5p17 5.1.2-a_drop5p4 5.1.2-a_drop5p5
5701 5.1.2-a_drop5p6 5.1.2-a_drop5p7 5.1.2-a_drop5p8
5702 5.1.2-a_drop5p9 5.1.3-a_drop5p17 5.1.3-a_drop5p17b
5703 5.1.3-a_drop5p17c 5.1.4-a_drop5p18 5.1.4-a_drop5p19
5704 5.1.4-a_drop5p20 5.1.4-a_drop6p0 5.1.4-a_drop6p1
5705 5.1.4-a_drop6p2 5.1.5-a_drop5p20 5.2.0-a_drop6p3
5706 5.2.0-a_drop6p4 5.2.0-a_drop6p5 5.2.0-a_drop6p6
5707 5.2.1-a_drop6p10 5.2.1-a_drop6p11 5.2.1-a_drop6p12
5708 5.2.1-a_drop6p6 5.2.1-a_drop6p7 5.2.1-a_drop6p8
5709 5.2.2-a_drop6p13 5.2.2-a_drop6p13-alpha 5.2.2-a_drop6p13b
5710 5.2.2-a_drop6p13c
5711
5712 (this was found by grepping for "mysql," in all historical
5713 versions of configure.in in the trees listed above).
5714
5715 There are 5.1.1-alpha versions that use the new event id's, so we
5716 do not test that version string. So replication from 5.1.1-alpha
5717 with the other event id's to a new version does not work.
5718 Moreover, we can safely ignore the part after drop[56]. This
5719 allows us to simplify the big list above to the following regexes:
5720
5721 5\.1\.[1-5]-a_drop5.*
5722 5\.1\.4-a_drop6.*
5723 5\.2\.[0-2]-a_drop6.*
5724
5725 This is what we test for in the 'if' below.
5726 */
5727 if (post_header_len &&
5728 server_version[0] == '5' && server_version[1] == '.' &&
5729 server_version[3] == '.' &&
5730 strncmp(server_version + 5, "-a_drop", 7) == 0 &&
5731 ((server_version[2] == '1' &&
5732 server_version[4] >= '1' && server_version[4] <= '5' &&
5733 server_version[12] == '5') ||
5734 (server_version[2] == '1' &&
5735 server_version[4] == '4' &&
5736 server_version[12] == '6') ||
5737 (server_version[2] == '2' &&
5738 server_version[4] >= '0' && server_version[4] <= '2' &&
5739 server_version[12] == '6')))
5740 {
5741 if (number_of_event_types != 22)
5742 {
5743 DBUG_PRINT("info", (" number_of_event_types=%d",
5744 number_of_event_types));
5745 /* this makes is_valid() return false. */
5746 my_free(post_header_len);
5747 post_header_len= NULL;
5748 DBUG_VOID_RETURN;
5749 }
5750 static const uint8 perm[EVENT_TYPE_PERMUTATION_NUM]=
5751 {
5752 UNKNOWN_EVENT, START_EVENT_V3, QUERY_EVENT, STOP_EVENT, ROTATE_EVENT,
5753 INTVAR_EVENT, LOAD_EVENT, SLAVE_EVENT, CREATE_FILE_EVENT,
5754 APPEND_BLOCK_EVENT, EXEC_LOAD_EVENT, DELETE_FILE_EVENT,
5755 NEW_LOAD_EVENT,
5756 RAND_EVENT, USER_VAR_EVENT,
5757 FORMAT_DESCRIPTION_EVENT,
5758 TABLE_MAP_EVENT,
5759 PRE_GA_WRITE_ROWS_EVENT,
5760 PRE_GA_UPDATE_ROWS_EVENT,
5761 PRE_GA_DELETE_ROWS_EVENT,
5762 XID_EVENT,
5763 BEGIN_LOAD_QUERY_EVENT,
5764 EXECUTE_LOAD_QUERY_EVENT,
5765 };
5766 event_type_permutation= perm;
5767 /*
5768 Since we use (permuted) event id's to index the post_header_len
5769 array, we need to permute the post_header_len array too.
5770 */
5771 uint8 post_header_len_temp[EVENT_TYPE_PERMUTATION_NUM];
5772 for (uint i= 1; i < EVENT_TYPE_PERMUTATION_NUM; i++)
5773 post_header_len_temp[perm[i] - 1]= post_header_len[i - 1];
5774 for (uint i= 0; i < EVENT_TYPE_PERMUTATION_NUM - 1; i++)
5775 post_header_len[i] = post_header_len_temp[i];
5776 }
5777 DBUG_VOID_RETURN;
5778 }
5779
5780 #ifndef MYSQL_CLIENT
write(IO_CACHE * file)5781 bool Format_description_log_event::write(IO_CACHE* file)
5782 {
5783 bool ret;
5784 bool no_checksum;
5785 /*
5786 We don't call Start_log_event_v3::write() because this would make 2
5787 my_b_safe_write().
5788 */
5789 uchar buff[FORMAT_DESCRIPTION_HEADER_LEN + BINLOG_CHECKSUM_ALG_DESC_LEN];
5790 size_t rec_size= sizeof(buff);
5791 int2store(buff + ST_BINLOG_VER_OFFSET,binlog_version);
5792 memcpy((char*) buff + ST_SERVER_VER_OFFSET,server_version,ST_SERVER_VER_LEN);
5793 if (!dont_set_created)
5794 created= get_time();
5795 int4store(buff + ST_CREATED_OFFSET,created);
5796 buff[ST_COMMON_HEADER_LEN_OFFSET]= LOG_EVENT_HEADER_LEN;
5797 memcpy((char*) buff+ST_COMMON_HEADER_LEN_OFFSET + 1, (uchar*) post_header_len,
5798 LOG_EVENT_TYPES);
5799 /*
5800 if checksum is requested
5801 record the checksum-algorithm descriptor next to
5802 post_header_len vector which will be followed by the checksum value.
5803 Master is supposed to trigger checksum computing by binlog_checksum_options,
5804 slave does it via marking the event according to
5805 FD_queue checksum_alg value.
5806 */
5807 compile_time_assert(sizeof(BINLOG_CHECKSUM_ALG_DESC_LEN == 1));
5808 #ifndef DBUG_OFF
5809 data_written= 0; // to prepare for need_checksum assert
5810 #endif
5811 buff[FORMAT_DESCRIPTION_HEADER_LEN]= need_checksum() ?
5812 checksum_alg : (uint8) BINLOG_CHECKSUM_ALG_OFF;
5813 /*
5814 FD of checksum-aware server is always checksum-equipped, (V) is in,
5815 regardless of @@global.binlog_checksum policy.
5816 Thereby a combination of (A) == 0, (V) != 0 means
5817 it's the checksum-aware server's FD event that heads checksum-free binlog
5818 file.
5819 Here 0 stands for checksumming OFF to evaluate (V) as 0 is that case.
5820 A combination of (A) != 0, (V) != 0 denotes FD of the checksum-aware server
5821 heading the checksummed binlog.
5822 (A), (V) presence in FD of the checksum-aware server makes the event
5823 1 + 4 bytes bigger comparing to the former FD.
5824 */
5825
5826 if ((no_checksum= (checksum_alg == BINLOG_CHECKSUM_ALG_OFF)))
5827 {
5828 checksum_alg= BINLOG_CHECKSUM_ALG_CRC32; // Forcing (V) room to fill anyway
5829 }
5830 ret= (write_header(file, rec_size) ||
5831 wrapper_my_b_safe_write(file, buff, rec_size) ||
5832 write_footer(file));
5833 if (no_checksum)
5834 checksum_alg= BINLOG_CHECKSUM_ALG_OFF;
5835 return ret;
5836 }
5837 #endif
5838
5839 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
do_apply_event(Relay_log_info const * rli)5840 int Format_description_log_event::do_apply_event(Relay_log_info const *rli)
5841 {
5842 int ret= 0;
5843 DBUG_ENTER("Format_description_log_event::do_apply_event");
5844
5845 /*
5846 As a transaction NEVER spans on 2 or more binlogs:
5847 if we have an active transaction at this point, the master died
5848 while writing the transaction to the binary log, i.e. while
5849 flushing the binlog cache to the binlog. XA guarantees that master has
5850 rolled back. So we roll back.
5851 Note: this event could be sent by the master to inform us of the
5852 format of its binlog; in other words maybe it is not at its
5853 original place when it comes to us; we'll know this by checking
5854 log_pos ("artificial" events have log_pos == 0).
5855 */
5856 if (!thd->rli_fake && !is_artificial_event() && created
5857 && thd->transaction.all.ha_list)
5858 {
5859 /* This is not an error (XA is safe), just an information */
5860 rli->report(INFORMATION_LEVEL, 0,
5861 "Rolling back unfinished transaction (no COMMIT "
5862 "or ROLLBACK in relay log). A probable cause is that "
5863 "the master died while writing the transaction to "
5864 "its binary log, thus rolled back too.");
5865 const_cast<Relay_log_info*>(rli)->cleanup_context(thd, 1);
5866 }
5867
5868 /*
5869 If this event comes from ourselves, there is no cleaning task to
5870 perform, we don't call Start_log_event_v3::do_apply_event()
5871 (this was just to update the log's description event).
5872 */
5873 if (server_id != (uint32) ::server_id)
5874 {
5875 /*
5876 If the event was not requested by the slave i.e. the master sent
5877 it while the slave asked for a position >4, the event will make
5878 rli->group_master_log_pos advance. Say that the slave asked for
5879 position 1000, and the Format_desc event's end is 96. Then in
5880 the beginning of replication rli->group_master_log_pos will be
5881 0, then 96, then jump to first really asked event (which is
5882 >96). So this is ok.
5883 */
5884 ret= Start_log_event_v3::do_apply_event(rli);
5885 }
5886
5887 if (!ret)
5888 {
5889 /* Save the information describing this binlog */
5890 const_cast<Relay_log_info *>(rli)->set_rli_description_event(this);
5891 }
5892
5893 DBUG_RETURN(ret);
5894 }
5895
do_update_pos(Relay_log_info * rli)5896 int Format_description_log_event::do_update_pos(Relay_log_info *rli)
5897 {
5898 if (server_id == (uint32) ::server_id)
5899 {
5900 /*
5901 We only increase the relay log position if we are skipping
5902 events and do not touch any group_* variables, nor flush the
5903 relay log info. If there is a crash, we will have to re-skip
5904 the events again, but that is a minor issue.
5905
5906 If we do not skip stepping the group log position (and the
5907 server id was changed when restarting the server), it might well
5908 be that we start executing at a position that is invalid, e.g.,
5909 at a Rows_log_event or a Query_log_event preceeded by a
5910 Intvar_log_event instead of starting at a Table_map_log_event or
5911 the Intvar_log_event respectively.
5912 */
5913 rli->inc_event_relay_log_pos();
5914 return 0;
5915 }
5916 else
5917 {
5918 return Log_event::do_update_pos(rli);
5919 }
5920 }
5921
5922 Log_event::enum_skip_reason
do_shall_skip(Relay_log_info * rli)5923 Format_description_log_event::do_shall_skip(Relay_log_info *rli)
5924 {
5925 return Log_event::EVENT_SKIP_NOT;
5926 }
5927
5928 #endif
5929
5930
5931 /**
5932 'server_version_split' is used for lookups to find if the server which
5933 created this event has some known bug.
5934 */
calc_server_version_split()5935 void Format_description_log_event::calc_server_version_split()
5936 {
5937 do_server_version_split(server_version, server_version_split);
5938
5939 DBUG_PRINT("info",("Format_description_log_event::server_version_split:"
5940 " '%s' %d %d %d", server_version,
5941 server_version_split[0],
5942 server_version_split[1], server_version_split[2]));
5943 }
5944
5945 /**
5946 @return integer representing the version of server that originated
5947 the current FD instance.
5948 */
get_version_product() const5949 ulong Format_description_log_event::get_version_product() const
5950 {
5951 return version_product(server_version_split);
5952 }
5953
5954 /**
5955 @return TRUE is the event's version is earlier than one that introduced
5956 the replication event checksum. FALSE otherwise.
5957 */
is_version_before_checksum() const5958 bool Format_description_log_event::is_version_before_checksum() const
5959 {
5960 return get_version_product() < checksum_version_product;
5961 }
5962
5963 /**
5964 @param buf buffer holding serialized FD event
5965 @param len netto (possible checksum is stripped off) length of the event buf
5966
5967 @return the version-safe checksum alg descriptor where zero
5968 designates no checksum, 255 - the orginator is
5969 checksum-unaware (effectively no checksum) and the actuall
5970 [1-254] range alg descriptor.
5971 */
get_checksum_alg(const char * buf,ulong len)5972 uint8 get_checksum_alg(const char* buf, ulong len)
5973 {
5974 uint8 ret;
5975 char version[ST_SERVER_VER_LEN];
5976 uchar version_split[3];
5977
5978 DBUG_ENTER("get_checksum_alg");
5979 DBUG_ASSERT(buf[EVENT_TYPE_OFFSET] == FORMAT_DESCRIPTION_EVENT);
5980
5981 memcpy(version, buf +
5982 buf[LOG_EVENT_MINIMAL_HEADER_LEN + ST_COMMON_HEADER_LEN_OFFSET]
5983 + ST_SERVER_VER_OFFSET, ST_SERVER_VER_LEN);
5984 version[ST_SERVER_VER_LEN - 1]= 0;
5985
5986 do_server_version_split(version, version_split);
5987 ret= (version_product(version_split) < checksum_version_product) ?
5988 (uint8) BINLOG_CHECKSUM_ALG_UNDEF :
5989 * (uint8*) (buf + len - BINLOG_CHECKSUM_LEN - BINLOG_CHECKSUM_ALG_DESC_LEN);
5990 DBUG_ASSERT(ret == BINLOG_CHECKSUM_ALG_OFF ||
5991 ret == BINLOG_CHECKSUM_ALG_UNDEF ||
5992 ret == BINLOG_CHECKSUM_ALG_CRC32);
5993 DBUG_RETURN(ret);
5994 }
5995
5996
5997 /**************************************************************************
5998 Load_log_event methods
5999 General note about Load_log_event: the binlogging of LOAD DATA INFILE is
6000 going to be changed in 5.0 (or maybe in 5.1; not decided yet).
6001 However, the 5.0 slave could still have to read such events (from a 4.x
6002 master), convert them (which just means maybe expand the header, when 5.0
6003 servers have a UID in events) (remember that whatever is after the header
6004 will be like in 4.x, as this event's format is not modified in 5.0 as we
6005 will use new types of events to log the new LOAD DATA INFILE features).
6006 To be able to read/convert, we just need to not assume that the common
6007 header is of length LOG_EVENT_HEADER_LEN (we must use the description
6008 event).
6009 Note that I (Guilhem) manually tested replication of a big LOAD DATA INFILE
6010 between 3.23 and 5.0, and between 4.0 and 5.0, and it works fine (and the
6011 positions displayed in SHOW SLAVE STATUS then are fine too).
6012 **************************************************************************/
6013
6014 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
get_query_buffer_length()6015 uint Load_log_event::get_query_buffer_length()
6016 {
6017 return
6018 //the DB name may double if we escape the quote character
6019 5 + 2*db_len + 3 +
6020 18 + fname_len*4 + 2 + // "LOAD DATA INFILE 'file''"
6021 11 + // "CONCURRENT "
6022 7 + // LOCAL
6023 9 + // " REPLACE or IGNORE "
6024 13 + table_name_len*2 + // "INTO TABLE `table`"
6025 21 + sql_ex.field_term_len*4 + 2 + // " FIELDS TERMINATED BY 'str'"
6026 23 + sql_ex.enclosed_len*4 + 2 + // " OPTIONALLY ENCLOSED BY 'str'"
6027 12 + sql_ex.escaped_len*4 + 2 + // " ESCAPED BY 'str'"
6028 21 + sql_ex.line_term_len*4 + 2 + // " LINES TERMINATED BY 'str'"
6029 19 + sql_ex.line_start_len*4 + 2 + // " LINES STARTING BY 'str'"
6030 15 + 22 + // " IGNORE xxx LINES"
6031 3 + (num_fields-1)*2 + field_block_len; // " (field1, field2, ...)"
6032 }
6033
6034
print_query(bool need_db,const char * cs,char * buf,char ** end,char ** fn_start,char ** fn_end)6035 void Load_log_event::print_query(bool need_db, const char *cs, char *buf,
6036 char **end, char **fn_start, char **fn_end)
6037 {
6038 char quoted_id[1 + NAME_LEN * 2 + 2];//quoted length
6039 int quoted_id_len= 0;
6040 char *pos= buf;
6041
6042 if (need_db && db && db_len)
6043 {
6044 pos= strmov(pos, "use ");
6045 #ifdef MYSQL_SERVER
6046 quoted_id_len= my_strmov_quoted_identifier(this->thd, (char *) quoted_id,
6047 db, 0);
6048 #else
6049 quoted_id_len= my_strmov_quoted_identifier((char *) quoted_id, db);
6050 #endif
6051 quoted_id[quoted_id_len]= '\0';
6052 pos= strmov(pos, quoted_id);
6053 pos= strmov(pos, "; ");
6054 }
6055
6056 pos= strmov(pos, "LOAD DATA ");
6057
6058 if (is_concurrent)
6059 pos= strmov(pos, "CONCURRENT ");
6060
6061 if (fn_start)
6062 *fn_start= pos;
6063
6064 if (check_fname_outside_temp_buf())
6065 pos= strmov(pos, "LOCAL ");
6066 pos= strmov(pos, "INFILE ");
6067 pos= pretty_print_str(pos, fname, fname_len);
6068 pos= strmov(pos, " ");
6069
6070 if (sql_ex.opt_flags & REPLACE_FLAG)
6071 pos= strmov(pos, "REPLACE ");
6072 else if (sql_ex.opt_flags & IGNORE_FLAG)
6073 pos= strmov(pos, "IGNORE ");
6074
6075 pos= strmov(pos ,"INTO");
6076
6077 if (fn_end)
6078 *fn_end= pos;
6079
6080 pos= strmov(pos ," TABLE ");
6081 memcpy(pos, table_name, table_name_len);
6082 pos+= table_name_len;
6083
6084 if (cs != NULL)
6085 {
6086 pos= strmov(pos ," CHARACTER SET ");
6087 pos= strmov(pos , cs);
6088 }
6089
6090 /* We have to create all optional fields as the default is not empty */
6091 pos= strmov(pos, " FIELDS TERMINATED BY ");
6092 pos= pretty_print_str(pos, sql_ex.field_term, sql_ex.field_term_len);
6093 if (sql_ex.opt_flags & OPT_ENCLOSED_FLAG)
6094 pos= strmov(pos, " OPTIONALLY ");
6095 pos= strmov(pos, " ENCLOSED BY ");
6096 pos= pretty_print_str(pos, sql_ex.enclosed, sql_ex.enclosed_len);
6097
6098 pos= strmov(pos, " ESCAPED BY ");
6099 pos= pretty_print_str(pos, sql_ex.escaped, sql_ex.escaped_len);
6100
6101 pos= strmov(pos, " LINES TERMINATED BY ");
6102 pos= pretty_print_str(pos, sql_ex.line_term, sql_ex.line_term_len);
6103 if (sql_ex.line_start_len)
6104 {
6105 pos= strmov(pos, " STARTING BY ");
6106 pos= pretty_print_str(pos, sql_ex.line_start, sql_ex.line_start_len);
6107 }
6108
6109 if ((long) skip_lines > 0)
6110 {
6111 pos= strmov(pos, " IGNORE ");
6112 pos= longlong10_to_str((longlong) skip_lines, pos, 10);
6113 pos= strmov(pos," LINES ");
6114 }
6115
6116 if (num_fields)
6117 {
6118 uint i;
6119 const char *field= fields;
6120 pos= strmov(pos, " (");
6121 for (i = 0; i < num_fields; i++)
6122 {
6123 if (i)
6124 {
6125 *pos++= ' ';
6126 *pos++= ',';
6127 }
6128 quoted_id_len= my_strmov_quoted_identifier(this->thd, quoted_id, field,
6129 0);
6130 memcpy(pos, quoted_id, quoted_id_len-1);
6131 }
6132 *pos++= ')';
6133 }
6134
6135 *end= pos;
6136 }
6137
6138
pack_info(Protocol * protocol)6139 int Load_log_event::pack_info(Protocol *protocol)
6140 {
6141 char *buf, *end;
6142
6143 if (!(buf= (char*) my_malloc(get_query_buffer_length(), MYF(MY_WME))))
6144 return 1;
6145 print_query(TRUE, NULL, buf, &end, 0, 0);
6146 protocol->store(buf, end-buf, &my_charset_bin);
6147 my_free(buf);
6148 return 0;
6149 }
6150 #endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
6151
6152
6153 #ifndef MYSQL_CLIENT
6154
6155 /*
6156 Load_log_event::write_data_header()
6157 */
6158
write_data_header(IO_CACHE * file)6159 bool Load_log_event::write_data_header(IO_CACHE* file)
6160 {
6161 char buf[LOAD_HEADER_LEN];
6162 int4store(buf + L_THREAD_ID_OFFSET, slave_proxy_id);
6163 int4store(buf + L_EXEC_TIME_OFFSET, exec_time);
6164 int4store(buf + L_SKIP_LINES_OFFSET, skip_lines);
6165 buf[L_TBL_LEN_OFFSET] = (char)table_name_len;
6166 buf[L_DB_LEN_OFFSET] = (char)db_len;
6167 int4store(buf + L_NUM_FIELDS_OFFSET, num_fields);
6168 return my_b_safe_write(file, (uchar*)buf, LOAD_HEADER_LEN) != 0;
6169 }
6170
6171
6172 /*
6173 Load_log_event::write_data_body()
6174 */
6175
write_data_body(IO_CACHE * file)6176 bool Load_log_event::write_data_body(IO_CACHE* file)
6177 {
6178 if (sql_ex.write_data(file))
6179 return 1;
6180 if (num_fields && fields && field_lens)
6181 {
6182 if (my_b_safe_write(file, (uchar*)field_lens, num_fields) ||
6183 my_b_safe_write(file, (uchar*)fields, field_block_len))
6184 return 1;
6185 }
6186 return (my_b_safe_write(file, (uchar*)table_name, table_name_len + 1) ||
6187 my_b_safe_write(file, (uchar*)db, db_len + 1) ||
6188 my_b_safe_write(file, (uchar*)fname, fname_len));
6189 }
6190
6191
6192 /*
6193 Load_log_event::Load_log_event()
6194 */
6195
Load_log_event(THD * thd_arg,sql_exchange * ex,const char * db_arg,const char * table_name_arg,List<Item> & fields_arg,bool is_concurrent_arg,enum enum_duplicates handle_dup,bool ignore,bool using_trans)6196 Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex,
6197 const char *db_arg, const char *table_name_arg,
6198 List<Item> &fields_arg,
6199 bool is_concurrent_arg,
6200 enum enum_duplicates handle_dup,
6201 bool ignore, bool using_trans)
6202 :Log_event(thd_arg,
6203 thd_arg->thread_specific_used ? LOG_EVENT_THREAD_SPECIFIC_F : 0,
6204 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
6205 Log_event::EVENT_STMT_CACHE,
6206 Log_event::EVENT_NORMAL_LOGGING),
6207 thread_id(thd_arg->thread_id),
6208 slave_proxy_id(thd_arg->variables.pseudo_thread_id),
6209 num_fields(0),fields(0),
6210 field_lens(0),field_block_len(0),
6211 table_name(table_name_arg ? table_name_arg : ""),
6212 db(db_arg), fname(ex->file_name), local_fname(FALSE),
6213 is_concurrent(is_concurrent_arg)
6214 {
6215
6216 /*
6217 exec_time calculation has changed to use the same method that is used
6218 to fill out "thd_arg->start_time"
6219 */
6220
6221 struct timeval end_time;
6222 ulonglong micro_end_time= my_micro_time();
6223 my_micro_time_to_timeval(micro_end_time, &end_time);
6224
6225 exec_time= end_time.tv_sec - thd_arg->start_time.tv_sec;
6226
6227 /* db can never be a zero pointer in 4.0 */
6228 db_len = (uint32) strlen(db);
6229 table_name_len = (uint32) strlen(table_name);
6230 fname_len = (fname) ? (uint) strlen(fname) : 0;
6231 sql_ex.field_term = (char*) ex->field_term->ptr();
6232 sql_ex.field_term_len = (uint8) ex->field_term->length();
6233 sql_ex.enclosed = (char*) ex->enclosed->ptr();
6234 sql_ex.enclosed_len = (uint8) ex->enclosed->length();
6235 sql_ex.line_term = (char*) ex->line_term->ptr();
6236 sql_ex.line_term_len = (uint8) ex->line_term->length();
6237 sql_ex.line_start = (char*) ex->line_start->ptr();
6238 sql_ex.line_start_len = (uint8) ex->line_start->length();
6239 sql_ex.escaped = (char*) ex->escaped->ptr();
6240 sql_ex.escaped_len = (uint8) ex->escaped->length();
6241 sql_ex.opt_flags = 0;
6242 sql_ex.cached_new_format = -1;
6243
6244 if (ex->dumpfile)
6245 sql_ex.opt_flags|= DUMPFILE_FLAG;
6246 if (ex->opt_enclosed)
6247 sql_ex.opt_flags|= OPT_ENCLOSED_FLAG;
6248
6249 sql_ex.empty_flags= 0;
6250
6251 switch (handle_dup) {
6252 case DUP_REPLACE:
6253 sql_ex.opt_flags|= REPLACE_FLAG;
6254 break;
6255 case DUP_UPDATE: // Impossible here
6256 case DUP_ERROR:
6257 break;
6258 }
6259 if (ignore)
6260 sql_ex.opt_flags|= IGNORE_FLAG;
6261
6262 if (!ex->field_term->length())
6263 sql_ex.empty_flags |= FIELD_TERM_EMPTY;
6264 if (!ex->enclosed->length())
6265 sql_ex.empty_flags |= ENCLOSED_EMPTY;
6266 if (!ex->line_term->length())
6267 sql_ex.empty_flags |= LINE_TERM_EMPTY;
6268 if (!ex->line_start->length())
6269 sql_ex.empty_flags |= LINE_START_EMPTY;
6270 if (!ex->escaped->length())
6271 sql_ex.empty_flags |= ESCAPED_EMPTY;
6272
6273 skip_lines = ex->skip_lines;
6274
6275 List_iterator<Item> li(fields_arg);
6276 field_lens_buf.length(0);
6277 fields_buf.length(0);
6278 Item* item;
6279 while ((item = li++))
6280 {
6281 num_fields++;
6282 uchar len= (uchar) item->item_name.length();
6283 field_block_len += len + 1;
6284 fields_buf.append(item->item_name.ptr(), len + 1);
6285 field_lens_buf.append((char*)&len, 1);
6286 }
6287
6288 field_lens = (const uchar*)field_lens_buf.ptr();
6289 fields = fields_buf.ptr();
6290 }
6291 #endif /* !MYSQL_CLIENT */
6292
6293
6294 /**
6295 @note
6296 The caller must do buf[event_len] = 0 before he starts using the
6297 constructed event.
6298 */
Load_log_event(const char * buf,uint event_len,const Format_description_log_event * description_event)6299 Load_log_event::Load_log_event(const char *buf, uint event_len,
6300 const Format_description_log_event *description_event)
6301 :Log_event(buf, description_event), num_fields(0), fields(0),
6302 field_lens(0),field_block_len(0),
6303 table_name(0), db(0), fname(0), local_fname(FALSE),
6304 /*
6305 Load_log_event which comes from the binary log does not contain
6306 information about the type of insert which was used on the master.
6307 Assume that it was an ordinary, non-concurrent LOAD DATA.
6308 */
6309 is_concurrent(FALSE)
6310 {
6311 DBUG_ENTER("Load_log_event");
6312 /*
6313 I (Guilhem) manually tested replication of LOAD DATA INFILE for 3.23->5.0,
6314 4.0->5.0 and 5.0->5.0 and it works.
6315 */
6316 if (event_len)
6317 copy_log_event(buf, event_len,
6318 ((buf[EVENT_TYPE_OFFSET] == LOAD_EVENT) ?
6319 LOAD_HEADER_LEN +
6320 description_event->common_header_len :
6321 LOAD_HEADER_LEN + LOG_EVENT_HEADER_LEN),
6322 description_event);
6323 /* otherwise it's a derived class, will call copy_log_event() itself */
6324 DBUG_VOID_RETURN;
6325 }
6326
6327
6328 /*
6329 Load_log_event::copy_log_event()
6330 */
6331
copy_log_event(const char * buf,ulong event_len,int body_offset,const Format_description_log_event * description_event)6332 int Load_log_event::copy_log_event(const char *buf, ulong event_len,
6333 int body_offset,
6334 const Format_description_log_event *description_event)
6335 {
6336 DBUG_ENTER("Load_log_event::copy_log_event");
6337 uint data_len;
6338 char* buf_end = (char*)buf + event_len;
6339 /* this is the beginning of the post-header */
6340 const char* data_head = buf + description_event->common_header_len;
6341 slave_proxy_id= thread_id= uint4korr(data_head + L_THREAD_ID_OFFSET);
6342 exec_time = uint4korr(data_head + L_EXEC_TIME_OFFSET);
6343 skip_lines = uint4korr(data_head + L_SKIP_LINES_OFFSET);
6344 table_name_len = (uint)data_head[L_TBL_LEN_OFFSET];
6345 db_len = (uint)data_head[L_DB_LEN_OFFSET];
6346 num_fields = uint4korr(data_head + L_NUM_FIELDS_OFFSET);
6347
6348 if ((int) event_len < body_offset)
6349 DBUG_RETURN(1);
6350 /*
6351 Sql_ex.init() on success returns the pointer to the first byte after
6352 the sql_ex structure, which is the start of field lengths array.
6353 */
6354 if (!(field_lens= (uchar*)sql_ex.init((char*)buf + body_offset,
6355 buf_end,
6356 buf[EVENT_TYPE_OFFSET] != LOAD_EVENT)))
6357 DBUG_RETURN(1);
6358
6359 data_len = event_len - body_offset;
6360 if (num_fields > data_len) // simple sanity check against corruption
6361 DBUG_RETURN(1);
6362 for (uint i = 0; i < num_fields; i++)
6363 field_block_len += (uint)field_lens[i] + 1;
6364
6365 fields = (char*)field_lens + num_fields;
6366 table_name = fields + field_block_len;
6367 if (strlen(table_name) > NAME_LEN)
6368 goto err;
6369
6370 db = table_name + table_name_len + 1;
6371 DBUG_EXECUTE_IF ("simulate_invalid_address",
6372 db_len = data_len;);
6373 fname = db + db_len + 1;
6374 if ((db_len > data_len) || (fname > buf_end))
6375 goto err;
6376 fname_len = (uint) strlen(fname);
6377 if ((fname_len > data_len) || (fname + fname_len > buf_end))
6378 goto err;
6379 // null termination is accomplished by the caller doing buf[event_len]=0
6380
6381 DBUG_RETURN(0);
6382
6383 err:
6384 // Invalid event.
6385 table_name = 0;
6386 DBUG_RETURN(1);
6387 }
6388
6389
6390 /*
6391 Load_log_event::print()
6392 */
6393
6394 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)6395 void Load_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
6396 {
6397 print(file, print_event_info, 0);
6398 }
6399
6400
print(FILE * file_arg,PRINT_EVENT_INFO * print_event_info,bool commented)6401 void Load_log_event::print(FILE* file_arg, PRINT_EVENT_INFO* print_event_info,
6402 bool commented)
6403 {
6404 IO_CACHE *const head= &print_event_info->head_cache;
6405 size_t id_len= 0;
6406 char temp_buf[1 + 2*FN_REFLEN + 2];
6407
6408 DBUG_ENTER("Load_log_event::print");
6409 if (!print_event_info->short_form)
6410 {
6411 print_header(head, print_event_info, FALSE);
6412 my_b_printf(head, "\tQuery\tthread_id=%ld\texec_time=%ld\n",
6413 thread_id, exec_time);
6414 }
6415
6416 bool different_db= 1;
6417 if (db)
6418 {
6419 /*
6420 If the database is different from the one of the previous statement, we
6421 need to print the "use" command, and we update the last_db.
6422 But if commented, the "use" is going to be commented so we should not
6423 update the last_db.
6424 */
6425 if ((different_db= memcmp(print_event_info->db, db, db_len + 1)) &&
6426 !commented)
6427 memcpy(print_event_info->db, db, db_len + 1);
6428 }
6429
6430 if (db && db[0] && different_db)
6431 {
6432 #ifdef MYSQL_SERVER
6433 id_len= my_strmov_quoted_identifier(this->thd, temp_buf, db, 0);
6434 #else
6435 id_len= my_strmov_quoted_identifier(temp_buf, db);
6436 #endif
6437 temp_buf[id_len]= '\0';
6438 my_b_printf(head, "%suse %s%s\n",
6439 commented ? "# " : "", temp_buf, print_event_info->delimiter);
6440 }
6441 if (flags & LOG_EVENT_THREAD_SPECIFIC_F)
6442 my_b_printf(head,"%sSET @@session.pseudo_thread_id=%lu%s\n",
6443 commented ? "# " : "", (ulong)thread_id,
6444 print_event_info->delimiter);
6445 my_b_printf(head, "%sLOAD DATA ",
6446 commented ? "# " : "");
6447 if (check_fname_outside_temp_buf())
6448 my_b_printf(head, "LOCAL ");
6449 my_b_printf(head, "INFILE '%-*s' ", fname_len, fname);
6450
6451 if (sql_ex.opt_flags & REPLACE_FLAG)
6452 my_b_printf(head,"REPLACE ");
6453 else if (sql_ex.opt_flags & IGNORE_FLAG)
6454 my_b_printf(head,"IGNORE ");
6455
6456 #ifdef MYSQL_SERVER
6457 id_len= my_strmov_quoted_identifier(this->thd, temp_buf, table_name, 0);
6458 #else
6459 id_len= my_strmov_quoted_identifier(temp_buf, table_name);
6460 #endif
6461 temp_buf[id_len]= '\0';
6462 my_b_printf(head, "INTO TABLE %s", temp_buf);
6463
6464 my_b_printf(head, " FIELDS TERMINATED BY ");
6465 pretty_print_str(head, sql_ex.field_term, sql_ex.field_term_len);
6466
6467 if (sql_ex.opt_flags & OPT_ENCLOSED_FLAG)
6468 my_b_printf(head," OPTIONALLY ");
6469 my_b_printf(head, " ENCLOSED BY ");
6470 pretty_print_str(head, sql_ex.enclosed, sql_ex.enclosed_len);
6471
6472 my_b_printf(head, " ESCAPED BY ");
6473 pretty_print_str(head, sql_ex.escaped, sql_ex.escaped_len);
6474
6475 my_b_printf(head," LINES TERMINATED BY ");
6476 pretty_print_str(head, sql_ex.line_term, sql_ex.line_term_len);
6477
6478
6479 if (sql_ex.line_start)
6480 {
6481 my_b_printf(head," STARTING BY ");
6482 pretty_print_str(head, sql_ex.line_start, sql_ex.line_start_len);
6483 }
6484 if ((long) skip_lines > 0)
6485 my_b_printf(head, " IGNORE %ld LINES", (long) skip_lines);
6486
6487 if (num_fields)
6488 {
6489 uint i;
6490 const char* field = fields;
6491 my_b_printf(head, " (");
6492 for (i = 0; i < num_fields; i++)
6493 {
6494 if (i)
6495 my_b_printf(head, ",");
6496 id_len= my_strmov_quoted_identifier((char *) temp_buf, field);
6497 temp_buf[id_len]= '\0';
6498 my_b_printf(head, "%s", temp_buf);
6499
6500 field += field_lens[i] + 1;
6501 }
6502 my_b_printf(head, ")");
6503 }
6504
6505 my_b_printf(head, "%s\n", print_event_info->delimiter);
6506 DBUG_VOID_RETURN;
6507 }
6508 #endif /* MYSQL_CLIENT */
6509
6510 #ifndef MYSQL_CLIENT
6511
6512 /**
6513 Load_log_event::set_fields()
6514
6515 @note
6516 This function can not use the member variable
6517 for the database, since LOAD DATA INFILE on the slave
6518 can be for a different database than the current one.
6519 This is the reason for the affected_db argument to this method.
6520 */
6521
set_fields(const char * affected_db,List<Item> & field_list,Name_resolution_context * context)6522 void Load_log_event::set_fields(const char* affected_db,
6523 List<Item> &field_list,
6524 Name_resolution_context *context)
6525 {
6526 uint i;
6527 const char* field = fields;
6528 for (i= 0; i < num_fields; i++)
6529 {
6530 field_list.push_back(new Item_field(context,
6531 affected_db, table_name, field));
6532 field+= field_lens[i] + 1;
6533 }
6534 }
6535 #endif /* !MYSQL_CLIENT */
6536
6537
6538 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
6539 /**
6540 Does the data loading job when executing a LOAD DATA on the slave.
6541
6542 @param net
6543 @param rli
6544 @param use_rli_only_for_errors If set to 1, rli is provided to
6545 Load_log_event::exec_event only for this
6546 function to have rli->get_rpl_log_name and
6547 rli->last_slave_error, both being used by
6548 error reports. rli's position advancing
6549 is skipped (done by the caller which is
6550 Execute_load_log_event::exec_event).
6551 If set to 0, rli is provided for full use,
6552 i.e. for error reports and position
6553 advancing.
6554
6555 @todo
6556 fix this; this can be done by testing rules in
6557 Create_file_log_event::exec_event() and then discarding Append_block and
6558 al.
6559 @todo
6560 this is a bug - this needs to be moved to the I/O thread
6561
6562 @retval
6563 0 Success
6564 @retval
6565 1 Failure
6566 */
6567
do_apply_event(NET * net,Relay_log_info const * rli,bool use_rli_only_for_errors)6568 int Load_log_event::do_apply_event(NET* net, Relay_log_info const *rli,
6569 bool use_rli_only_for_errors)
6570 {
6571 DBUG_ASSERT(thd->query() == 0);
6572 thd->reset_query_inner(); // Should not be needed
6573 set_thd_db(thd, db, db_len);
6574 thd->is_slave_error= 0;
6575 clear_all_errors(thd, const_cast<Relay_log_info*>(rli));
6576
6577 /* see Query_log_event::do_apply_event() and BUG#13360 */
6578 DBUG_ASSERT(!rli->m_table_map.count());
6579 /*
6580 Usually lex_start() is called by mysql_parse(), but we need it here
6581 as the present method does not call mysql_parse().
6582 */
6583 lex_start(thd);
6584 thd->lex->local_file= local_fname;
6585 mysql_reset_thd_for_next_command(thd);
6586
6587 if (!use_rli_only_for_errors)
6588 {
6589 /*
6590 Saved for InnoDB, see comment in
6591 Query_log_event::do_apply_event()
6592 */
6593 const_cast<Relay_log_info*>(rli)->set_future_group_master_log_pos(log_pos);
6594 DBUG_PRINT("info", ("log_pos: %lu", (ulong) log_pos));
6595 }
6596
6597 /*
6598 We test replicate_*_db rules. Note that we have already prepared
6599 the file to load, even if we are going to ignore and delete it
6600 now. So it is possible that we did a lot of disk writes for
6601 nothing. In other words, a big LOAD DATA INFILE on the master will
6602 still consume a lot of space on the slave (space in the relay log
6603 + space of temp files: twice the space of the file to load...)
6604 even if it will finally be ignored. TODO: fix this; this can be
6605 done by testing rules in Create_file_log_event::do_apply_event()
6606 and then discarding Append_block and al. Another way is do the
6607 filtering in the I/O thread (more efficient: no disk writes at
6608 all).
6609
6610
6611 Note: We do not need to execute reset_one_shot_variables() if this
6612 db_ok() test fails.
6613 Reason: The db stored in binlog events is the same for SET and for
6614 its companion query. If the SET is ignored because of
6615 db_ok(), the companion query will also be ignored, and if
6616 the companion query is ignored in the db_ok() test of
6617 ::do_apply_event(), then the companion SET also have so
6618 we don't need to reset_one_shot_variables().
6619 */
6620 if (rpl_filter->db_ok(thd->db))
6621 {
6622 thd->set_time(&when);
6623 thd->set_query_id(next_query_id());
6624 thd->get_stmt_da()->opt_clear_warning_info(thd->query_id);
6625
6626 TABLE_LIST tables;
6627 char table_buf[NAME_LEN + 1];
6628 strmov(table_buf, table_name);
6629 if (lower_case_table_names == 1)
6630 my_casedn_str(system_charset_info, table_buf);
6631 tables.init_one_table(thd->strmake(thd->db, thd->db_length),
6632 thd->db_length,
6633 table_buf, strlen(table_buf),
6634 table_buf, TL_WRITE);
6635 tables.updating= 1;
6636
6637 // the table will be opened in mysql_load
6638 if (rpl_filter->is_on() && !rpl_filter->tables_ok(thd->db, &tables))
6639 {
6640 // TODO: this is a bug - this needs to be moved to the I/O thread
6641 if (net)
6642 skip_load_data_infile(net);
6643 }
6644 else
6645 {
6646 char llbuff[22];
6647 char *end;
6648 enum enum_duplicates handle_dup;
6649 bool ignore= 0;
6650 char *load_data_query;
6651
6652 /*
6653 Forge LOAD DATA INFILE query which will be used in SHOW PROCESS LIST
6654 and written to slave's binlog if binlogging is on.
6655 */
6656 if (!(load_data_query= (char *)thd->alloc(get_query_buffer_length() + 1)))
6657 {
6658 /*
6659 This will set thd->fatal_error in case of OOM. So we surely will notice
6660 that something is wrong.
6661 */
6662 goto error;
6663 }
6664
6665 print_query(FALSE, NULL, load_data_query, &end, NULL, NULL);
6666 *end= 0;
6667 thd->set_query(load_data_query, (uint) (end - load_data_query));
6668
6669 if (sql_ex.opt_flags & REPLACE_FLAG)
6670 handle_dup= DUP_REPLACE;
6671 else if (sql_ex.opt_flags & IGNORE_FLAG)
6672 {
6673 ignore= 1;
6674 handle_dup= DUP_ERROR;
6675 }
6676 else
6677 {
6678 /*
6679 When replication is running fine, if it was DUP_ERROR on the
6680 master then we could choose IGNORE here, because if DUP_ERROR
6681 suceeded on master, and data is identical on the master and slave,
6682 then there should be no uniqueness errors on slave, so IGNORE is
6683 the same as DUP_ERROR. But in the unlikely case of uniqueness errors
6684 (because the data on the master and slave happen to be different
6685 (user error or bug), we want LOAD DATA to print an error message on
6686 the slave to discover the problem.
6687
6688 If reading from net (a 3.23 master), mysql_load() will change this
6689 to IGNORE.
6690 */
6691 handle_dup= DUP_ERROR;
6692 }
6693 /*
6694 We need to set thd->lex->sql_command and thd->lex->duplicates
6695 since InnoDB tests these variables to decide if this is a LOAD
6696 DATA ... REPLACE INTO ... statement even though mysql_parse()
6697 is not called. This is not needed in 5.0 since there the LOAD
6698 DATA ... statement is replicated using mysql_parse(), which
6699 sets the thd->lex fields correctly.
6700 */
6701 thd->lex->sql_command= SQLCOM_LOAD;
6702 thd->lex->duplicates= handle_dup;
6703
6704 sql_exchange ex((char*)fname, sql_ex.opt_flags & DUMPFILE_FLAG);
6705 String field_term(sql_ex.field_term,sql_ex.field_term_len,log_cs);
6706 String enclosed(sql_ex.enclosed,sql_ex.enclosed_len,log_cs);
6707 String line_term(sql_ex.line_term,sql_ex.line_term_len,log_cs);
6708 String line_start(sql_ex.line_start,sql_ex.line_start_len,log_cs);
6709 String escaped(sql_ex.escaped,sql_ex.escaped_len, log_cs);
6710 const String empty_str("", 0, log_cs);
6711 ex.field_term= &field_term;
6712 ex.enclosed= &enclosed;
6713 ex.line_term= &line_term;
6714 ex.line_start= &line_start;
6715 ex.escaped= &escaped;
6716
6717 ex.opt_enclosed = (sql_ex.opt_flags & OPT_ENCLOSED_FLAG);
6718 if (sql_ex.empty_flags & FIELD_TERM_EMPTY)
6719 ex.field_term= &empty_str;
6720
6721 ex.skip_lines = skip_lines;
6722 List<Item> field_list;
6723 thd->lex->select_lex.context.resolve_in_table_list_only(&tables);
6724 set_fields(tables.db, field_list, &thd->lex->select_lex.context);
6725 thd->variables.pseudo_thread_id= thread_id;
6726 if (net)
6727 {
6728 // mysql_load will use thd->net to read the file
6729 thd->net.vio = net->vio;
6730 // Make sure the client does not get confused about the packet sequence
6731 thd->net.pkt_nr = net->pkt_nr;
6732 }
6733 /*
6734 It is safe to use tmp_list twice because we are not going to
6735 update it inside mysql_load().
6736 */
6737 List<Item> tmp_list;
6738 if (open_temporary_tables(thd, &tables) ||
6739 mysql_load(thd, &ex, &tables, field_list, tmp_list, tmp_list,
6740 handle_dup, ignore, net != 0))
6741 thd->is_slave_error= 1;
6742 if (thd->cuted_fields)
6743 {
6744 /* log_pos is the position of the LOAD event in the master log */
6745 sql_print_warning("Slave: load data infile on table '%s' at "
6746 "log position %s in log '%s' produced %ld "
6747 "warning(s). Default database: '%s'",
6748 (char*) table_name,
6749 llstr(log_pos,llbuff),
6750 const_cast<Relay_log_info*>(rli)->get_rpl_log_name(),
6751 (ulong) thd->cuted_fields,
6752 print_slave_db_safe(thd->db));
6753 }
6754 if (net)
6755 net->pkt_nr= thd->net.pkt_nr;
6756 }
6757 }
6758 else
6759 {
6760 /*
6761 We will just ask the master to send us /dev/null if we do not
6762 want to load the data.
6763 TODO: this a bug - needs to be done in I/O thread
6764 */
6765 if (net)
6766 skip_load_data_infile(net);
6767 }
6768
6769 error:
6770 thd->net.vio = 0;
6771 const char *remember_db= thd->db;
6772 thd->catalog= 0;
6773 thd->set_db(NULL, 0); /* will free the current database */
6774 thd->reset_query();
6775 thd->get_stmt_da()->set_overwrite_status(true);
6776 thd->is_error() ? trans_rollback_stmt(thd) : trans_commit_stmt(thd);
6777 thd->get_stmt_da()->set_overwrite_status(false);
6778 close_thread_tables(thd);
6779 /*
6780 - If transaction rollback was requested due to deadlock
6781 perform it and release metadata locks.
6782 - If inside a multi-statement transaction,
6783 defer the release of metadata locks until the current
6784 transaction is either committed or rolled back. This prevents
6785 other statements from modifying the table for the entire
6786 duration of this transaction. This provides commit ordering
6787 and guarantees serializability across multiple transactions.
6788 - If in autocommit mode, or outside a transactional context,
6789 automatically release metadata locks of the current statement.
6790 */
6791 if (thd->transaction_rollback_request)
6792 {
6793 trans_rollback_implicit(thd);
6794 thd->mdl_context.release_transactional_locks();
6795 }
6796 else if (! thd->in_multi_stmt_transaction_mode())
6797 thd->mdl_context.release_transactional_locks();
6798 else
6799 thd->mdl_context.release_statement_locks();
6800
6801 DBUG_EXECUTE_IF("LOAD_DATA_INFILE_has_fatal_error",
6802 thd->is_slave_error= 0; thd->is_fatal_error= 1;);
6803
6804 if (thd->is_slave_error)
6805 {
6806 /* this err/sql_errno code is copy-paste from net_send_error() */
6807 const char *err;
6808 int sql_errno;
6809 if (thd->is_error())
6810 {
6811 err= thd->get_stmt_da()->message();
6812 sql_errno= thd->get_stmt_da()->sql_errno();
6813 }
6814 else
6815 {
6816 sql_errno=ER_UNKNOWN_ERROR;
6817 err=ER(sql_errno);
6818 }
6819 rli->report(ERROR_LEVEL, sql_errno,"\
6820 Error '%s' running LOAD DATA INFILE on table '%s'. Default database: '%s'",
6821 err, (char*)table_name, print_slave_db_safe(remember_db));
6822 free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
6823 return 1;
6824 }
6825 free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
6826
6827 if (thd->is_fatal_error)
6828 {
6829 char buf[256];
6830 my_snprintf(buf, sizeof(buf),
6831 "Running LOAD DATA INFILE on table '%-.64s'."
6832 " Default database: '%-.64s'",
6833 (char*)table_name,
6834 print_slave_db_safe(remember_db));
6835
6836 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
6837 ER(ER_SLAVE_FATAL_ERROR), buf);
6838 return 1;
6839 }
6840
6841 return ( use_rli_only_for_errors ? 0 : Log_event::do_apply_event(rli) );
6842 }
6843 #endif
6844
6845
6846 /**************************************************************************
6847 Rotate_log_event methods
6848 **************************************************************************/
6849
6850 /*
6851 Rotate_log_event::pack_info()
6852 */
6853
6854 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
pack_info(Protocol * protocol)6855 int Rotate_log_event::pack_info(Protocol *protocol)
6856 {
6857 char buf1[256], buf[22];
6858 String tmp(buf1, sizeof(buf1), log_cs);
6859 tmp.length(0);
6860 tmp.append(new_log_ident, ident_len);
6861 tmp.append(STRING_WITH_LEN(";pos="));
6862 tmp.append(llstr(pos,buf));
6863 protocol->store(tmp.ptr(), tmp.length(), &my_charset_bin);
6864 return 0;
6865 }
6866 #endif
6867
6868
6869 /*
6870 Rotate_log_event::print()
6871 */
6872
6873 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)6874 void Rotate_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
6875 {
6876 char buf[22];
6877 IO_CACHE *const head= &print_event_info->head_cache;
6878
6879 if (print_event_info->short_form)
6880 return;
6881 print_header(head, print_event_info, FALSE);
6882 my_b_printf(head, "\tRotate to ");
6883 if (new_log_ident)
6884 my_b_write(head, (uchar*) new_log_ident, (uint)ident_len);
6885 my_b_printf(head, " pos: %s\n", llstr(pos, buf));
6886 }
6887 #endif /* MYSQL_CLIENT */
6888
6889
6890
6891 /*
6892 Rotate_log_event::Rotate_log_event() (2 constructors)
6893 */
6894
6895
6896 #ifndef MYSQL_CLIENT
Rotate_log_event(const char * new_log_ident_arg,uint ident_len_arg,ulonglong pos_arg,uint flags_arg)6897 Rotate_log_event::Rotate_log_event(const char* new_log_ident_arg,
6898 uint ident_len_arg, ulonglong pos_arg,
6899 uint flags_arg)
6900 :Log_event(Log_event::EVENT_NO_CACHE, Log_event::EVENT_IMMEDIATE_LOGGING),
6901 new_log_ident(new_log_ident_arg), pos(pos_arg),ident_len(ident_len_arg ?
6902 ident_len_arg : (uint) strlen(new_log_ident_arg)), flags(flags_arg)
6903 {
6904 #ifndef DBUG_OFF
6905 char buff[22];
6906 DBUG_ENTER("Rotate_log_event::Rotate_log_event(...,flags)");
6907 DBUG_PRINT("enter",("new_log_ident: %s pos: %s flags: %lu", new_log_ident_arg,
6908 llstr(pos_arg, buff), (ulong) flags));
6909 #endif
6910 if (flags & DUP_NAME)
6911 new_log_ident= my_strndup(new_log_ident_arg, ident_len, MYF(MY_WME));
6912 if (flags & RELAY_LOG)
6913 set_relay_log_event();
6914 DBUG_VOID_RETURN;
6915 }
6916 #endif
6917
6918
Rotate_log_event(const char * buf,uint event_len,const Format_description_log_event * description_event)6919 Rotate_log_event::Rotate_log_event(const char* buf, uint event_len,
6920 const Format_description_log_event* description_event)
6921 :Log_event(buf, description_event) ,new_log_ident(0), flags(DUP_NAME)
6922 {
6923 DBUG_ENTER("Rotate_log_event::Rotate_log_event(char*,...)");
6924 // The caller will ensure that event_len is what we have at EVENT_LEN_OFFSET
6925 uint8 header_size= description_event->common_header_len;
6926 uint8 post_header_len= description_event->post_header_len[ROTATE_EVENT-1];
6927 uint ident_offset;
6928 if (event_len < header_size)
6929 DBUG_VOID_RETURN;
6930 buf += header_size;
6931 pos = post_header_len ? uint8korr(buf + R_POS_OFFSET) : 4;
6932 ident_len = (uint)(event_len -
6933 (header_size+post_header_len));
6934 ident_offset = post_header_len;
6935 set_if_smaller(ident_len,FN_REFLEN-1);
6936 new_log_ident= my_strndup(buf + ident_offset, (uint) ident_len, MYF(MY_WME));
6937 DBUG_PRINT("debug", ("new_log_ident: '%s'", new_log_ident));
6938 DBUG_VOID_RETURN;
6939 }
6940
6941
6942 /*
6943 Rotate_log_event::write()
6944 */
6945
6946 #ifndef MYSQL_CLIENT
write(IO_CACHE * file)6947 bool Rotate_log_event::write(IO_CACHE* file)
6948 {
6949 char buf[ROTATE_HEADER_LEN];
6950 int8store(buf + R_POS_OFFSET, pos);
6951 return (write_header(file, ROTATE_HEADER_LEN + ident_len) ||
6952 wrapper_my_b_safe_write(file, (uchar*) buf, ROTATE_HEADER_LEN) ||
6953 wrapper_my_b_safe_write(file, (uchar*) new_log_ident,
6954 (uint) ident_len) ||
6955 write_footer(file));
6956 }
6957 #endif
6958
6959
6960 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
6961
6962 /*
6963 Got a rotate log event from the master.
6964
6965 This is mainly used so that we can later figure out the logname and
6966 position for the master.
6967
6968 We can't rotate the slave's BINlog as this will cause infinitive rotations
6969 in a A -> B -> A setup.
6970 The NOTES below is a wrong comment which will disappear when 4.1 is merged.
6971
6972 This must only be called from the Slave SQL thread, since it calls
6973 flush_relay_log_info().
6974
6975 @retval
6976 0 ok
6977 */
do_update_pos(Relay_log_info * rli)6978 int Rotate_log_event::do_update_pos(Relay_log_info *rli)
6979 {
6980 int error= 0;
6981 DBUG_ENTER("Rotate_log_event::do_update_pos");
6982 #ifndef DBUG_OFF
6983 char buf[32];
6984 #endif
6985
6986 DBUG_PRINT("info", ("server_id=%lu; ::server_id=%lu",
6987 (ulong) this->server_id, (ulong) ::server_id));
6988 DBUG_PRINT("info", ("new_log_ident: %s", this->new_log_ident));
6989 DBUG_PRINT("info", ("pos: %s", llstr(this->pos, buf)));
6990
6991 /*
6992 If we are in a transaction or in a group: the only normal case is
6993 when the I/O thread was copying a big transaction, then it was
6994 stopped and restarted: we have this in the relay log:
6995
6996 BEGIN
6997 ...
6998 ROTATE (a fake one)
6999 ...
7000 COMMIT or ROLLBACK
7001
7002 In that case, we don't want to touch the coordinates which
7003 correspond to the beginning of the transaction. Starting from
7004 5.0.0, there also are some rotates from the slave itself, in the
7005 relay log, which shall not change the group positions.
7006 */
7007
7008 /*
7009 The way we check if SQL thread is currently in a group is different
7010 for STS and MTS.
7011 */
7012 bool in_group = rli->is_parallel_exec() ?
7013 (rli->mts_group_status == Relay_log_info::MTS_IN_GROUP) :
7014 rli->is_in_group();
7015
7016 if ((server_id != ::server_id || rli->replicate_same_server_id) &&
7017 !is_relay_log_event() &&
7018 !in_group)
7019 {
7020 if (rli->is_parallel_exec())
7021 {
7022 /*
7023 Rotate events are special events that are handled as a
7024 synchronization point. For that reason, the checkpoint
7025 routine is being called here.
7026 */
7027 if ((error= mts_checkpoint_routine(rli, 0, false,
7028 true/*need_data_lock=true*/)))
7029 goto err;
7030 }
7031
7032 /*
7033 Acquire protection against global BINLOG lock before rli->data_lock is
7034 locked (otherwise we would also block SHOW SLAVE STATUS).
7035 */
7036 DBUG_ASSERT(!thd->backup_binlog_lock.is_acquired());
7037 DBUG_PRINT("debug", ("Acquiring binlog protection lock"));
7038 mysql_mutex_assert_not_owner(&rli->data_lock);
7039 const ulong timeout= thd->variables.lock_wait_timeout;
7040 if (thd->backup_binlog_lock.acquire_protection(thd, MDL_EXPLICIT, timeout))
7041 {
7042 error= 1;
7043 goto err;
7044 }
7045
7046 mysql_mutex_lock(&rli->data_lock);
7047 DBUG_PRINT("info", ("old group_master_log_name: '%s' "
7048 "old group_master_log_pos: %lu",
7049 rli->get_group_master_log_name(),
7050 (ulong) rli->get_group_master_log_pos()));
7051
7052 memcpy((void *)rli->get_group_master_log_name(),
7053 new_log_ident, ident_len + 1);
7054 rli->notify_group_master_log_name_update();
7055 if ((error= rli->inc_group_relay_log_pos(pos,
7056 false/*need_data_lock=false*/)))
7057 {
7058 mysql_mutex_unlock(&rli->data_lock);
7059 DBUG_PRINT("debug", ("Releasing binlog protection lock"));
7060 thd->backup_binlog_lock.release_protection(thd);
7061 goto err;
7062 }
7063
7064 DBUG_PRINT("info", ("new group_master_log_name: '%s' "
7065 "new group_master_log_pos: %lu",
7066 rli->get_group_master_log_name(),
7067 (ulong) rli->get_group_master_log_pos()));
7068 mysql_mutex_unlock(&rli->data_lock);
7069
7070 DBUG_PRINT("debug", ("Releasing binlog protection lock"));
7071 thd->backup_binlog_lock.release_protection(thd);
7072
7073 if (rli->is_parallel_exec())
7074 {
7075 bool real_event= server_id && !is_artificial_event();
7076 time_t ts= when.tv_sec + static_cast<time_t>(exec_time);
7077 rli->reset_notified_checkpoint(0,
7078 real_event ? &ts : NULL,
7079 true/*need_data_lock=true*/);
7080 }
7081
7082 /*
7083 Reset thd->variables.option_bits and sql_mode etc, because this could be the signal of
7084 a master's downgrade from 5.0 to 4.0.
7085 However, no need to reset rli_description_event: indeed, if the next
7086 master is 5.0 (even 5.0.1) we will soon get a Format_desc; if the next
7087 master is 4.0 then the events are in the slave's format (conversion).
7088 */
7089 set_slave_thread_options(thd);
7090 set_slave_thread_default_charset(thd, rli);
7091 thd->variables.sql_mode= global_system_variables.sql_mode;
7092 thd->variables.auto_increment_increment=
7093 thd->variables.auto_increment_offset= 1;
7094 }
7095 else
7096 rli->inc_event_relay_log_pos();
7097
7098 err:
7099 DBUG_RETURN(error);
7100 }
7101
7102
7103 Log_event::enum_skip_reason
do_shall_skip(Relay_log_info * rli)7104 Rotate_log_event::do_shall_skip(Relay_log_info *rli)
7105 {
7106 enum_skip_reason reason= Log_event::do_shall_skip(rli);
7107
7108 switch (reason) {
7109 case Log_event::EVENT_SKIP_NOT:
7110 case Log_event::EVENT_SKIP_COUNT:
7111 return Log_event::EVENT_SKIP_NOT;
7112
7113 case Log_event::EVENT_SKIP_IGNORE:
7114 return Log_event::EVENT_SKIP_IGNORE;
7115 }
7116 DBUG_ASSERT(0);
7117 return Log_event::EVENT_SKIP_NOT; // To keep compiler happy
7118 }
7119
7120 #endif
7121
7122
7123 /**************************************************************************
7124 Intvar_log_event methods
7125 **************************************************************************/
7126
7127 /*
7128 Intvar_log_event::pack_info()
7129 */
7130
7131 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
pack_info(Protocol * protocol)7132 int Intvar_log_event::pack_info(Protocol *protocol)
7133 {
7134 char buf[256], *pos;
7135 pos= strmake(buf, get_var_type_name(), sizeof(buf)-23);
7136 *pos++= '=';
7137 pos= longlong10_to_str(val, pos, -10);
7138 protocol->store(buf, (uint) (pos-buf), &my_charset_bin);
7139 return 0;
7140 }
7141 #endif
7142
7143
7144 /*
7145 Intvar_log_event::Intvar_log_event()
7146 */
7147
Intvar_log_event(const char * buf,const Format_description_log_event * description_event)7148 Intvar_log_event::Intvar_log_event(const char* buf,
7149 const Format_description_log_event* description_event)
7150 :Log_event(buf, description_event)
7151 {
7152 /* The Post-Header is empty. The Varible Data part begins immediately. */
7153 buf+= description_event->common_header_len +
7154 description_event->post_header_len[INTVAR_EVENT-1];
7155 type= buf[I_TYPE_OFFSET];
7156 val= uint8korr(buf+I_VAL_OFFSET);
7157 }
7158
7159
7160 /*
7161 Intvar_log_event::get_var_type_name()
7162 */
7163
get_var_type_name()7164 const char* Intvar_log_event::get_var_type_name()
7165 {
7166 switch(type) {
7167 case LAST_INSERT_ID_EVENT: return "LAST_INSERT_ID";
7168 case INSERT_ID_EVENT: return "INSERT_ID";
7169 default: /* impossible */ return "UNKNOWN";
7170 }
7171 }
7172
7173
7174 /*
7175 Intvar_log_event::write()
7176 */
7177
7178 #ifndef MYSQL_CLIENT
write(IO_CACHE * file)7179 bool Intvar_log_event::write(IO_CACHE* file)
7180 {
7181 uchar buf[9];
7182 buf[I_TYPE_OFFSET]= (uchar) type;
7183 int8store(buf + I_VAL_OFFSET, val);
7184 return (write_header(file, sizeof(buf)) ||
7185 wrapper_my_b_safe_write(file, buf, sizeof(buf)) ||
7186 write_footer(file));
7187 }
7188 #endif
7189
7190
7191 /*
7192 Intvar_log_event::print()
7193 */
7194
7195 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)7196 void Intvar_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
7197 {
7198 char llbuff[22];
7199 const char *msg;
7200 LINT_INIT(msg);
7201 IO_CACHE *const head= &print_event_info->head_cache;
7202
7203 if (!print_event_info->short_form)
7204 {
7205 print_header(head, print_event_info, FALSE);
7206 my_b_printf(head, "\tIntvar\n");
7207 }
7208
7209 my_b_printf(head, "SET ");
7210 switch (type) {
7211 case LAST_INSERT_ID_EVENT:
7212 msg="LAST_INSERT_ID";
7213 break;
7214 case INSERT_ID_EVENT:
7215 msg="INSERT_ID";
7216 break;
7217 case INVALID_INT_EVENT:
7218 default: // cannot happen
7219 msg="INVALID_INT";
7220 break;
7221 }
7222 my_b_printf(head, "%s=%s%s\n",
7223 msg, llstr(val,llbuff), print_event_info->delimiter);
7224 }
7225 #endif
7226
7227
7228 #if defined(HAVE_REPLICATION)&& !defined(MYSQL_CLIENT)
7229
7230 /*
7231 Intvar_log_event::do_apply_event()
7232 */
7233
do_apply_event(Relay_log_info const * rli)7234 int Intvar_log_event::do_apply_event(Relay_log_info const *rli)
7235 {
7236 /*
7237 We are now in a statement until the associated query log event has
7238 been processed.
7239 */
7240 const_cast<Relay_log_info*>(rli)->set_flag(Relay_log_info::IN_STMT);
7241
7242 if (rli->deferred_events_collecting)
7243 return rli->deferred_events->add(this);
7244
7245 switch (type) {
7246 case LAST_INSERT_ID_EVENT:
7247 thd->first_successful_insert_id_in_prev_stmt= val;
7248 break;
7249 case INSERT_ID_EVENT:
7250 thd->force_one_auto_inc_interval(val);
7251 break;
7252 }
7253 return 0;
7254 }
7255
do_update_pos(Relay_log_info * rli)7256 int Intvar_log_event::do_update_pos(Relay_log_info *rli)
7257 {
7258 rli->inc_event_relay_log_pos();
7259 return 0;
7260 }
7261
7262
7263 Log_event::enum_skip_reason
do_shall_skip(Relay_log_info * rli)7264 Intvar_log_event::do_shall_skip(Relay_log_info *rli)
7265 {
7266 /*
7267 It is a common error to set the slave skip counter to 1 instead of
7268 2 when recovering from an insert which used a auto increment,
7269 rand, or user var. Therefore, if the slave skip counter is 1, we
7270 just say that this event should be skipped by ignoring it, meaning
7271 that we do not change the value of the slave skip counter since it
7272 will be decreased by the following insert event.
7273 */
7274 return continue_group(rli);
7275 }
7276
7277 #endif
7278
7279
7280 /**************************************************************************
7281 Rand_log_event methods
7282 **************************************************************************/
7283
7284 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
pack_info(Protocol * protocol)7285 int Rand_log_event::pack_info(Protocol *protocol)
7286 {
7287 char buf1[256], *pos;
7288 pos= strmov(buf1,"rand_seed1=");
7289 pos= int10_to_str((long) seed1, pos, 10);
7290 pos= strmov(pos, ",rand_seed2=");
7291 pos= int10_to_str((long) seed2, pos, 10);
7292 protocol->store(buf1, (uint) (pos-buf1), &my_charset_bin);
7293 return 0;
7294 }
7295 #endif
7296
7297
Rand_log_event(const char * buf,const Format_description_log_event * description_event)7298 Rand_log_event::Rand_log_event(const char* buf,
7299 const Format_description_log_event* description_event)
7300 :Log_event(buf, description_event)
7301 {
7302 /* The Post-Header is empty. The Variable Data part begins immediately. */
7303 buf+= description_event->common_header_len +
7304 description_event->post_header_len[RAND_EVENT-1];
7305 seed1= uint8korr(buf+RAND_SEED1_OFFSET);
7306 seed2= uint8korr(buf+RAND_SEED2_OFFSET);
7307 }
7308
7309
7310 #ifndef MYSQL_CLIENT
write(IO_CACHE * file)7311 bool Rand_log_event::write(IO_CACHE* file)
7312 {
7313 uchar buf[16];
7314 int8store(buf + RAND_SEED1_OFFSET, seed1);
7315 int8store(buf + RAND_SEED2_OFFSET, seed2);
7316 return (write_header(file, sizeof(buf)) ||
7317 wrapper_my_b_safe_write(file, buf, sizeof(buf)) ||
7318 write_footer(file));
7319 }
7320 #endif
7321
7322
7323 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)7324 void Rand_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
7325 {
7326 IO_CACHE *const head= &print_event_info->head_cache;
7327
7328 char llbuff[22],llbuff2[22];
7329 if (!print_event_info->short_form)
7330 {
7331 print_header(head, print_event_info, FALSE);
7332 my_b_printf(head, "\tRand\n");
7333 }
7334 my_b_printf(head, "SET @@RAND_SEED1=%s, @@RAND_SEED2=%s%s\n",
7335 llstr(seed1, llbuff),llstr(seed2, llbuff2),
7336 print_event_info->delimiter);
7337 }
7338 #endif /* MYSQL_CLIENT */
7339
7340
7341 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
do_apply_event(Relay_log_info const * rli)7342 int Rand_log_event::do_apply_event(Relay_log_info const *rli)
7343 {
7344 /*
7345 We are now in a statement until the associated query log event has
7346 been processed.
7347 */
7348 const_cast<Relay_log_info*>(rli)->set_flag(Relay_log_info::IN_STMT);
7349
7350 if (rli->deferred_events_collecting)
7351 return rli->deferred_events->add(this);
7352
7353 thd->rand.seed1= (ulong) seed1;
7354 thd->rand.seed2= (ulong) seed2;
7355 return 0;
7356 }
7357
do_update_pos(Relay_log_info * rli)7358 int Rand_log_event::do_update_pos(Relay_log_info *rli)
7359 {
7360 rli->inc_event_relay_log_pos();
7361 return 0;
7362 }
7363
7364
7365 Log_event::enum_skip_reason
do_shall_skip(Relay_log_info * rli)7366 Rand_log_event::do_shall_skip(Relay_log_info *rli)
7367 {
7368 /*
7369 It is a common error to set the slave skip counter to 1 instead of
7370 2 when recovering from an insert which used a auto increment,
7371 rand, or user var. Therefore, if the slave skip counter is 1, we
7372 just say that this event should be skipped by ignoring it, meaning
7373 that we do not change the value of the slave skip counter since it
7374 will be decreased by the following insert event.
7375 */
7376 return continue_group(rli);
7377 }
7378
7379 /**
7380 Exec deferred Int-, Rand- and User- var events prefixing
7381 a Query-log-event event.
7382
7383 @param thd THD handle
7384
7385 @return false on success, true if a failure in an event applying occurred.
7386 */
slave_execute_deferred_events(THD * thd)7387 bool slave_execute_deferred_events(THD *thd)
7388 {
7389 bool res= false;
7390 Relay_log_info *rli= thd->rli_slave;
7391
7392 DBUG_ASSERT(rli && (!rli->deferred_events_collecting || rli->deferred_events));
7393
7394 if (!rli->deferred_events_collecting || rli->deferred_events->is_empty())
7395 return res;
7396
7397 res= rli->deferred_events->execute(rli);
7398
7399 return res;
7400 }
7401
7402 #endif /* !MYSQL_CLIENT */
7403
7404
7405 /**************************************************************************
7406 Xid_log_event methods
7407 **************************************************************************/
7408
7409 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
pack_info(Protocol * protocol)7410 int Xid_log_event::pack_info(Protocol *protocol)
7411 {
7412 char buf[128], *pos;
7413 pos= strmov(buf, "COMMIT /* xid=");
7414 pos= longlong10_to_str(xid, pos, 10);
7415 pos= strmov(pos, " */");
7416 protocol->store(buf, (uint) (pos-buf), &my_charset_bin);
7417 return 0;
7418 }
7419 #endif
7420
7421 /**
7422 @note
7423 It's ok not to use int8store here,
7424 as long as xid_t::set(ulonglong) and
7425 xid_t::get_my_xid doesn't do it either.
7426 We don't care about actual values of xids as long as
7427 identical numbers compare identically
7428 */
7429
7430 Xid_log_event::
Xid_log_event(const char * buf,const Format_description_log_event * description_event)7431 Xid_log_event(const char* buf,
7432 const Format_description_log_event *description_event)
7433 :Log_event(buf, description_event)
7434 {
7435 /* The Post-Header is empty. The Variable Data part begins immediately. */
7436 buf+= description_event->common_header_len +
7437 description_event->post_header_len[XID_EVENT-1];
7438 memcpy((char*) &xid, buf, sizeof(xid));
7439 }
7440
7441
7442 #ifndef MYSQL_CLIENT
write(IO_CACHE * file)7443 bool Xid_log_event::write(IO_CACHE* file)
7444 {
7445 DBUG_EXECUTE_IF("do_not_write_xid", return 0;);
7446 return (write_header(file, sizeof(xid)) ||
7447 wrapper_my_b_safe_write(file, (uchar*) &xid, sizeof(xid)) ||
7448 write_footer(file));
7449 }
7450 #endif
7451
7452
7453 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)7454 void Xid_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
7455 {
7456 IO_CACHE *const head= &print_event_info->head_cache;
7457
7458 if (!print_event_info->short_form)
7459 {
7460 char buf[64];
7461 longlong10_to_str(xid, buf, 10);
7462
7463 print_header(head, print_event_info, FALSE);
7464 my_b_printf(head, "\tXid = %s\n", buf);
7465 }
7466 my_b_printf(head, "COMMIT%s\n", print_event_info->delimiter);
7467 }
7468 #endif /* MYSQL_CLIENT */
7469
7470
7471 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
7472 /**
7473 The methods combines few commit actions to make it useable
7474 as in the single- so multi- threaded case.
7475
7476 @param thd a pointer to THD handle
7477 @return false as success and
7478 true as an error
7479 */
7480
do_commit(THD * thd)7481 bool Xid_log_event::do_commit(THD *thd)
7482 {
7483 DBUG_EXECUTE_IF("dbug.reached_commit",
7484 {DBUG_SET("+d,dbug.enabled_commit");});
7485 bool error= trans_commit(thd); /* Automatically rolls back on error. */
7486 DBUG_EXECUTE_IF("crash_after_apply",
7487 sql_print_information("Crashing crash_after_apply.");
7488 DBUG_SUICIDE(););
7489 thd->mdl_context.release_transactional_locks();
7490
7491 if (thd->variables.gtid_next.type == GTID_GROUP &&
7492 thd->owned_gtid.sidno != 0)
7493 {
7494 // GTID logging and cleanup runs regardless of the current res
7495 error |= gtid_empty_group_log_and_cleanup(thd);
7496 }
7497
7498 /*
7499 Increment the global status commit count variable
7500 */
7501 if (!error)
7502 status_var_increment(thd->status_var.com_stat[SQLCOM_COMMIT]);
7503
7504 return error;
7505 }
7506
7507 /**
7508 Worker commits Xid transaction and in case of its transactional
7509 info table marks the current group as done in the Coordnator's
7510 Group Assigned Queue.
7511
7512 @return zero as success or non-zero as an error
7513 */
do_apply_event_worker(Slave_worker * w)7514 int Xid_log_event::do_apply_event_worker(Slave_worker *w)
7515 {
7516 int error= 0;
7517 lex_start(thd);
7518 mysql_reset_thd_for_next_command(thd);
7519 Slave_committed_queue *coordinator_gaq= w->c_rli->gaq;
7520
7521 /* For a slave Xid_log_event is COMMIT */
7522 general_log_print(thd, COM_QUERY,
7523 "COMMIT /* implicit, from Xid_log_event */");
7524
7525 DBUG_PRINT("mts", ("do_apply group master %s %llu group relay %s %llu event %s %llu.",
7526 w->get_group_master_log_name(),
7527 w->get_group_master_log_pos(),
7528 w->get_group_relay_log_name(),
7529 w->get_group_relay_log_pos(),
7530 w->get_event_relay_log_name(),
7531 w->get_event_relay_log_pos()));
7532
7533 DBUG_EXECUTE_IF("crash_before_update_pos",
7534 sql_print_information("Crashing crash_before_update_pos.");
7535 DBUG_SUICIDE(););
7536
7537 ulong gaq_idx= mts_group_idx;
7538 Slave_job_group *ptr_group= coordinator_gaq->get_job_group(gaq_idx);
7539
7540 if ((error= w->commit_positions(this, ptr_group,
7541 w->c_rli->is_transactional())))
7542 goto err;
7543
7544 DBUG_PRINT("mts", ("do_apply group master %s %llu group relay %s %llu event %s %llu.",
7545 w->get_group_master_log_name(),
7546 w->get_group_master_log_pos(),
7547 w->get_group_relay_log_name(),
7548 w->get_group_relay_log_pos(),
7549 w->get_event_relay_log_name(),
7550 w->get_event_relay_log_pos()));
7551
7552 DBUG_EXECUTE_IF("crash_after_update_pos_before_apply",
7553 sql_print_information("Crashing crash_after_update_pos_before_apply.");
7554 DBUG_SUICIDE(););
7555
7556 error= do_commit(thd);
7557 if (error)
7558 w->rollback_positions(ptr_group);
7559 err:
7560 return error;
7561 }
7562
do_apply_event(Relay_log_info const * rli)7563 int Xid_log_event::do_apply_event(Relay_log_info const *rli)
7564 {
7565 DBUG_ENTER("Xid_log_event::do_apply_event");
7566 int error= 0;
7567 char saved_group_master_log_name[FN_REFLEN];
7568 char saved_group_relay_log_name[FN_REFLEN];
7569 volatile my_off_t saved_group_master_log_pos;
7570 volatile my_off_t saved_group_relay_log_pos;
7571
7572 char new_group_master_log_name[FN_REFLEN];
7573 char new_group_relay_log_name[FN_REFLEN];
7574 volatile my_off_t new_group_master_log_pos;
7575 volatile my_off_t new_group_relay_log_pos;
7576
7577 lex_start(thd);
7578 mysql_reset_thd_for_next_command(thd);
7579 Relay_log_info *rli_ptr= const_cast<Relay_log_info *>(rli);
7580 bool binlog_prot_acquired= false;
7581
7582 /* For a slave Xid_log_event is COMMIT */
7583 general_log_print(thd, COM_QUERY,
7584 "COMMIT /* implicit, from Xid_log_event */");
7585
7586 if (!thd->backup_binlog_lock.is_acquired())
7587 {
7588 const ulong timeout= thd->variables.lock_wait_timeout;
7589
7590 DBUG_PRINT("debug", ("Acquiring binlog protection lock"));
7591 mysql_mutex_assert_not_owner(&rli->data_lock);
7592 if (thd->backup_binlog_lock.acquire_protection(thd, MDL_EXPLICIT,
7593 timeout))
7594 DBUG_RETURN(1);
7595
7596 binlog_prot_acquired= true;
7597 }
7598
7599 mysql_mutex_lock(&rli_ptr->data_lock);
7600
7601 /*
7602 Save the rli positions. We need them to temporarily reset the positions
7603 just before the commit.
7604 */
7605 strmake(saved_group_master_log_name, rli_ptr->get_group_master_log_name(),
7606 FN_REFLEN - 1);
7607 saved_group_master_log_pos= rli_ptr->get_group_master_log_pos();
7608 strmake(saved_group_relay_log_name, rli_ptr->get_group_relay_log_name(),
7609 FN_REFLEN - 1);
7610 saved_group_relay_log_pos= rli_ptr->get_group_relay_log_pos();
7611
7612 DBUG_PRINT("info", ("do_apply group master %s %llu group relay %s %llu event %s %llu\n",
7613 rli_ptr->get_group_master_log_name(),
7614 rli_ptr->get_group_master_log_pos(),
7615 rli_ptr->get_group_relay_log_name(),
7616 rli_ptr->get_group_relay_log_pos(),
7617 rli_ptr->get_event_relay_log_name(),
7618 rli_ptr->get_event_relay_log_pos()));
7619
7620 DBUG_EXECUTE_IF("crash_before_update_pos",
7621 sql_print_information("Crashing crash_before_update_pos.");
7622 DBUG_SUICIDE(););
7623
7624 /*
7625 We need to update the positions in here to make it transactional.
7626 */
7627 rli_ptr->inc_event_relay_log_pos();
7628 rli_ptr->set_group_relay_log_pos(rli_ptr->get_event_relay_log_pos());
7629 rli_ptr->set_group_relay_log_name(rli_ptr->get_event_relay_log_name());
7630
7631 rli_ptr->notify_group_relay_log_name_update();
7632
7633 if (log_pos) // 3.23 binlogs don't have log_posx
7634 rli_ptr->set_group_master_log_pos(log_pos);
7635
7636 /*
7637 rli repository being transactional means replication is crash safe.
7638 Positions are written into transactional tables ahead of commit and the
7639 changes are made permanent during commit.
7640 */
7641 if (rli_ptr->is_transactional())
7642 {
7643 if ((error= rli_ptr->flush_info(true)))
7644 goto err;
7645 }
7646
7647 DBUG_PRINT("info", ("do_apply group master %s %llu group relay %s %llu event %s %llu\n",
7648 rli_ptr->get_group_master_log_name(),
7649 rli_ptr->get_group_master_log_pos(),
7650 rli_ptr->get_group_relay_log_name(),
7651 rli_ptr->get_group_relay_log_pos(),
7652 rli_ptr->get_event_relay_log_name(),
7653 rli_ptr->get_event_relay_log_pos()));
7654
7655 DBUG_EXECUTE_IF("crash_after_update_pos_before_apply",
7656 sql_print_information("Crashing crash_after_update_pos_before_apply.");
7657 DBUG_SUICIDE(););
7658
7659 /**
7660 Commit operation expects the global transaction state variable 'xa_state'to
7661 be set to 'XA_NOTR'. In order to simulate commit failure we set
7662 the 'xa_state' to 'XA_IDLE' so that the commit reports 'ER_XAER_RMFAIL'
7663 error.
7664 */
7665 DBUG_EXECUTE_IF("simulate_commit_failure",
7666 {
7667 thd->transaction.xid_state.xa_state = XA_IDLE;
7668 });
7669
7670 /*
7671 Save the new rli positions. These positions will be set back to group*
7672 positions on successful completion of the commit operation.
7673 */
7674 strmake(new_group_master_log_name, rli_ptr->get_group_master_log_name(),
7675 FN_REFLEN - 1);
7676 new_group_master_log_pos= rli_ptr->get_group_master_log_pos();
7677 strmake(new_group_relay_log_name, rli_ptr->get_group_relay_log_name(),
7678 FN_REFLEN - 1);
7679 new_group_relay_log_pos= rli_ptr->get_group_relay_log_pos();
7680 /*
7681 Rollback positions in memory just before commit. Position values will be
7682 reset to their new values only on successful commit operation.
7683 */
7684 rli_ptr->set_group_master_log_name(saved_group_master_log_name);
7685 rli_ptr->notify_group_master_log_name_update();
7686 rli_ptr->set_group_master_log_pos(saved_group_master_log_pos);
7687 rli_ptr->set_group_relay_log_name(saved_group_relay_log_name);
7688 rli_ptr->notify_group_relay_log_name_update();
7689 rli_ptr->set_group_relay_log_pos(saved_group_relay_log_pos);
7690
7691 DBUG_PRINT("info", ("Rolling back to group master %s %llu group relay %s"
7692 " %llu\n", rli_ptr->get_group_master_log_name(),
7693 rli_ptr->get_group_master_log_pos(),
7694 rli_ptr->get_group_relay_log_name(),
7695 rli_ptr->get_group_relay_log_pos()));
7696 mysql_mutex_unlock(&rli_ptr->data_lock);
7697 error= do_commit(thd);
7698 mysql_mutex_lock(&rli_ptr->data_lock);
7699 if (error)
7700 {
7701 rli->report(ERROR_LEVEL, thd->get_stmt_da()->sql_errno(),
7702 "Error in Xid_log_event: Commit could not be completed, '%s'",
7703 thd->get_stmt_da()->message());
7704 }
7705 else
7706 {
7707 DBUG_EXECUTE_IF("crash_after_commit_before_update_pos",
7708 sql_print_information("Crashing "
7709 "crash_after_commit_before_update_pos.");
7710 DBUG_SUICIDE(););
7711 /* Update positions on successful commit */
7712 rli_ptr->set_group_master_log_name(new_group_master_log_name);
7713 rli_ptr->notify_group_master_log_name_update();
7714 rli_ptr->set_group_master_log_pos(new_group_master_log_pos);
7715 rli_ptr->set_group_relay_log_name(new_group_relay_log_name);
7716 rli_ptr->notify_group_relay_log_name_update();
7717 rli_ptr->set_group_relay_log_pos(new_group_relay_log_pos);
7718
7719 DBUG_PRINT("info", ("Updating positions on succesful commit to group master"
7720 " %s %llu group relay %s %llu\n",
7721 rli_ptr->get_group_master_log_name(),
7722 rli_ptr->get_group_master_log_pos(),
7723 rli_ptr->get_group_relay_log_name(),
7724 rli_ptr->get_group_relay_log_pos()));
7725
7726 /*
7727 For transactional repository the positions are flushed ahead of commit.
7728 Where as for non transactional rli repository the positions are flushed
7729 only on succesful commit.
7730 */
7731 if (!rli_ptr->is_transactional())
7732 rli_ptr->flush_info(false);
7733 }
7734 err:
7735 mysql_cond_broadcast(&rli_ptr->data_cond);
7736 mysql_mutex_unlock(&rli_ptr->data_lock);
7737
7738 if (binlog_prot_acquired)
7739 {
7740 DBUG_PRINT("debug", ("Releasing binlog protection lock"));
7741 thd->backup_binlog_lock.release_protection(thd);
7742 }
7743
7744 DBUG_RETURN(error);
7745 }
7746
7747 Log_event::enum_skip_reason
do_shall_skip(Relay_log_info * rli)7748 Xid_log_event::do_shall_skip(Relay_log_info *rli)
7749 {
7750 DBUG_ENTER("Xid_log_event::do_shall_skip");
7751 if (rli->slave_skip_counter > 0) {
7752 thd->variables.option_bits&= ~OPTION_BEGIN;
7753 DBUG_RETURN(Log_event::EVENT_SKIP_COUNT);
7754 }
7755 DBUG_RETURN(Log_event::do_shall_skip(rli));
7756 }
7757 #endif /* !MYSQL_CLIENT */
7758
7759
7760 /**************************************************************************
7761 User_var_log_event methods
7762 **************************************************************************/
7763
7764 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
pack_info(Protocol * protocol)7765 int User_var_log_event::pack_info(Protocol* protocol)
7766 {
7767 char *buf= 0;
7768 char quoted_id[1 + FN_REFLEN * 2 + 2];// quoted identifier
7769 int id_len= my_strmov_quoted_identifier(this->thd, quoted_id, name, name_len);
7770 quoted_id[id_len]= '\0';
7771 uint val_offset= 2 + id_len;
7772 uint event_len= val_offset;
7773
7774 if (is_null)
7775 {
7776 if (!(buf= (char*) my_malloc(val_offset + 5, MYF(MY_WME))))
7777 return 1;
7778 strmov(buf + val_offset, "NULL");
7779 event_len= val_offset + 4;
7780 }
7781 else
7782 {
7783 switch (type) {
7784 case REAL_RESULT:
7785 double real_val;
7786 float8get(real_val, val);
7787 if (!(buf= (char*) my_malloc(val_offset + MY_GCVT_MAX_FIELD_WIDTH + 1,
7788 MYF(MY_WME))))
7789 return 1;
7790 event_len+= my_gcvt(real_val, MY_GCVT_ARG_DOUBLE, MY_GCVT_MAX_FIELD_WIDTH,
7791 buf + val_offset, NULL);
7792 break;
7793 case INT_RESULT:
7794 if (!(buf= (char*) my_malloc(val_offset + 22, MYF(MY_WME))))
7795 return 1;
7796 event_len= longlong10_to_str(uint8korr(val), buf + val_offset,
7797 ((flags & User_var_log_event::UNSIGNED_F) ?
7798 10 : -10))-buf;
7799 break;
7800 case DECIMAL_RESULT:
7801 {
7802 if (!(buf= (char*) my_malloc(val_offset + DECIMAL_MAX_STR_LENGTH + 1,
7803 MYF(MY_WME))))
7804 return 1;
7805 String str(buf+val_offset, DECIMAL_MAX_STR_LENGTH + 1, &my_charset_bin);
7806 my_decimal dec;
7807 binary2my_decimal(E_DEC_FATAL_ERROR, (uchar*) (val+2), &dec, val[0],
7808 val[1]);
7809 my_decimal2string(E_DEC_FATAL_ERROR, &dec, 0, 0, 0, &str);
7810 event_len= str.length() + val_offset;
7811 break;
7812 }
7813 case STRING_RESULT:
7814 /* 15 is for 'COLLATE' and other chars */
7815 buf= (char*) my_malloc(event_len+val_len*2+1+2*MY_CS_NAME_SIZE+15,
7816 MYF(MY_WME));
7817 CHARSET_INFO *cs;
7818 if (!buf)
7819 return 1;
7820 if (!(cs= get_charset(charset_number, MYF(0))))
7821 {
7822 strmov(buf+val_offset, "???");
7823 event_len+= 3;
7824 }
7825 else
7826 {
7827 char *p= strxmov(buf + val_offset, "_", cs->csname, " ", NullS);
7828 p= str_to_hex(p, val, val_len);
7829 p= strxmov(p, " COLLATE ", cs->name, NullS);
7830 event_len= p-buf;
7831 }
7832 break;
7833 case ROW_RESULT:
7834 default:
7835 DBUG_ASSERT(1);
7836 return 1;
7837 }
7838 }
7839 buf[0]= '@';
7840 memcpy(buf + 1, quoted_id, id_len);
7841 buf[1 + id_len]= '=';
7842 protocol->store(buf, event_len, &my_charset_bin);
7843 my_free(buf);
7844 return 0;
7845 }
7846 #endif /* !MYSQL_CLIENT */
7847
7848
7849 User_var_log_event::
User_var_log_event(const char * buf,uint event_len,const Format_description_log_event * description_event)7850 User_var_log_event(const char* buf, uint event_len,
7851 const Format_description_log_event* description_event)
7852 :Log_event(buf, description_event)
7853 #ifndef MYSQL_CLIENT
7854 , deferred(false), query_id(0)
7855 #endif
7856 {
7857 bool error= false;
7858 const char* buf_start= buf;
7859 /* The Post-Header is empty. The Variable Data part begins immediately. */
7860 const char *start= buf;
7861 buf+= description_event->common_header_len +
7862 description_event->post_header_len[USER_VAR_EVENT-1];
7863 name_len= uint4korr(buf);
7864 /* Avoid reading out of buffer */
7865 if ((buf - buf_start) + UV_NAME_LEN_SIZE + name_len > event_len)
7866 {
7867 error= true;
7868 goto err;
7869 }
7870
7871 name= (char *) buf + UV_NAME_LEN_SIZE;
7872
7873 /*
7874 We don't know yet is_null value, so we must assume that name_len
7875 may have the bigger value possible, is_null= True and there is no
7876 payload for val, or even that name_len is 0.
7877 */
7878 if (!valid_buffer_range<uint>(name_len, buf_start, name,
7879 event_len - UV_VAL_IS_NULL))
7880 {
7881 error= true;
7882 goto err;
7883 }
7884
7885 buf+= UV_NAME_LEN_SIZE + name_len;
7886 is_null= (bool) *buf;
7887 flags= User_var_log_event::UNDEF_F; // defaults to UNDEF_F
7888 if (is_null)
7889 {
7890 type= STRING_RESULT;
7891 charset_number= my_charset_bin.number;
7892 val_len= 0;
7893 val= 0;
7894 }
7895 else
7896 {
7897 if (!valid_buffer_range<uint>(UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE
7898 + UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE,
7899 buf_start, buf, event_len))
7900 {
7901 error= true;
7902 goto err;
7903 }
7904
7905 type= (Item_result) buf[UV_VAL_IS_NULL];
7906 charset_number= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE);
7907 val_len= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
7908 UV_CHARSET_NUMBER_SIZE);
7909 val= (char *) (buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
7910 UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE);
7911
7912 if (!valid_buffer_range<uint>(val_len, buf_start, val, event_len))
7913 {
7914 error= true;
7915 goto err;
7916 }
7917
7918 /**
7919 We need to check if this is from an old server
7920 that did not pack information for flags.
7921 We do this by checking if there are extra bytes
7922 after the packed value. If there are we take the
7923 extra byte and it's value is assumed to contain
7924 the flags value.
7925
7926 Old events will not have this extra byte, thence,
7927 we keep the flags set to UNDEF_F.
7928 */
7929 uint bytes_read= ((val + val_len) - start);
7930 if (bytes_read > event_len)
7931 {
7932 error= true;
7933 goto err;
7934 }
7935 #ifndef DBUG_OFF
7936 bool old_pre_checksum_fd= description_event->is_version_before_checksum();
7937 const int checksum_length = (old_pre_checksum_fd || description_event->checksum_alg == BINLOG_CHECKSUM_ALG_OFF) ? 0 : BINLOG_CHECKSUM_LEN;
7938 #endif
7939 DBUG_ASSERT(bytes_read == data_written - checksum_length || bytes_read == data_written - checksum_length - 1);
7940 if ((data_written - bytes_read) > 0)
7941 {
7942 flags= (uint) *(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
7943 UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE +
7944 val_len);
7945 }
7946 }
7947
7948 err:
7949 if (error)
7950 name= 0;
7951 }
7952
7953
7954 #ifndef MYSQL_CLIENT
write(IO_CACHE * file)7955 bool User_var_log_event::write(IO_CACHE* file)
7956 {
7957 char buf[UV_NAME_LEN_SIZE];
7958 char buf1[UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
7959 UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE];
7960 uchar buf2[MY_MAX(8, DECIMAL_MAX_FIELD_SIZE + 2)], *pos= buf2;
7961 uint unsigned_len= 0;
7962 uint buf1_length;
7963 ulong event_length;
7964
7965 int4store(buf, name_len);
7966
7967 if ((buf1[0]= is_null))
7968 {
7969 buf1_length= 1;
7970 val_len= 0; // Length of 'pos'
7971 }
7972 else
7973 {
7974 buf1[1]= type;
7975 int4store(buf1 + 2, charset_number);
7976
7977 switch (type) {
7978 case REAL_RESULT:
7979 float8store(buf2, *(double*) val);
7980 break;
7981 case INT_RESULT:
7982 int8store(buf2, *(longlong*) val);
7983 unsigned_len= 1;
7984 break;
7985 case DECIMAL_RESULT:
7986 {
7987 my_decimal *dec= (my_decimal *)val;
7988 dec->fix_buffer_pointer();
7989 buf2[0]= (char)(dec->intg + dec->frac);
7990 buf2[1]= (char)dec->frac;
7991 decimal2bin((decimal_t*)val, buf2+2, buf2[0], buf2[1]);
7992 val_len= decimal_bin_size(buf2[0], buf2[1]) + 2;
7993 break;
7994 }
7995 case STRING_RESULT:
7996 pos= (uchar*) val;
7997 break;
7998 case ROW_RESULT:
7999 default:
8000 DBUG_ASSERT(1);
8001 return 0;
8002 }
8003 int4store(buf1 + 2 + UV_CHARSET_NUMBER_SIZE, val_len);
8004 buf1_length= 10;
8005 }
8006
8007 /* Length of the whole event */
8008 event_length= sizeof(buf)+ name_len + buf1_length + val_len + unsigned_len;
8009
8010 return (write_header(file, event_length) ||
8011 wrapper_my_b_safe_write(file, (uchar*) buf, sizeof(buf)) ||
8012 wrapper_my_b_safe_write(file, (uchar*) name, name_len) ||
8013 wrapper_my_b_safe_write(file, (uchar*) buf1, buf1_length) ||
8014 wrapper_my_b_safe_write(file, pos, val_len) ||
8015 wrapper_my_b_safe_write(file, &flags, unsigned_len) ||
8016 write_footer(file));
8017 }
8018 #endif
8019
8020
8021 /*
8022 User_var_log_event::print()
8023 */
8024
8025 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)8026 void User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
8027 {
8028 IO_CACHE *const head= &print_event_info->head_cache;
8029 char quoted_id[1 + NAME_LEN * 2 + 2];// quoted length of the identifier
8030 char name_id[NAME_LEN];
8031 int quoted_len= 0;
8032
8033 if (!print_event_info->short_form)
8034 {
8035 print_header(head, print_event_info, FALSE);
8036 my_b_printf(head, "\tUser_var\n");
8037 }
8038 strmov(name_id, name);
8039 name_id[name_len]= '\0';
8040 my_b_printf(head, "SET @");
8041 quoted_len= my_strmov_quoted_identifier((char *) quoted_id,
8042 (const char *) name_id);
8043 quoted_id[quoted_len]= '\0';
8044 my_b_write(head, (uchar*) quoted_id, quoted_len);
8045
8046 if (is_null)
8047 {
8048 my_b_printf(head, ":=NULL%s\n", print_event_info->delimiter);
8049 }
8050 else
8051 {
8052 switch (type) {
8053 case REAL_RESULT:
8054 double real_val;
8055 char real_buf[FMT_G_BUFSIZE(14)];
8056 float8get(real_val, val);
8057 sprintf(real_buf, "%.14g", real_val);
8058 my_b_printf(head, ":=%s%s\n", real_buf, print_event_info->delimiter);
8059 break;
8060 case INT_RESULT:
8061 char int_buf[22];
8062 longlong10_to_str(uint8korr(val), int_buf,
8063 ((flags & User_var_log_event::UNSIGNED_F) ? 10 : -10));
8064 my_b_printf(head, ":=%s%s\n", int_buf, print_event_info->delimiter);
8065 break;
8066 case DECIMAL_RESULT:
8067 {
8068 char str_buf[200];
8069 int str_len= sizeof(str_buf) - 1;
8070 int precision= (int)val[0];
8071 int scale= (int)val[1];
8072 decimal_digit_t dec_buf[10];
8073 decimal_t dec;
8074 dec.len= 10;
8075 dec.buf= dec_buf;
8076
8077 bin2decimal((uchar*) val+2, &dec, precision, scale);
8078 decimal2string(&dec, str_buf, &str_len, 0, 0, 0);
8079 str_buf[str_len]= 0;
8080 my_b_printf(head, ":=%s%s\n", str_buf, print_event_info->delimiter);
8081 break;
8082 }
8083 case STRING_RESULT:
8084 {
8085 /*
8086 Let's express the string in hex. That's the most robust way. If we
8087 print it in character form instead, we need to escape it with
8088 character_set_client which we don't know (we will know it in 5.0, but
8089 in 4.1 we don't know it easily when we are printing
8090 User_var_log_event). Explanation why we would need to bother with
8091 character_set_client (quoting Bar):
8092 > Note, the parser doesn't switch to another unescaping mode after
8093 > it has met a character set introducer.
8094 > For example, if an SJIS client says something like:
8095 > SET @a= _ucs2 \0a\0b'
8096 > the string constant is still unescaped according to SJIS, not
8097 > according to UCS2.
8098 */
8099 char *hex_str;
8100 CHARSET_INFO *cs;
8101
8102 hex_str= (char *)my_malloc(2*val_len+1+2,MYF(MY_WME)); // 2 hex digits / byte
8103 if (!hex_str)
8104 return;
8105 str_to_hex(hex_str, val, val_len);
8106 /*
8107 For proper behaviour when mysqlbinlog|mysql, we need to explicitely
8108 specify the variable's collation. It will however cause problems when
8109 people want to mysqlbinlog|mysql into another server not supporting the
8110 character set. But there's not much to do about this and it's unlikely.
8111 */
8112 if (!(cs= get_charset(charset_number, MYF(0))))
8113 /*
8114 Generate an unusable command (=> syntax error) is probably the best
8115 thing we can do here.
8116 */
8117 my_b_printf(head, ":=???%s\n", print_event_info->delimiter);
8118 else
8119 my_b_printf(head, ":=_%s %s COLLATE `%s`%s\n",
8120 cs->csname, hex_str, cs->name,
8121 print_event_info->delimiter);
8122 my_free(hex_str);
8123 }
8124 break;
8125 case ROW_RESULT:
8126 default:
8127 DBUG_ASSERT(1);
8128 return;
8129 }
8130 }
8131 }
8132 #endif
8133
8134
8135 /*
8136 User_var_log_event::do_apply_event()
8137 */
8138
8139 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
do_apply_event(Relay_log_info const * rli)8140 int User_var_log_event::do_apply_event(Relay_log_info const *rli)
8141 {
8142 Item *it= 0;
8143 CHARSET_INFO *charset;
8144 query_id_t sav_query_id= 0; /* memorize orig id when deferred applying */
8145
8146 if (rli->deferred_events_collecting)
8147 {
8148 set_deferred(current_thd->query_id);
8149 return rli->deferred_events->add(this);
8150 } else if (is_deferred())
8151 {
8152 sav_query_id= current_thd->query_id;
8153 current_thd->query_id= query_id; /* recreating original time context */
8154 }
8155
8156 if (!(charset= get_charset(charset_number, MYF(MY_WME))))
8157 {
8158 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
8159 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
8160 "Invalid character set for User var event");
8161 return 1;
8162 }
8163 double real_val;
8164 longlong int_val;
8165
8166 /*
8167 We are now in a statement until the associated query log event has
8168 been processed.
8169 */
8170 const_cast<Relay_log_info*>(rli)->set_flag(Relay_log_info::IN_STMT);
8171
8172 if (is_null)
8173 {
8174 it= new Item_null();
8175 }
8176 else
8177 {
8178 switch (type) {
8179 case REAL_RESULT:
8180 if (val_len != 8)
8181 {
8182 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
8183 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
8184 "Invalid variable length at User var event");
8185 return 1;
8186 }
8187 float8get(real_val, val);
8188 it= new Item_float(real_val, 0);
8189 val= (char*) &real_val; // Pointer to value in native format
8190 val_len= 8;
8191 break;
8192 case INT_RESULT:
8193 if (val_len != 8)
8194 {
8195 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
8196 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
8197 "Invalid variable length at User var event");
8198 return 1;
8199 }
8200 int_val= (longlong) uint8korr(val);
8201 it= new Item_int(int_val);
8202 val= (char*) &int_val; // Pointer to value in native format
8203 val_len= 8;
8204 break;
8205 case DECIMAL_RESULT:
8206 {
8207 if (val_len < 3)
8208 {
8209 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
8210 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
8211 "Invalid variable length at User var event");
8212 return 1;
8213 }
8214 Item_decimal *dec= new Item_decimal((uchar*) val+2, val[0], val[1]);
8215 it= dec;
8216 val= (char *)dec->val_decimal(NULL);
8217 val_len= sizeof(my_decimal);
8218 break;
8219 }
8220 case STRING_RESULT:
8221 it= new Item_string(val, val_len, charset);
8222 break;
8223 case ROW_RESULT:
8224 default:
8225 DBUG_ASSERT(1);
8226 return 0;
8227 }
8228 }
8229 Item_func_set_user_var *e=
8230 new Item_func_set_user_var(Name_string(name, name_len, false), it, false);
8231 /*
8232 Item_func_set_user_var can't substitute something else on its place =>
8233 0 can be passed as last argument (reference on item)
8234
8235 Fix_fields() can fail, in which case a call of update_hash() might
8236 crash the server, so if fix fields fails, we just return with an
8237 error.
8238 */
8239 if (e->fix_fields(thd, 0))
8240 return 1;
8241
8242 /*
8243 A variable can just be considered as a table with
8244 a single record and with a single column. Thus, like
8245 a column value, it could always have IMPLICIT derivation.
8246 */
8247 e->update_hash(val, val_len, type, charset, DERIVATION_IMPLICIT,
8248 (flags & User_var_log_event::UNSIGNED_F));
8249 if (!is_deferred())
8250 free_root(thd->mem_root, 0);
8251 else
8252 current_thd->query_id= sav_query_id; /* restore current query's context */
8253
8254 return 0;
8255 }
8256
do_update_pos(Relay_log_info * rli)8257 int User_var_log_event::do_update_pos(Relay_log_info *rli)
8258 {
8259 rli->inc_event_relay_log_pos();
8260 return 0;
8261 }
8262
8263 Log_event::enum_skip_reason
do_shall_skip(Relay_log_info * rli)8264 User_var_log_event::do_shall_skip(Relay_log_info *rli)
8265 {
8266 /*
8267 It is a common error to set the slave skip counter to 1 instead
8268 of 2 when recovering from an insert which used a auto increment,
8269 rand, or user var. Therefore, if the slave skip counter is 1, we
8270 just say that this event should be skipped by ignoring it, meaning
8271 that we do not change the value of the slave skip counter since it
8272 will be decreased by the following insert event.
8273 */
8274 return continue_group(rli);
8275 }
8276 #endif /* !MYSQL_CLIENT */
8277
8278
8279 /**************************************************************************
8280 Unknown_log_event methods
8281 **************************************************************************/
8282
8283 #ifdef HAVE_REPLICATION
8284 #ifdef MYSQL_CLIENT
print(FILE * file_arg,PRINT_EVENT_INFO * print_event_info)8285 void Unknown_log_event::print(FILE* file_arg, PRINT_EVENT_INFO* print_event_info)
8286 {
8287 if (print_event_info->short_form)
8288 return;
8289 print_header(&print_event_info->head_cache, print_event_info, FALSE);
8290 my_b_printf(&print_event_info->head_cache, "\n# %s", "Unknown event\n");
8291 }
8292 #endif
8293
8294 /**************************************************************************
8295 Stop_log_event methods
8296 **************************************************************************/
8297
8298 /*
8299 Stop_log_event::print()
8300 */
8301
8302 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)8303 void Stop_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
8304 {
8305 if (print_event_info->short_form)
8306 return;
8307
8308 print_header(&print_event_info->head_cache, print_event_info, FALSE);
8309 my_b_printf(&print_event_info->head_cache, "\tStop\n");
8310 }
8311 #endif /* MYSQL_CLIENT */
8312
8313
8314 #ifndef MYSQL_CLIENT
8315 /*
8316 The master stopped. We used to clean up all temporary tables but
8317 this is useless as, as the master has shut down properly, it has
8318 written all DROP TEMPORARY TABLE (prepared statements' deletion is
8319 TODO only when we binlog prep stmts). We used to clean up
8320 slave_load_tmpdir, but this is useless as it has been cleared at the
8321 end of LOAD DATA INFILE. So we have nothing to do here. The place
8322 were we must do this cleaning is in
8323 Start_log_event_v3::do_apply_event(), not here. Because if we come
8324 here, the master was sane.
8325
8326 This must only be called from the Slave SQL thread, since it calls
8327 flush_relay_log_info().
8328 */
do_update_pos(Relay_log_info * rli)8329 int Stop_log_event::do_update_pos(Relay_log_info *rli)
8330 {
8331 int error_inc= 0;
8332 int error_flush= 0;
8333 /*
8334 We do not want to update master_log pos because we get a rotate event
8335 before stop, so by now group_master_log_name is set to the next log.
8336 If we updated it, we will have incorrect master coordinates and this
8337 could give false triggers in MASTER_POS_WAIT() that we have reached
8338 the target position when in fact we have not.
8339 The group position is always unchanged in MTS mode because the event
8340 is never executed so can't be scheduled to a Worker.
8341 */
8342 if ((thd->variables.option_bits & OPTION_BEGIN) || rli->is_parallel_exec())
8343 rli->inc_event_relay_log_pos();
8344 else
8345 {
8346 error_inc= rli->inc_group_relay_log_pos(0, true/*need_data_lock=true*/);
8347 error_flush= rli->flush_info(TRUE);
8348 }
8349 return (error_inc || error_flush);
8350 }
8351
8352 #endif /* !MYSQL_CLIENT */
8353 #endif /* HAVE_REPLICATION */
8354
8355
8356 /**************************************************************************
8357 Create_file_log_event methods
8358 **************************************************************************/
8359
8360 /*
8361 Create_file_log_event ctor
8362 */
8363
8364 #ifndef MYSQL_CLIENT
8365 Create_file_log_event::
Create_file_log_event(THD * thd_arg,sql_exchange * ex,const char * db_arg,const char * table_name_arg,List<Item> & fields_arg,bool is_concurrent_arg,enum enum_duplicates handle_dup,bool ignore,uchar * block_arg,uint block_len_arg,bool using_trans)8366 Create_file_log_event(THD* thd_arg, sql_exchange* ex,
8367 const char* db_arg, const char* table_name_arg,
8368 List<Item>& fields_arg,
8369 bool is_concurrent_arg,
8370 enum enum_duplicates handle_dup,
8371 bool ignore,
8372 uchar* block_arg, uint block_len_arg, bool using_trans)
8373 :Load_log_event(thd_arg, ex, db_arg, table_name_arg, fields_arg,
8374 is_concurrent_arg,
8375 handle_dup, ignore, using_trans),
8376 fake_base(0), block(block_arg), event_buf(0), block_len(block_len_arg),
8377 file_id(thd_arg->file_id = mysql_bin_log.next_file_id())
8378 {
8379 DBUG_ENTER("Create_file_log_event");
8380 sql_ex.force_new_format();
8381 DBUG_VOID_RETURN;
8382 }
8383
8384
8385 /*
8386 Create_file_log_event::write_data_body()
8387 */
8388
write_data_body(IO_CACHE * file)8389 bool Create_file_log_event::write_data_body(IO_CACHE* file)
8390 {
8391 bool res;
8392 if ((res= Load_log_event::write_data_body(file)) || fake_base)
8393 return res;
8394 return (my_b_safe_write(file, (uchar*) "", 1) ||
8395 my_b_safe_write(file, (uchar*) block, block_len));
8396 }
8397
8398
8399 /*
8400 Create_file_log_event::write_data_header()
8401 */
8402
write_data_header(IO_CACHE * file)8403 bool Create_file_log_event::write_data_header(IO_CACHE* file)
8404 {
8405 bool res;
8406 uchar buf[CREATE_FILE_HEADER_LEN];
8407 if ((res= Load_log_event::write_data_header(file)) || fake_base)
8408 return res;
8409 int4store(buf + CF_FILE_ID_OFFSET, file_id);
8410 return my_b_safe_write(file, buf, CREATE_FILE_HEADER_LEN) != 0;
8411 }
8412
8413
8414 /*
8415 Create_file_log_event::write_base()
8416 */
8417
write_base(IO_CACHE * file)8418 bool Create_file_log_event::write_base(IO_CACHE* file)
8419 {
8420 bool res;
8421 fake_base= 1; // pretend we are Load event
8422 res= write(file);
8423 fake_base= 0;
8424 return res;
8425 }
8426
8427 #endif /* !MYSQL_CLIENT */
8428
8429 /*
8430 Create_file_log_event ctor
8431 */
8432
Create_file_log_event(const char * buf,uint len,const Format_description_log_event * description_event)8433 Create_file_log_event::Create_file_log_event(const char* buf, uint len,
8434 const Format_description_log_event* description_event)
8435 :Load_log_event(buf,0,description_event),fake_base(0),block(0),inited_from_old(0)
8436 {
8437 DBUG_ENTER("Create_file_log_event::Create_file_log_event(char*,...)");
8438 uint block_offset;
8439 uint header_len= description_event->common_header_len;
8440 uint8 load_header_len= description_event->post_header_len[LOAD_EVENT-1];
8441 uint8 create_file_header_len= description_event->post_header_len[CREATE_FILE_EVENT-1];
8442 if (!(event_buf= (char*) my_memdup(buf, len, MYF(MY_WME))) ||
8443 copy_log_event(event_buf,len,
8444 ((buf[EVENT_TYPE_OFFSET] == LOAD_EVENT) ?
8445 load_header_len + header_len :
8446 (fake_base ? (header_len+load_header_len) :
8447 (header_len+load_header_len) +
8448 create_file_header_len)),
8449 description_event))
8450 DBUG_VOID_RETURN;
8451 if (description_event->binlog_version!=1)
8452 {
8453 file_id= uint4korr(buf +
8454 header_len +
8455 load_header_len + CF_FILE_ID_OFFSET);
8456 /*
8457 Note that it's ok to use get_data_size() below, because it is computed
8458 with values we have already read from this event (because we called
8459 copy_log_event()); we are not using slave's format info to decode
8460 master's format, we are really using master's format info.
8461 Anyway, both formats should be identical (except the common_header_len)
8462 as these Load events are not changed between 4.0 and 5.0 (as logging of
8463 LOAD DATA INFILE does not use Load_log_event in 5.0).
8464
8465 The + 1 is for \0 terminating fname
8466 */
8467 block_offset= (description_event->common_header_len +
8468 Load_log_event::get_data_size() +
8469 create_file_header_len + 1);
8470 if (len < block_offset)
8471 DBUG_VOID_RETURN;
8472 block = (uchar*)buf + block_offset;
8473 block_len = len - block_offset;
8474 }
8475 else
8476 {
8477 sql_ex.force_new_format();
8478 inited_from_old = 1;
8479 }
8480 DBUG_VOID_RETURN;
8481 }
8482
8483
8484 /*
8485 Create_file_log_event::print()
8486 */
8487
8488 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info,bool enable_local)8489 void Create_file_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info,
8490 bool enable_local)
8491 {
8492 if (print_event_info->short_form)
8493 {
8494 if (enable_local && check_fname_outside_temp_buf())
8495 Load_log_event::print(file, print_event_info);
8496 return;
8497 }
8498
8499 if (enable_local)
8500 {
8501 Load_log_event::print(file, print_event_info,
8502 !check_fname_outside_temp_buf());
8503 /**
8504 reduce the size of io cache so that the write function is called
8505 for every call to my_b_printf().
8506 */
8507 DBUG_EXECUTE_IF ("simulate_create_event_write_error",
8508 {(&print_event_info->head_cache)->write_pos=
8509 (&print_event_info->head_cache)->write_end;
8510 DBUG_SET("+d,simulate_file_write_error");});
8511 /*
8512 That one is for "file_id: etc" below: in mysqlbinlog we want the #, in
8513 SHOW BINLOG EVENTS we don't.
8514 */
8515 my_b_printf(&print_event_info->head_cache, "#");
8516 }
8517
8518 my_b_printf(&print_event_info->head_cache,
8519 " file_id: %d block_len: %d\n", file_id, block_len);
8520 }
8521
8522
print(FILE * file,PRINT_EVENT_INFO * print_event_info)8523 void Create_file_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
8524 {
8525 print(file, print_event_info, 0);
8526 }
8527 #endif /* MYSQL_CLIENT */
8528
8529
8530 /*
8531 Create_file_log_event::pack_info()
8532 */
8533
8534 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
pack_info(Protocol * protocol)8535 int Create_file_log_event::pack_info(Protocol *protocol)
8536 {
8537 char buf[NAME_LEN*2 + 30 + 21*2], *pos;
8538 pos= strmov(buf, "db=");
8539 memcpy(pos, db, db_len);
8540 pos= strmov(pos + db_len, ";table=");
8541 memcpy(pos, table_name, table_name_len);
8542 pos= strmov(pos + table_name_len, ";file_id=");
8543 pos= int10_to_str((long) file_id, pos, 10);
8544 pos= strmov(pos, ";block_len=");
8545 pos= int10_to_str((long) block_len, pos, 10);
8546 protocol->store(buf, (uint) (pos-buf), &my_charset_bin);
8547 return 0;
8548 }
8549 #endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
8550
8551
8552 /**
8553 Create_file_log_event::do_apply_event()
8554 Constructor for Create_file_log_event to intantiate an event
8555 from the relay log on the slave.
8556
8557 @retval
8558 0 Success
8559 @retval
8560 1 Failure
8561 */
8562
8563 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
do_apply_event(Relay_log_info const * rli)8564 int Create_file_log_event::do_apply_event(Relay_log_info const *rli)
8565 {
8566 char fname_buf[FN_REFLEN+TEMP_FILE_MAX_LEN];
8567 char *ext;
8568 int fd = -1;
8569 IO_CACHE file;
8570 int error = 1;
8571
8572 lex_start(thd);
8573 mysql_reset_thd_for_next_command(thd);
8574 THD_STAGE_INFO(thd, stage_making_temp_file_create_before_load_data);
8575 memset(&file, 0, sizeof(file));
8576 ext= slave_load_file_stem(fname_buf, file_id, server_id, ".info");
8577 /* old copy may exist already */
8578 mysql_file_delete(key_file_log_event_info, fname_buf, MYF(0));
8579 /**
8580 To simulate file creation failure, convert the file name to a
8581 directory by appending a "/" to the file name.
8582 */
8583 DBUG_EXECUTE_IF("simulate_file_create_error_create_log_event",
8584 {
8585 strcat(fname_buf,"/");
8586 });
8587 if ((fd= mysql_file_create(key_file_log_event_info,
8588 fname_buf, CREATE_MODE,
8589 O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW,
8590 MYF(MY_WME))) < 0 ||
8591 init_io_cache(&file, fd, IO_SIZE, WRITE_CACHE, (my_off_t)0, 0,
8592 MYF(MY_WME|MY_NABP)))
8593 {
8594 rli->report(ERROR_LEVEL, thd->get_stmt_da()->sql_errno(),
8595 "Error in Create_file event: could not open file '%s'",
8596 fname_buf);
8597 goto err;
8598 }
8599
8600 // a trick to avoid allocating another buffer
8601 fname= fname_buf;
8602 fname_len= (uint) (strmov(ext, ".data") - fname);
8603 if (write_base(&file))
8604 {
8605 strmov(ext, ".info"); // to have it right in the error message
8606 rli->report(ERROR_LEVEL, my_errno,
8607 "Error in Create_file event: could not write to file '%s'",
8608 fname_buf);
8609 goto err;
8610 }
8611 end_io_cache(&file);
8612 mysql_file_close(fd, MYF(0));
8613
8614 // fname_buf now already has .data, not .info, because we did our trick
8615 /* old copy may exist already */
8616 mysql_file_delete(key_file_log_event_data, fname_buf, MYF(0));
8617 if ((fd= mysql_file_create(key_file_log_event_data,
8618 fname_buf, CREATE_MODE,
8619 O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW,
8620 MYF(MY_WME))) < 0)
8621 {
8622 rli->report(ERROR_LEVEL, my_errno,
8623 "Error in Create_file event: could not open file '%s'",
8624 fname_buf);
8625 goto err;
8626 }
8627 /**
8628 To simulate file write failure,close the file before the write operation.
8629 Write will fail with an error reporting file is UNOPENED.
8630 */
8631 DBUG_EXECUTE_IF("simulate_file_write_error_create_log_event",
8632 {
8633 mysql_file_close(fd, MYF(0));
8634 });
8635 if (mysql_file_write(fd, (uchar*) block, block_len, MYF(MY_WME+MY_NABP)))
8636 {
8637 rli->report(ERROR_LEVEL, thd->get_stmt_da()->sql_errno(),
8638 "Error in Create_file event: write to '%s' failed",
8639 fname_buf);
8640 goto err;
8641 }
8642 error=0; // Everything is ok
8643
8644 err:
8645 if (error)
8646 end_io_cache(&file);
8647 if (fd >= 0)
8648 mysql_file_close(fd, MYF(0));
8649 return error != 0;
8650 }
8651 #endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
8652
8653
8654 /**************************************************************************
8655 Append_block_log_event methods
8656 **************************************************************************/
8657
8658 /*
8659 Append_block_log_event ctor
8660 */
8661
8662 #ifndef MYSQL_CLIENT
Append_block_log_event(THD * thd_arg,const char * db_arg,uchar * block_arg,uint block_len_arg,bool using_trans)8663 Append_block_log_event::Append_block_log_event(THD *thd_arg,
8664 const char *db_arg,
8665 uchar *block_arg,
8666 uint block_len_arg,
8667 bool using_trans)
8668 :Log_event(thd_arg, 0,
8669 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
8670 Log_event::EVENT_STMT_CACHE,
8671 Log_event::EVENT_NORMAL_LOGGING),
8672 block(block_arg),
8673 block_len(block_len_arg), file_id(thd_arg->file_id), db(db_arg)
8674 {
8675 }
8676 #endif
8677
8678
8679 /*
8680 Append_block_log_event ctor
8681 */
8682
Append_block_log_event(const char * buf,uint len,const Format_description_log_event * description_event)8683 Append_block_log_event::Append_block_log_event(const char* buf, uint len,
8684 const Format_description_log_event* description_event)
8685 :Log_event(buf, description_event),block(0)
8686 {
8687 DBUG_ENTER("Append_block_log_event::Append_block_log_event(char*,...)");
8688 uint8 common_header_len= description_event->common_header_len;
8689 uint8 append_block_header_len=
8690 description_event->post_header_len[APPEND_BLOCK_EVENT-1];
8691 uint total_header_len= common_header_len+append_block_header_len;
8692 if (len < total_header_len)
8693 DBUG_VOID_RETURN;
8694 file_id= uint4korr(buf + common_header_len + AB_FILE_ID_OFFSET);
8695 block= (uchar*)buf + total_header_len;
8696 block_len= len - total_header_len;
8697 DBUG_VOID_RETURN;
8698 }
8699
8700
8701 /*
8702 Append_block_log_event::write()
8703 */
8704
8705 #ifndef MYSQL_CLIENT
write(IO_CACHE * file)8706 bool Append_block_log_event::write(IO_CACHE* file)
8707 {
8708 uchar buf[APPEND_BLOCK_HEADER_LEN];
8709 int4store(buf + AB_FILE_ID_OFFSET, file_id);
8710 return (write_header(file, APPEND_BLOCK_HEADER_LEN + block_len) ||
8711 wrapper_my_b_safe_write(file, buf, APPEND_BLOCK_HEADER_LEN) ||
8712 wrapper_my_b_safe_write(file, (uchar*) block, block_len) ||
8713 write_footer(file));
8714 }
8715 #endif
8716
8717
8718 /*
8719 Append_block_log_event::print()
8720 */
8721
8722 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)8723 void Append_block_log_event::print(FILE* file,
8724 PRINT_EVENT_INFO* print_event_info)
8725 {
8726 if (print_event_info->short_form)
8727 return;
8728 print_header(&print_event_info->head_cache, print_event_info, FALSE);
8729 my_b_printf(&print_event_info->head_cache,
8730 "\n#%s: file_id: %d block_len: %d\n",
8731 get_type_str(), file_id, block_len);
8732 }
8733 #endif /* MYSQL_CLIENT */
8734
8735
8736 /*
8737 Append_block_log_event::pack_info()
8738 */
8739
8740 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
pack_info(Protocol * protocol)8741 int Append_block_log_event::pack_info(Protocol *protocol)
8742 {
8743 char buf[256];
8744 size_t length;
8745 length= my_snprintf(buf, sizeof(buf), ";file_id=%u;block_len=%u",
8746 file_id, block_len);
8747 protocol->store(buf, length, &my_charset_bin);
8748 return 0;
8749 }
8750
8751
8752 /*
8753 Append_block_log_event::get_create_or_append()
8754 */
8755
get_create_or_append() const8756 int Append_block_log_event::get_create_or_append() const
8757 {
8758 return 0; /* append to the file, fail if not exists */
8759 }
8760
8761 /*
8762 Append_block_log_event::do_apply_event()
8763 */
8764
do_apply_event(Relay_log_info const * rli)8765 int Append_block_log_event::do_apply_event(Relay_log_info const *rli)
8766 {
8767 char fname[FN_REFLEN+TEMP_FILE_MAX_LEN];
8768 int fd;
8769 int error = 1;
8770 DBUG_ENTER("Append_block_log_event::do_apply_event");
8771
8772 THD_STAGE_INFO(thd, stage_making_temp_file_append_before_load_data);
8773 slave_load_file_stem(fname, file_id, server_id, ".data");
8774 if (get_create_or_append())
8775 {
8776 /*
8777 Usually lex_start() is called by mysql_parse(), but we need it here
8778 as the present method does not call mysql_parse().
8779 */
8780 lex_start(thd);
8781 mysql_reset_thd_for_next_command(thd);
8782 /* old copy may exist already */
8783 mysql_file_delete(key_file_log_event_data, fname, MYF(0));
8784 if ((fd= mysql_file_create(key_file_log_event_data,
8785 fname, CREATE_MODE,
8786 O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW,
8787 MYF(MY_WME))) < 0)
8788 {
8789 rli->report(ERROR_LEVEL, my_errno,
8790 "Error in %s event: could not create file '%s'",
8791 get_type_str(), fname);
8792 goto err;
8793 }
8794 }
8795 else if ((fd= mysql_file_open(key_file_log_event_data,
8796 fname,
8797 O_WRONLY | O_APPEND | O_BINARY | O_NOFOLLOW,
8798 MYF(MY_WME))) < 0)
8799 {
8800 rli->report(ERROR_LEVEL, my_errno,
8801 "Error in %s event: could not open file '%s'",
8802 get_type_str(), fname);
8803 goto err;
8804 }
8805
8806 DBUG_EXECUTE_IF("remove_slave_load_file_before_write",
8807 {
8808 my_delete_allow_opened(fname, MYF(0));
8809 });
8810
8811 if (mysql_file_write(fd, (uchar*) block, block_len, MYF(MY_WME+MY_NABP)))
8812 {
8813 rli->report(ERROR_LEVEL, my_errno,
8814 "Error in %s event: write to '%s' failed",
8815 get_type_str(), fname);
8816 goto err;
8817 }
8818 error=0;
8819
8820 err:
8821 if (fd >= 0)
8822 mysql_file_close(fd, MYF(0));
8823 DBUG_RETURN(error);
8824 }
8825 #endif
8826
8827
8828 /**************************************************************************
8829 Delete_file_log_event methods
8830 **************************************************************************/
8831
8832 /*
8833 Delete_file_log_event ctor
8834 */
8835
8836 #ifndef MYSQL_CLIENT
Delete_file_log_event(THD * thd_arg,const char * db_arg,bool using_trans)8837 Delete_file_log_event::Delete_file_log_event(THD *thd_arg, const char* db_arg,
8838 bool using_trans)
8839 :Log_event(thd_arg, 0,
8840 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
8841 Log_event::EVENT_STMT_CACHE,
8842 Log_event::EVENT_NORMAL_LOGGING),
8843 file_id(thd_arg->file_id), db(db_arg)
8844 {
8845 }
8846 #endif
8847
8848 /*
8849 Delete_file_log_event ctor
8850 */
8851
Delete_file_log_event(const char * buf,uint len,const Format_description_log_event * description_event)8852 Delete_file_log_event::Delete_file_log_event(const char* buf, uint len,
8853 const Format_description_log_event* description_event)
8854 :Log_event(buf, description_event),file_id(0)
8855 {
8856 uint8 common_header_len= description_event->common_header_len;
8857 uint8 delete_file_header_len= description_event->post_header_len[DELETE_FILE_EVENT-1];
8858 if (len < (uint)(common_header_len + delete_file_header_len))
8859 return;
8860 file_id= uint4korr(buf + common_header_len + DF_FILE_ID_OFFSET);
8861 }
8862
8863
8864 /*
8865 Delete_file_log_event::write()
8866 */
8867
8868 #ifndef MYSQL_CLIENT
write(IO_CACHE * file)8869 bool Delete_file_log_event::write(IO_CACHE* file)
8870 {
8871 uchar buf[DELETE_FILE_HEADER_LEN];
8872 int4store(buf + DF_FILE_ID_OFFSET, file_id);
8873 return (write_header(file, sizeof(buf)) ||
8874 wrapper_my_b_safe_write(file, buf, sizeof(buf)) ||
8875 write_footer(file));
8876 }
8877 #endif
8878
8879
8880 /*
8881 Delete_file_log_event::print()
8882 */
8883
8884 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)8885 void Delete_file_log_event::print(FILE* file,
8886 PRINT_EVENT_INFO* print_event_info)
8887 {
8888 if (print_event_info->short_form)
8889 return;
8890 print_header(&print_event_info->head_cache, print_event_info, FALSE);
8891 my_b_printf(&print_event_info->head_cache,
8892 "\n#Delete_file: file_id=%u\n", file_id);
8893 }
8894 #endif /* MYSQL_CLIENT */
8895
8896 /*
8897 Delete_file_log_event::pack_info()
8898 */
8899
8900 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
pack_info(Protocol * protocol)8901 int Delete_file_log_event::pack_info(Protocol *protocol)
8902 {
8903 char buf[64];
8904 size_t length;
8905 length= my_snprintf(buf, sizeof(buf), ";file_id=%u", (uint) file_id);
8906 protocol->store(buf, length, &my_charset_bin);
8907 return 0;
8908 }
8909 #endif
8910
8911 /*
8912 Delete_file_log_event::do_apply_event()
8913 */
8914
8915 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
do_apply_event(Relay_log_info const * rli)8916 int Delete_file_log_event::do_apply_event(Relay_log_info const *rli)
8917 {
8918 char fname[FN_REFLEN+TEMP_FILE_MAX_LEN];
8919 lex_start(thd);
8920 mysql_reset_thd_for_next_command(thd);
8921 char *ext= slave_load_file_stem(fname, file_id, server_id, ".data");
8922 mysql_file_delete(key_file_log_event_data, fname, MYF(MY_WME));
8923 strmov(ext, ".info");
8924 mysql_file_delete(key_file_log_event_info, fname, MYF(MY_WME));
8925 return 0;
8926 }
8927 #endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
8928
8929
8930 /**************************************************************************
8931 Execute_load_log_event methods
8932 **************************************************************************/
8933
8934 /*
8935 Execute_load_log_event ctor
8936 */
8937
8938 #ifndef MYSQL_CLIENT
Execute_load_log_event(THD * thd_arg,const char * db_arg,bool using_trans)8939 Execute_load_log_event::Execute_load_log_event(THD *thd_arg,
8940 const char* db_arg,
8941 bool using_trans)
8942 :Log_event(thd_arg, 0,
8943 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
8944 Log_event::EVENT_STMT_CACHE,
8945 Log_event::EVENT_NORMAL_LOGGING),
8946 file_id(thd_arg->file_id), db(db_arg)
8947 {
8948 }
8949 #endif
8950
8951
8952 /*
8953 Execute_load_log_event ctor
8954 */
8955
Execute_load_log_event(const char * buf,uint len,const Format_description_log_event * description_event)8956 Execute_load_log_event::Execute_load_log_event(const char* buf, uint len,
8957 const Format_description_log_event* description_event)
8958 :Log_event(buf, description_event), file_id(0)
8959 {
8960 uint8 common_header_len= description_event->common_header_len;
8961 uint8 exec_load_header_len= description_event->post_header_len[EXEC_LOAD_EVENT-1];
8962 if (len < (uint)(common_header_len+exec_load_header_len))
8963 return;
8964 file_id= uint4korr(buf + common_header_len + EL_FILE_ID_OFFSET);
8965 }
8966
8967
8968 /*
8969 Execute_load_log_event::write()
8970 */
8971
8972 #ifndef MYSQL_CLIENT
write(IO_CACHE * file)8973 bool Execute_load_log_event::write(IO_CACHE* file)
8974 {
8975 uchar buf[EXEC_LOAD_HEADER_LEN];
8976 int4store(buf + EL_FILE_ID_OFFSET, file_id);
8977 return (write_header(file, sizeof(buf)) ||
8978 wrapper_my_b_safe_write(file, buf, sizeof(buf)) ||
8979 write_footer(file));
8980 }
8981 #endif
8982
8983
8984 /*
8985 Execute_load_log_event::print()
8986 */
8987
8988 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)8989 void Execute_load_log_event::print(FILE* file,
8990 PRINT_EVENT_INFO* print_event_info)
8991 {
8992 if (print_event_info->short_form)
8993 return;
8994 print_header(&print_event_info->head_cache, print_event_info, FALSE);
8995 my_b_printf(&print_event_info->head_cache, "\n#Exec_load: file_id=%d\n",
8996 file_id);
8997 }
8998 #endif
8999
9000 /*
9001 Execute_load_log_event::pack_info()
9002 */
9003
9004 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
pack_info(Protocol * protocol)9005 int Execute_load_log_event::pack_info(Protocol *protocol)
9006 {
9007 char buf[64];
9008 size_t length;
9009 length= my_snprintf(buf, sizeof(buf), ";file_id=%u", (uint) file_id);
9010 protocol->store(buf, length, &my_charset_bin);
9011 return 0;
9012 }
9013
9014
9015 /*
9016 Execute_load_log_event::do_apply_event()
9017 */
9018
do_apply_event(Relay_log_info const * rli)9019 int Execute_load_log_event::do_apply_event(Relay_log_info const *rli)
9020 {
9021 char fname[FN_REFLEN+TEMP_FILE_MAX_LEN];
9022 char *ext;
9023 int fd;
9024 int error= 1;
9025 IO_CACHE file;
9026 Load_log_event *lev= 0;
9027
9028 lex_start(thd);
9029 mysql_reset_thd_for_next_command(thd);
9030 ext= slave_load_file_stem(fname, file_id, server_id, ".info");
9031 /**
9032 To simulate file open failure, convert the file name to a
9033 directory by appending a "/" to the file name. File open
9034 will fail with an error reporting it is not a directory.
9035 */
9036 DBUG_EXECUTE_IF("simulate_file_open_error_exec_event",
9037 {
9038 strcat(fname,"/");
9039 });
9040 if ((fd= mysql_file_open(key_file_log_event_info,
9041 fname, O_RDONLY | O_BINARY | O_NOFOLLOW,
9042 MYF(MY_WME))) < 0 ||
9043 init_io_cache(&file, fd, IO_SIZE, READ_CACHE, (my_off_t)0, 0,
9044 MYF(MY_WME|MY_NABP)))
9045 {
9046 rli->report(ERROR_LEVEL, thd->get_stmt_da()->sql_errno(),
9047 "Error in Exec_load event: could not open file '%s'",
9048 fname);
9049 goto err;
9050 }
9051 if (!(lev= (Load_log_event*)
9052 Log_event::read_log_event(&file,
9053 (mysql_mutex_t*) 0,
9054 rli->get_rli_description_event(),
9055 opt_slave_sql_verify_checksum)) ||
9056 lev->get_type_code() != NEW_LOAD_EVENT)
9057 {
9058 rli->report(ERROR_LEVEL, 0, "Error in Exec_load event: "
9059 "file '%s' appears corrupted", fname);
9060 goto err;
9061 }
9062 lev->thd = thd;
9063 /*
9064 lev->do_apply_event should use rli only for errors i.e. should
9065 not advance rli's position.
9066
9067 lev->do_apply_event is the place where the table is loaded (it
9068 calls mysql_load()).
9069 */
9070 const_cast<Relay_log_info*>(rli)->set_future_group_master_log_pos(log_pos);
9071 if (lev->do_apply_event(0,rli,1))
9072 {
9073 /*
9074 We want to indicate the name of the file that could not be loaded
9075 (SQL_LOADxxx).
9076 But as we are here we are sure the error is in rli->last_slave_error and
9077 rli->last_slave_errno (example of error: duplicate entry for key), so we
9078 don't want to overwrite it with the filename.
9079 What we want instead is add the filename to the current error message.
9080 */
9081 char *tmp= my_strdup(rli->last_error().message, MYF(MY_WME));
9082 if (tmp)
9083 {
9084 rli->report(ERROR_LEVEL, rli->last_error().number,
9085 "%s. Failed executing load from '%s'", tmp, fname);
9086 my_free(tmp);
9087 }
9088 goto err;
9089 }
9090 /*
9091 We have an open file descriptor to the .info file; we need to close it
9092 or Windows will refuse to delete the file in mysql_file_delete().
9093 */
9094 if (fd >= 0)
9095 {
9096 mysql_file_close(fd, MYF(0));
9097 end_io_cache(&file);
9098 fd= -1;
9099 }
9100 mysql_file_delete(key_file_log_event_info, fname, MYF(MY_WME));
9101 memcpy(ext, ".data", 6);
9102 mysql_file_delete(key_file_log_event_data, fname, MYF(MY_WME));
9103 error = 0;
9104
9105 err:
9106 delete lev;
9107 if (fd >= 0)
9108 {
9109 mysql_file_close(fd, MYF(0));
9110 end_io_cache(&file);
9111 }
9112 return error;
9113 }
9114
9115 #endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
9116
9117
9118 /**************************************************************************
9119 Begin_load_query_log_event methods
9120 **************************************************************************/
9121
9122 #ifndef MYSQL_CLIENT
9123 Begin_load_query_log_event::
Begin_load_query_log_event(THD * thd_arg,const char * db_arg,uchar * block_arg,uint block_len_arg,bool using_trans)9124 Begin_load_query_log_event(THD* thd_arg, const char* db_arg, uchar* block_arg,
9125 uint block_len_arg, bool using_trans)
9126 :Append_block_log_event(thd_arg, db_arg, block_arg, block_len_arg,
9127 using_trans)
9128 {
9129 file_id= thd_arg->file_id= mysql_bin_log.next_file_id();
9130 }
9131 #endif
9132
9133
9134 Begin_load_query_log_event::
Begin_load_query_log_event(const char * buf,uint len,const Format_description_log_event * desc_event)9135 Begin_load_query_log_event(const char* buf, uint len,
9136 const Format_description_log_event* desc_event)
9137 :Append_block_log_event(buf, len, desc_event)
9138 {
9139 }
9140
9141
9142 #if defined( HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
get_create_or_append() const9143 int Begin_load_query_log_event::get_create_or_append() const
9144 {
9145 return 1; /* create the file */
9146 }
9147 #endif /* defined( HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
9148
9149
9150 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
9151 Log_event::enum_skip_reason
do_shall_skip(Relay_log_info * rli)9152 Begin_load_query_log_event::do_shall_skip(Relay_log_info *rli)
9153 {
9154 /*
9155 If the slave skip counter is 1, then we should not start executing
9156 on the next event.
9157 */
9158 return continue_group(rli);
9159 }
9160 #endif
9161
9162
9163 /**************************************************************************
9164 Execute_load_query_log_event methods
9165 **************************************************************************/
9166
9167
9168 #ifndef MYSQL_CLIENT
9169 Execute_load_query_log_event::
Execute_load_query_log_event(THD * thd_arg,const char * query_arg,ulong query_length_arg,uint fn_pos_start_arg,uint fn_pos_end_arg,enum_load_dup_handling dup_handling_arg,bool using_trans,bool immediate,bool suppress_use,int errcode)9170 Execute_load_query_log_event(THD *thd_arg, const char* query_arg,
9171 ulong query_length_arg, uint fn_pos_start_arg,
9172 uint fn_pos_end_arg,
9173 enum_load_dup_handling dup_handling_arg,
9174 bool using_trans, bool immediate, bool suppress_use,
9175 int errcode):
9176 Query_log_event(thd_arg, query_arg, query_length_arg, using_trans, immediate,
9177 suppress_use, errcode),
9178 file_id(thd_arg->file_id), fn_pos_start(fn_pos_start_arg),
9179 fn_pos_end(fn_pos_end_arg), dup_handling(dup_handling_arg)
9180 {
9181 }
9182 #endif /* !MYSQL_CLIENT */
9183
9184
9185 Execute_load_query_log_event::
Execute_load_query_log_event(const char * buf,uint event_len,const Format_description_log_event * desc_event)9186 Execute_load_query_log_event(const char* buf, uint event_len,
9187 const Format_description_log_event* desc_event):
9188 Query_log_event(buf, event_len, desc_event, EXECUTE_LOAD_QUERY_EVENT),
9189 file_id(0), fn_pos_start(0), fn_pos_end(0)
9190 {
9191 if (!Query_log_event::is_valid())
9192 return;
9193
9194 buf+= desc_event->common_header_len;
9195
9196 fn_pos_start= uint4korr(buf + ELQ_FN_POS_START_OFFSET);
9197 fn_pos_end= uint4korr(buf + ELQ_FN_POS_END_OFFSET);
9198 dup_handling= (enum_load_dup_handling)(*(buf + ELQ_DUP_HANDLING_OFFSET));
9199
9200 if (fn_pos_start > q_len || fn_pos_end > q_len ||
9201 dup_handling > LOAD_DUP_REPLACE)
9202 return;
9203
9204 file_id= uint4korr(buf + ELQ_FILE_ID_OFFSET);
9205 }
9206
9207
get_post_header_size_for_derived()9208 ulong Execute_load_query_log_event::get_post_header_size_for_derived()
9209 {
9210 return EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN;
9211 }
9212
9213
9214 #ifndef MYSQL_CLIENT
9215 bool
write_post_header_for_derived(IO_CACHE * file)9216 Execute_load_query_log_event::write_post_header_for_derived(IO_CACHE* file)
9217 {
9218 uchar buf[EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN];
9219 int4store(buf, file_id);
9220 int4store(buf + 4, fn_pos_start);
9221 int4store(buf + 4 + 4, fn_pos_end);
9222 *(buf + 4 + 4 + 4)= (uchar) dup_handling;
9223 return wrapper_my_b_safe_write(file, buf, EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN);
9224 }
9225 #endif
9226
9227
9228 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)9229 void Execute_load_query_log_event::print(FILE* file,
9230 PRINT_EVENT_INFO* print_event_info)
9231 {
9232 print(file, print_event_info, 0);
9233 }
9234
9235 /**
9236 Prints the query as LOAD DATA LOCAL and with rewritten filename.
9237 */
print(FILE * file,PRINT_EVENT_INFO * print_event_info,const char * local_fname)9238 void Execute_load_query_log_event::print(FILE* file,
9239 PRINT_EVENT_INFO* print_event_info,
9240 const char *local_fname)
9241 {
9242 IO_CACHE *const head= &print_event_info->head_cache;
9243
9244 print_query_header(head, print_event_info);
9245 /**
9246 reduce the size of io cache so that the write function is called
9247 for every call to my_b_printf().
9248 */
9249 DBUG_EXECUTE_IF ("simulate_execute_event_write_error",
9250 {head->write_pos= head->write_end;
9251 DBUG_SET("+d,simulate_file_write_error");});
9252
9253 if (local_fname)
9254 {
9255 my_b_write(head, (uchar*) query, fn_pos_start);
9256 my_b_printf(head, " LOCAL INFILE ");
9257 pretty_print_str(head, local_fname, strlen(local_fname));
9258
9259 if (dup_handling == LOAD_DUP_REPLACE)
9260 my_b_printf(head, " REPLACE");
9261 my_b_printf(head, " INTO");
9262 my_b_write(head, (uchar*) query + fn_pos_end, q_len-fn_pos_end);
9263 my_b_printf(head, "\n%s\n", print_event_info->delimiter);
9264 }
9265 else
9266 {
9267 my_b_write(head, (uchar*) query, q_len);
9268 my_b_printf(head, "\n%s\n", print_event_info->delimiter);
9269 }
9270
9271 if (!print_event_info->short_form)
9272 my_b_printf(head, "# file_id: %d \n", file_id);
9273 }
9274 #endif
9275
9276
9277 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
pack_info(Protocol * protocol)9278 int Execute_load_query_log_event::pack_info(Protocol *protocol)
9279 {
9280 char *buf, *pos;
9281 if (!(buf= (char*) my_malloc(9 + (db_len * 2) + 2 + q_len + 10 + 21,
9282 MYF(MY_WME))))
9283 return 1;
9284 pos= buf;
9285 if (db && db_len)
9286 {
9287 /*
9288 Statically allocates room to store '\0' and an identifier
9289 that may have NAME_LEN * 2 due to quoting and there are
9290 two quoting characters that wrap them.
9291 */
9292 char quoted_db[1 + NAME_LEN * 2 + 2];// quoted length of the identifier
9293 size_t size= 0;
9294 size= my_strmov_quoted_identifier(this->thd, quoted_db, db, 0);
9295 pos= strmov(buf, "use ");
9296 memcpy(pos, quoted_db, size);
9297 pos= strmov(pos + size, "; ");
9298 }
9299 if (query && q_len)
9300 {
9301 memcpy(pos, query, q_len);
9302 pos+= q_len;
9303 }
9304 pos= strmov(pos, " ;file_id=");
9305 pos= int10_to_str((long) file_id, pos, 10);
9306 protocol->store(buf, pos-buf, &my_charset_bin);
9307 my_free(buf);
9308 return 0;
9309 }
9310
9311
9312 int
do_apply_event(Relay_log_info const * rli)9313 Execute_load_query_log_event::do_apply_event(Relay_log_info const *rli)
9314 {
9315 char *p;
9316 char *buf;
9317 char *fname;
9318 char *fname_end;
9319 int error;
9320
9321 buf= (char*) my_malloc(q_len + 1 - (fn_pos_end - fn_pos_start) +
9322 (FN_REFLEN + TEMP_FILE_MAX_LEN) + 10 + 8 + 5, MYF(MY_WME));
9323
9324 DBUG_EXECUTE_IF("LOAD_DATA_INFILE_has_fatal_error", my_free(buf); buf= NULL;);
9325
9326 /* Replace filename and LOCAL keyword in query before executing it */
9327 if (buf == NULL)
9328 {
9329 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
9330 ER(ER_SLAVE_FATAL_ERROR), "Not enough memory");
9331 return 1;
9332 }
9333
9334 p= buf;
9335 memcpy(p, query, fn_pos_start);
9336 p+= fn_pos_start;
9337 fname= (p= strmake(p, STRING_WITH_LEN(" INFILE \'")));
9338 p= slave_load_file_stem(p, file_id, server_id, ".data");
9339 fname_end= p= strend(p); // Safer than p=p+5
9340 *(p++)='\'';
9341 switch (dup_handling) {
9342 case LOAD_DUP_IGNORE:
9343 p= strmake(p, STRING_WITH_LEN(" IGNORE"));
9344 break;
9345 case LOAD_DUP_REPLACE:
9346 p= strmake(p, STRING_WITH_LEN(" REPLACE"));
9347 break;
9348 default:
9349 /* Ordinary load data */
9350 break;
9351 }
9352 p= strmake(p, STRING_WITH_LEN(" INTO "));
9353 p= strmake(p, query+fn_pos_end, q_len-fn_pos_end);
9354
9355 error= Query_log_event::do_apply_event(rli, buf, p-buf);
9356
9357 /* Forging file name for deletion in same buffer */
9358 *fname_end= 0;
9359
9360 /*
9361 If there was an error the slave is going to stop, leave the
9362 file so that we can re-execute this event at START SLAVE.
9363 */
9364 if (!error)
9365 mysql_file_delete(key_file_log_event_data, fname, MYF(MY_WME));
9366
9367 my_free(buf);
9368 return error;
9369 }
9370 #endif
9371
9372
9373 /**************************************************************************
9374 sql_ex_info methods
9375 **************************************************************************/
9376
9377 /*
9378 sql_ex_info::write_data()
9379 */
9380
write_data(IO_CACHE * file)9381 bool sql_ex_info::write_data(IO_CACHE* file)
9382 {
9383 if (new_format())
9384 {
9385 return (write_str_at_most_255_bytes(file, field_term, (uint) field_term_len) ||
9386 write_str_at_most_255_bytes(file, enclosed, (uint) enclosed_len) ||
9387 write_str_at_most_255_bytes(file, line_term, (uint) line_term_len) ||
9388 write_str_at_most_255_bytes(file, line_start, (uint) line_start_len) ||
9389 write_str_at_most_255_bytes(file, escaped, (uint) escaped_len) ||
9390 my_b_safe_write(file,(uchar*) &opt_flags,1));
9391 }
9392 else
9393 {
9394 /**
9395 @todo This is sensitive to field padding. We should write a
9396 char[7], not an old_sql_ex. /sven
9397 */
9398 old_sql_ex old_ex;
9399 old_ex.field_term= *field_term;
9400 old_ex.enclosed= *enclosed;
9401 old_ex.line_term= *line_term;
9402 old_ex.line_start= *line_start;
9403 old_ex.escaped= *escaped;
9404 old_ex.opt_flags= opt_flags;
9405 old_ex.empty_flags=empty_flags;
9406 return my_b_safe_write(file, (uchar*) &old_ex, sizeof(old_ex)) != 0;
9407 }
9408 }
9409
9410
9411 /*
9412 sql_ex_info::init()
9413 */
9414
init(const char * buf,const char * buf_end,bool use_new_format)9415 const char *sql_ex_info::init(const char *buf, const char *buf_end,
9416 bool use_new_format)
9417 {
9418 cached_new_format = use_new_format;
9419 if (use_new_format)
9420 {
9421 empty_flags=0;
9422 /*
9423 The code below assumes that buf will not disappear from
9424 under our feet during the lifetime of the event. This assumption
9425 holds true in the slave thread if the log is in new format, but is not
9426 the case when we have old format because we will be reusing net buffer
9427 to read the actual file before we write out the Create_file event.
9428 */
9429 if (read_str_at_most_255_bytes(&buf, buf_end, &field_term, &field_term_len) ||
9430 read_str_at_most_255_bytes(&buf, buf_end, &enclosed, &enclosed_len) ||
9431 read_str_at_most_255_bytes(&buf, buf_end, &line_term, &line_term_len) ||
9432 read_str_at_most_255_bytes(&buf, buf_end, &line_start, &line_start_len) ||
9433 read_str_at_most_255_bytes(&buf, buf_end, &escaped, &escaped_len))
9434 return 0;
9435 opt_flags = *buf++;
9436 }
9437 else
9438 {
9439 field_term_len= enclosed_len= line_term_len= line_start_len= escaped_len=1;
9440 field_term = buf++; // Use first byte in string
9441 enclosed= buf++;
9442 line_term= buf++;
9443 line_start= buf++;
9444 escaped= buf++;
9445 opt_flags = *buf++;
9446 empty_flags= *buf++;
9447 if (empty_flags & FIELD_TERM_EMPTY)
9448 field_term_len=0;
9449 if (empty_flags & ENCLOSED_EMPTY)
9450 enclosed_len=0;
9451 if (empty_flags & LINE_TERM_EMPTY)
9452 line_term_len=0;
9453 if (empty_flags & LINE_START_EMPTY)
9454 line_start_len=0;
9455 if (empty_flags & ESCAPED_EMPTY)
9456 escaped_len=0;
9457 }
9458 return buf;
9459 }
9460
9461 #ifndef DBUG_OFF
9462 #ifndef MYSQL_CLIENT
9463 static uchar dbug_extra_row_data_val= 0;
9464
9465 /**
9466 set_extra_data
9467
9468 Called during self-test to generate various
9469 self-consistent binlog row event extra
9470 thread data structures which can be checked
9471 when reading the binlog.
9472
9473 @param arr Buffer to use
9474 */
set_extra_data(uchar * arr)9475 const uchar* set_extra_data(uchar* arr)
9476 {
9477 uchar val= (dbug_extra_row_data_val++) %
9478 (EXTRA_ROW_INFO_MAX_PAYLOAD + 1); /* 0 .. MAX_PAYLOAD + 1 */
9479 arr[EXTRA_ROW_INFO_LEN_OFFSET]= val + EXTRA_ROW_INFO_HDR_BYTES;
9480 arr[EXTRA_ROW_INFO_FORMAT_OFFSET]= val;
9481 for (uchar i=0; i<val; i++)
9482 arr[EXTRA_ROW_INFO_HDR_BYTES+i]= val;
9483
9484 return arr;
9485 }
9486
9487 #endif // #ifndef MYSQL_CLIENT
9488
9489 /**
9490 check_extra_data
9491
9492 Called during self-test to check that
9493 binlog row event extra data is self-
9494 consistent as defined by the set_extra_data
9495 function above.
9496
9497 Will assert(false) if not.
9498
9499 @param extra_row_data
9500 */
check_extra_data(uchar * extra_row_data)9501 void check_extra_data(uchar* extra_row_data)
9502 {
9503 assert(extra_row_data);
9504 uint16 len= extra_row_data[EXTRA_ROW_INFO_LEN_OFFSET];
9505 uint8 val= len - EXTRA_ROW_INFO_HDR_BYTES;
9506 assert(extra_row_data[EXTRA_ROW_INFO_FORMAT_OFFSET] == val);
9507 for (uint16 i= 0; i < val; i++)
9508 {
9509 assert(extra_row_data[EXTRA_ROW_INFO_HDR_BYTES + i] == val);
9510 }
9511 }
9512
9513 #endif // #ifndef DBUG_OFF
9514
9515 /**************************************************************************
9516 Rows_log_event member functions
9517 **************************************************************************/
9518
9519 #ifndef MYSQL_CLIENT
Rows_log_event(THD * thd_arg,TABLE * tbl_arg,const Table_id & tid,MY_BITMAP const * cols,bool using_trans,Log_event_type event_type,const uchar * extra_row_info)9520 Rows_log_event::Rows_log_event(THD *thd_arg, TABLE *tbl_arg, const Table_id& tid,
9521 MY_BITMAP const *cols, bool using_trans,
9522 Log_event_type event_type,
9523 const uchar* extra_row_info)
9524 : Log_event(thd_arg, 0,
9525 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
9526 Log_event::EVENT_STMT_CACHE,
9527 Log_event::EVENT_NORMAL_LOGGING),
9528 m_row_count(0),
9529 m_table(tbl_arg),
9530 m_table_id(tid),
9531 m_width(tbl_arg ? tbl_arg->s->fields : 1),
9532 m_rows_buf(0), m_rows_cur(0), m_rows_end(0), m_flags(0),
9533 m_type(event_type), m_extra_row_data(0)
9534 #ifdef HAVE_REPLICATION
9535 , m_curr_row(NULL), m_curr_row_end(NULL), m_key(NULL), m_key_info(NULL),
9536 m_distinct_keys(Key_compare(&m_key_info)), m_distinct_key_spare_buf(NULL)
9537 #endif
9538 {
9539 DBUG_ASSERT(tbl_arg && tbl_arg->s && tid.is_valid());
9540
9541 if (thd_arg->variables.option_bits & OPTION_NO_FOREIGN_KEY_CHECKS)
9542 set_flags(NO_FOREIGN_KEY_CHECKS_F);
9543 if (thd_arg->variables.option_bits & OPTION_RELAXED_UNIQUE_CHECKS)
9544 set_flags(RELAXED_UNIQUE_CHECKS_F);
9545 #ifndef DBUG_OFF
9546 uchar extra_data[255];
9547 DBUG_EXECUTE_IF("extra_row_data_set",
9548 /* Set extra row data to a known value */
9549 extra_row_info = set_extra_data(extra_data););
9550 #endif
9551 if (extra_row_info)
9552 {
9553 /* Copy Extra data from thd into new event */
9554 uint8 extra_data_len= extra_row_info[EXTRA_ROW_INFO_LEN_OFFSET];
9555 assert(extra_data_len >= EXTRA_ROW_INFO_HDR_BYTES);
9556
9557 m_extra_row_data= (uchar*) my_malloc(extra_data_len, MYF(MY_WME));
9558
9559 if (likely(m_extra_row_data != NULL))
9560 {
9561 memcpy(m_extra_row_data, extra_row_info,
9562 extra_data_len);
9563 }
9564 }
9565
9566 /* if bitmap_init fails, caught in is_valid() */
9567 if (likely(!bitmap_init(&m_cols,
9568 m_width <= sizeof(m_bitbuf)*8 ? m_bitbuf : NULL,
9569 m_width,
9570 false)))
9571 {
9572 /* Cols can be zero if this is a dummy binrows event */
9573 if (likely(cols != NULL))
9574 {
9575 memcpy(m_cols.bitmap, cols->bitmap, no_bytes_in_map(cols));
9576 create_last_word_mask(&m_cols);
9577 }
9578 }
9579 else
9580 {
9581 // Needed because bitmap_init() does not set it to null on failure
9582 m_cols.bitmap= 0;
9583 }
9584 }
9585 #endif
9586
Rows_log_event(const char * buf,uint event_len,const Format_description_log_event * description_event)9587 Rows_log_event::Rows_log_event(const char *buf, uint event_len,
9588 const Format_description_log_event
9589 *description_event)
9590 : Log_event(buf, description_event),
9591 m_row_count(0),
9592 #ifndef MYSQL_CLIENT
9593 m_table(NULL),
9594 #endif
9595 m_table_id(0), m_rows_buf(0), m_rows_cur(0), m_rows_end(0),
9596 m_extra_row_data(0)
9597 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
9598 , m_curr_row(NULL), m_curr_row_end(NULL), m_key(NULL), m_key_info(NULL),
9599 m_distinct_keys(Key_compare(&m_key_info)), m_distinct_key_spare_buf(NULL)
9600 #endif
9601 {
9602 DBUG_ENTER("Rows_log_event::Rows_log_event(const char*,...)");
9603 uint8 const common_header_len= description_event->common_header_len;
9604 Log_event_type event_type= (Log_event_type) buf[EVENT_TYPE_OFFSET];
9605 m_type= event_type;
9606
9607 uint8 const post_header_len= description_event->post_header_len[event_type-1];
9608
9609 DBUG_PRINT("enter",("event_len: %u common_header_len: %d "
9610 "post_header_len: %d",
9611 event_len, common_header_len,
9612 post_header_len));
9613
9614 const char *post_start= buf + common_header_len;
9615 post_start+= RW_MAPID_OFFSET;
9616 if (post_header_len == 6)
9617 {
9618 /* Master is of an intermediate source tree before 5.1.4. Id is 4 bytes */
9619 m_table_id= uint4korr(post_start);
9620 post_start+= 4;
9621 }
9622 else
9623 {
9624 m_table_id= uint6korr(post_start);
9625 post_start+= RW_FLAGS_OFFSET;
9626 }
9627
9628 m_flags= uint2korr(post_start);
9629 post_start+= 2;
9630
9631 uint16 var_header_len= 0;
9632 if (post_header_len == ROWS_HEADER_LEN_V2)
9633 {
9634 /*
9635 Have variable length header, check length,
9636 which includes length bytes
9637 */
9638 var_header_len= uint2korr(post_start);
9639 /* Check length and also avoid out of buffer read */
9640 if (var_header_len < 2 ||
9641 event_len < static_cast<unsigned int>(var_header_len +
9642 (post_start - buf)))
9643 {
9644 m_cols.bitmap= NULL;
9645 DBUG_VOID_RETURN;
9646 }
9647
9648 var_header_len-= 2;
9649
9650 /* Iterate over var-len header, extracting 'chunks' */
9651 const char* start= post_start + 2;
9652 const char* end= start + var_header_len;
9653 for (const char* pos= start; pos < end;)
9654 {
9655 switch(*pos++)
9656 {
9657 case RW_V_EXTRAINFO_TAG:
9658 {
9659 /* Have an 'extra info' section, read it in */
9660 assert((end - pos) >= EXTRA_ROW_INFO_HDR_BYTES);
9661 uint8 infoLen= pos[EXTRA_ROW_INFO_LEN_OFFSET];
9662 assert((end - pos) >= infoLen);
9663 /* Just store/use the first tag of this type, skip others */
9664 if (likely(!m_extra_row_data))
9665 {
9666 m_extra_row_data= (uchar*) my_malloc(infoLen,
9667 MYF(MY_WME));
9668 if (likely(m_extra_row_data != NULL))
9669 {
9670 memcpy(m_extra_row_data, pos, infoLen);
9671 }
9672 DBUG_EXECUTE_IF("extra_row_data_check",
9673 /* Check extra data has expected value */
9674 check_extra_data(m_extra_row_data););
9675 }
9676 pos+= infoLen;
9677 break;
9678 }
9679 default:
9680 /* Unknown code, we will not understand anything further here */
9681 pos= end; /* Break loop */
9682 }
9683 }
9684 }
9685
9686 uchar const *const var_start=
9687 (const uchar *)buf + common_header_len + post_header_len + var_header_len;
9688 uchar const *const ptr_width= var_start;
9689 uchar *ptr_after_width= (uchar*) ptr_width;
9690 DBUG_PRINT("debug", ("Reading from %p", ptr_after_width));
9691 m_width = net_field_length(&ptr_after_width);
9692 DBUG_PRINT("debug", ("m_width=%lu", m_width));
9693 /* Avoid reading out of buffer */
9694 if (static_cast<unsigned int>((ptr_after_width +
9695 (m_width + 7) / 8) -
9696 (uchar*)buf) > event_len)
9697 {
9698 m_cols.bitmap= NULL;
9699 DBUG_VOID_RETURN;
9700 }
9701
9702 /* if bitmap_init fails, catched in is_valid() */
9703 if (likely(!bitmap_init(&m_cols,
9704 m_width <= sizeof(m_bitbuf)*8 ? m_bitbuf : NULL,
9705 m_width,
9706 false)))
9707 {
9708 DBUG_PRINT("debug", ("Reading from %p", ptr_after_width));
9709 memcpy(m_cols.bitmap, ptr_after_width, (m_width + 7) / 8);
9710 create_last_word_mask(&m_cols);
9711 ptr_after_width+= (m_width + 7) / 8;
9712 DBUG_DUMP("m_cols", (uchar*) m_cols.bitmap, no_bytes_in_map(&m_cols));
9713 }
9714 else
9715 {
9716 // Needed because bitmap_init() does not set it to null on failure
9717 m_cols.bitmap= NULL;
9718 DBUG_VOID_RETURN;
9719 }
9720
9721 m_cols_ai.bitmap= m_cols.bitmap; /* See explanation in is_valid() */
9722
9723 if ((event_type == UPDATE_ROWS_EVENT) ||
9724 (event_type == UPDATE_ROWS_EVENT_V1))
9725 {
9726 DBUG_PRINT("debug", ("Reading from %p", ptr_after_width));
9727
9728 /* if bitmap_init fails, caught in is_valid() */
9729 if (likely(!bitmap_init(&m_cols_ai,
9730 m_width <= sizeof(m_bitbuf_ai)*8 ? m_bitbuf_ai : NULL,
9731 m_width,
9732 false)))
9733 {
9734 DBUG_PRINT("debug", ("Reading from %p", ptr_after_width));
9735 memcpy(m_cols_ai.bitmap, ptr_after_width, (m_width + 7) / 8);
9736 create_last_word_mask(&m_cols_ai);
9737 ptr_after_width+= (m_width + 7) / 8;
9738 DBUG_DUMP("m_cols_ai", (uchar*) m_cols_ai.bitmap,
9739 no_bytes_in_map(&m_cols_ai));
9740 }
9741 else
9742 {
9743 // Needed because bitmap_init() does not set it to null on failure
9744 m_cols_ai.bitmap= 0;
9745 DBUG_VOID_RETURN;
9746 }
9747 }
9748
9749 const uchar* const ptr_rows_data= (const uchar*) ptr_after_width;
9750
9751 size_t const read_size= ptr_rows_data - (const unsigned char *) buf;
9752 if (read_size > event_len)
9753 {
9754 DBUG_VOID_RETURN;
9755 }
9756
9757 size_t const data_size= event_len - read_size;
9758 DBUG_PRINT("info",("m_table_id: %llu m_flags: %d m_width: %lu data_size: %lu",
9759 m_table_id.id(), m_flags, m_width, (ulong) data_size));
9760
9761 m_rows_buf= (uchar*) my_malloc(data_size, MYF(MY_WME));
9762 if (likely((bool)m_rows_buf))
9763 {
9764 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
9765 m_curr_row= m_rows_buf;
9766 #endif
9767 m_rows_end= m_rows_buf + data_size;
9768 m_rows_cur= m_rows_end;
9769 memcpy(m_rows_buf, ptr_rows_data, data_size);
9770 }
9771 else
9772 m_cols.bitmap= 0; // to not free it
9773
9774 DBUG_VOID_RETURN;
9775 }
9776
~Rows_log_event()9777 Rows_log_event::~Rows_log_event()
9778 {
9779 if (m_cols.bitmap == m_bitbuf) // no my_malloc happened
9780 m_cols.bitmap= 0; // so no my_free in bitmap_free
9781 bitmap_free(&m_cols); // To pair with bitmap_init().
9782 my_free(m_rows_buf);
9783 my_free(m_extra_row_data);
9784 }
9785
get_data_size()9786 int Rows_log_event::get_data_size()
9787 {
9788 int const general_type_code= get_general_type_code();
9789
9790 uchar buf[sizeof(m_width) + 1];
9791 uchar *end= net_store_length(buf, m_width);
9792
9793 DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master",
9794 return 6 + no_bytes_in_map(&m_cols) + (end - buf) +
9795 (general_type_code == UPDATE_ROWS_EVENT ? no_bytes_in_map(&m_cols_ai) : 0) +
9796 (m_rows_cur - m_rows_buf););
9797
9798 int data_size= 0;
9799 bool is_v2_event= get_type_code() > DELETE_ROWS_EVENT_V1;
9800 if (is_v2_event)
9801 {
9802 data_size= ROWS_HEADER_LEN_V2 +
9803 (m_extra_row_data ?
9804 RW_V_TAG_LEN + m_extra_row_data[EXTRA_ROW_INFO_LEN_OFFSET]:
9805 0);
9806 }
9807 else
9808 {
9809 data_size= ROWS_HEADER_LEN_V1;
9810 }
9811 data_size+= no_bytes_in_map(&m_cols);
9812 data_size+= (uint) (end - buf);
9813
9814 if (general_type_code == UPDATE_ROWS_EVENT)
9815 data_size+= no_bytes_in_map(&m_cols_ai);
9816
9817 data_size+= (uint) (m_rows_cur - m_rows_buf);
9818 return data_size;
9819 }
9820
9821
9822 #ifndef MYSQL_CLIENT
do_add_row_data(uchar * row_data,size_t length)9823 int Rows_log_event::do_add_row_data(uchar *row_data, size_t length)
9824 {
9825 /*
9826 When the table has a primary key, we would probably want, by default, to
9827 log only the primary key value instead of the entire "before image". This
9828 would save binlog space. TODO
9829 */
9830 DBUG_ENTER("Rows_log_event::do_add_row_data");
9831 DBUG_PRINT("enter", ("row_data: 0x%lx length: %lu", (ulong) row_data,
9832 (ulong) length));
9833
9834 /*
9835 If length is zero, there is nothing to write, so we just
9836 return. Note that this is not an optimization, since calling
9837 realloc() with size 0 means free().
9838 */
9839 if (length == 0)
9840 {
9841 m_row_count++;
9842 DBUG_RETURN(0);
9843 }
9844
9845 /*
9846 Don't print debug messages when running valgrind since they can
9847 trigger false warnings.
9848 */
9849 #ifndef HAVE_purify
9850 DBUG_DUMP("row_data", row_data, min<size_t>(length, 32));
9851 #endif
9852
9853 DBUG_ASSERT(m_rows_buf <= m_rows_cur);
9854 DBUG_ASSERT(!m_rows_buf || (m_rows_end && m_rows_buf < m_rows_end));
9855 DBUG_ASSERT(m_rows_cur <= m_rows_end);
9856
9857 /* The cast will always work since m_rows_cur <= m_rows_end */
9858 if (static_cast<size_t>(m_rows_end - m_rows_cur) <= length)
9859 {
9860 size_t const block_size= 1024;
9861 ulong cur_size= m_rows_cur - m_rows_buf;
9862 DBUG_EXECUTE_IF("simulate_too_big_row_case1",
9863 cur_size= UINT_MAX32 - (block_size * 10);
9864 length= UINT_MAX32 - (block_size * 10););
9865 DBUG_EXECUTE_IF("simulate_too_big_row_case2",
9866 cur_size= UINT_MAX32 - (block_size * 10);
9867 length= block_size * 10;);
9868 DBUG_EXECUTE_IF("simulate_too_big_row_case3",
9869 cur_size= block_size * 10;
9870 length= UINT_MAX32 - (block_size * 10););
9871 DBUG_EXECUTE_IF("simulate_too_big_row_case4",
9872 cur_size= UINT_MAX32 - (block_size * 10);
9873 length= (block_size * 10) - block_size + 1;);
9874 ulong remaining_space= UINT_MAX32 - cur_size;
9875 /* Check that the new data fits within remaining space and we can add
9876 block_size without wrapping.
9877 */
9878 if (length > remaining_space ||
9879 ((length + block_size) > remaining_space))
9880 {
9881 sql_print_error("The row data is greater than 4GB, which is too big to "
9882 "write to the binary log.");
9883 DBUG_RETURN(ER_BINLOG_ROW_LOGGING_FAILED);
9884 }
9885 ulong const new_alloc=
9886 block_size * ((cur_size + length + block_size - 1) / block_size);
9887
9888 uchar* const new_buf=
9889 (uchar*)my_realloc((uchar*)m_rows_buf, (uint) new_alloc,
9890 MYF(MY_ALLOW_ZERO_PTR|MY_WME));
9891 if (unlikely(!new_buf))
9892 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
9893
9894 /* If the memory moved, we need to move the pointers */
9895 if (new_buf != m_rows_buf)
9896 {
9897 m_rows_buf= new_buf;
9898 m_rows_cur= m_rows_buf + cur_size;
9899 }
9900
9901 /*
9902 The end pointer should always be changed to point to the end of
9903 the allocated memory.
9904 */
9905 m_rows_end= m_rows_buf + new_alloc;
9906 }
9907
9908 DBUG_ASSERT(m_rows_cur + length <= m_rows_end);
9909 memcpy(m_rows_cur, row_data, length);
9910 m_rows_cur+= length;
9911 m_row_count++;
9912 DBUG_RETURN(0);
9913 }
9914 #endif
9915
9916 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
9917
9918 /**
9919 Checks if any of the columns in the given table is
9920 signaled in the bitmap.
9921
9922 For each column in the given table checks if it is
9923 signaled in the bitmap. This is most useful when deciding
9924 whether a before image (BI) can be used or not for
9925 searching a row. If no column is signaled, then the
9926 image cannot be used for searching a record (regardless
9927 of using position(), index scan or table scan). Here is
9928 an example:
9929
9930 MASTER> SET @@binlog_row_image='MINIMAL';
9931 MASTER> CREATE TABLE t1 (a int, b int, c int, primary key(c));
9932 SLAVE> CREATE TABLE t1 (a int, b int);
9933 MASTER> INSERT INTO t1 VALUES (1,2,3);
9934 MASTER> UPDATE t1 SET a=2 WHERE b=2;
9935
9936 For the update statement only the PK (column c) is
9937 logged in the before image (BI). As such, given that
9938 the slave has no column c, it will not be able to
9939 find the row, because BI has no values for the columns
9940 the slave knows about (column a and b).
9941
9942 @param table the table reference on the slave.
9943 @param cols the bitmap signaling columns available in
9944 the BI.
9945
9946 @return TRUE if BI contains usable colums for searching,
9947 FALSE otherwise.
9948 */
9949 static
is_any_column_signaled_for_table(TABLE * table,MY_BITMAP * cols)9950 my_bool is_any_column_signaled_for_table(TABLE *table, MY_BITMAP *cols)
9951 {
9952 DBUG_ENTER("is_any_column_signaled_for_table");
9953
9954 for (Field **ptr= table->field ;
9955 *ptr && ((*ptr)->field_index < cols->n_bits);
9956 ptr++)
9957 {
9958 if (bitmap_is_set(cols, (*ptr)->field_index))
9959 DBUG_RETURN(TRUE);
9960 }
9961
9962 DBUG_RETURN (FALSE);
9963 }
9964
9965 /**
9966 Checks if the fields in the given key are signaled in
9967 the bitmap.
9968
9969 Validates whether the before image is usable for the
9970 given key. It can be the case that the before image
9971 does not contain values for the key (eg, master was
9972 using 'minimal' option for image logging and slave has
9973 different index structure on the table). Here is an
9974 example:
9975
9976 MASTER> SET @@binlog_row_image='MINIMAL';
9977 MASTER> CREATE TABLE t1 (a int, b int, c int, primary key(c));
9978 SLAVE> CREATE TABLE t1 (a int, b int, c int, key(a,c));
9979 MASTER> INSERT INTO t1 VALUES (1,2,3);
9980 MASTER> UPDATE t1 SET a=2 WHERE b=2;
9981
9982 When finding the row on the slave, one cannot use the
9983 index (a,c) to search for the row, because there is only
9984 data in the before image for column c. This function
9985 checks the fields needed for a given key and searches
9986 the bitmap to see if all the fields required are
9987 signaled.
9988
9989 @param keyinfo reference to key.
9990 @param cols the bitmap signaling which columns
9991 have available data.
9992
9993 @return TRUE if all fields are signaled in the bitmap
9994 for the given key, FALSE otherwise.
9995 */
9996 static
are_all_columns_signaled_for_key(KEY * keyinfo,MY_BITMAP * cols)9997 my_bool are_all_columns_signaled_for_key(KEY *keyinfo, MY_BITMAP *cols)
9998 {
9999 DBUG_ENTER("are_all_columns_signaled_for_key");
10000
10001 for (uint i=0 ; i < keyinfo->user_defined_key_parts ;i++)
10002 {
10003 uint fieldnr= keyinfo->key_part[i].fieldnr - 1;
10004 if (fieldnr >= cols->n_bits ||
10005 !bitmap_is_set(cols, fieldnr))
10006 DBUG_RETURN(FALSE);
10007 }
10008
10009 DBUG_RETURN(TRUE);
10010 }
10011
10012 /**
10013 Searches the table for a given key that can be used
10014 according to the existing values, ie, columns set
10015 in the bitmap.
10016
10017 The caller can specify which type of key to find by
10018 setting the following flags in the key_type parameter:
10019
10020 - PRI_KEY_FLAG
10021 Returns the primary key.
10022
10023 - UNIQUE_KEY_FLAG
10024 Returns a unique key (flagged with HA_NOSAME)
10025
10026 - MULTIPLE_KEY_FLAG
10027 Returns a key that is not unique (flagged with HA_NOSAME
10028 and without HA_NULL_PART_KEY) nor PK.
10029
10030 The above flags can be used together, in which case, the
10031 search is conducted in the above listed order. Eg, the
10032 following flag:
10033
10034 (PRI_KEY_FLAG | UNIQUE_KEY_FLAG | MULTIPLE_KEY_FLAG)
10035
10036 means that a primary key is returned if it is suitable. If
10037 not then the unique keys are searched. If no unique key is
10038 suitable, then the keys are searched. Finally, if no key
10039 is suitable, MAX_KEY is returned.
10040
10041 @param table reference to the table.
10042 @param bi_cols a bitmap that filters out columns that should
10043 not be considered while searching the key.
10044 Columns that should be considered are set.
10045 @param key_type the type of key to search for.
10046
10047 @return MAX_KEY if no key, according to the key_type specified
10048 is suitable. Returns the key otherwise.
10049
10050 */
10051 static
10052 uint
search_key_in_table(TABLE * table,MY_BITMAP * bi_cols,uint key_type)10053 search_key_in_table(TABLE *table, MY_BITMAP *bi_cols, uint key_type)
10054 {
10055 DBUG_ENTER("search_key_in_table");
10056
10057 KEY *keyinfo;
10058 uint res= MAX_KEY;
10059 uint key;
10060
10061 if (key_type & PRI_KEY_FLAG &&
10062 (table->s->primary_key < MAX_KEY))
10063 {
10064 DBUG_PRINT("debug", ("Searching for PK"));
10065 keyinfo= table->s->key_info + (uint) table->s->primary_key;
10066 if (are_all_columns_signaled_for_key(keyinfo, bi_cols))
10067 DBUG_RETURN(table->s->primary_key);
10068 }
10069
10070 DBUG_PRINT("debug", ("Unique keys count: %u", table->s->uniques));
10071
10072 if (key_type & UNIQUE_KEY_FLAG && table->s->uniques)
10073 {
10074 DBUG_PRINT("debug", ("Searching for UK"));
10075 for (key=0,keyinfo= table->key_info ;
10076 (key < table->s->keys) && (res == MAX_KEY);
10077 key++,keyinfo++)
10078 {
10079 /*
10080 - Unique keys cannot be disabled, thence we skip the check.
10081 - Skip unique keys with nullable parts
10082 - Skip primary keys
10083 */
10084 if (!((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME) ||
10085 (key == table->s->primary_key))
10086 continue;
10087 res= are_all_columns_signaled_for_key(keyinfo, bi_cols) ?
10088 key : MAX_KEY;
10089
10090 if (res < MAX_KEY)
10091 DBUG_RETURN(res);
10092 }
10093 DBUG_PRINT("debug", ("UK has NULLABLE parts or not all columns signaled."));
10094 }
10095
10096 if (key_type & MULTIPLE_KEY_FLAG && table->s->keys)
10097 {
10098 DBUG_PRINT("debug", ("Searching for K."));
10099 for (key=0,keyinfo= table->key_info ;
10100 (key < table->s->keys) && (res == MAX_KEY);
10101 key++,keyinfo++)
10102 {
10103 /*
10104 - Skip innactive keys
10105 - Skip unique keys without nullable parts
10106 - Skip indices that do not support ha_index_next() e.g. full-text
10107 - Skip primary keys
10108 */
10109 if (!(table->s->keys_in_use.is_set(key)) ||
10110 ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME) ||
10111 !(table->file->index_flags(key, 0, true) & HA_READ_NEXT) ||
10112 (key == table->s->primary_key))
10113 continue;
10114
10115 res= are_all_columns_signaled_for_key(keyinfo, bi_cols) ?
10116 key : MAX_KEY;
10117
10118 if (res < MAX_KEY)
10119 DBUG_RETURN(res);
10120 }
10121 DBUG_PRINT("debug", ("Not all columns signaled for K."));
10122 }
10123
10124 DBUG_RETURN(res);
10125 }
10126
10127 void
decide_row_lookup_algorithm_and_key()10128 Rows_log_event::decide_row_lookup_algorithm_and_key()
10129 {
10130
10131 DBUG_ENTER("decide_row_lookup_algorithm_and_key");
10132
10133 /*
10134 Decision table:
10135 - I --> Index scan / search
10136 - T --> Table scan
10137 - Hi --> Hash over index
10138 - Ht --> Hash over the entire table
10139
10140 |--------------+-----------+------+------+------|
10141 | Index\Option | I , T , H | I, T | I, H | T, H |
10142 |--------------+-----------+------+------+------|
10143 | PK / UK | I | I | I | Hi |
10144 | K | Hi | I | Hi | Hi |
10145 | No Index | Ht | T | Ht | Ht |
10146 |--------------+-----------+------+------+------|
10147
10148 */
10149
10150 TABLE *table= this->m_table;
10151 uint event_type= this->get_general_type_code();
10152 MY_BITMAP *cols= &this->m_cols;
10153 bool delete_update_lookup_condition= false;
10154 this->m_rows_lookup_algorithm= ROW_LOOKUP_NOT_NEEDED;
10155 this->m_key_index= MAX_KEY;
10156 this->m_key_info= NULL;
10157
10158 // row lookup not needed
10159 if (event_type == WRITE_ROWS_EVENT ||
10160 (delete_update_lookup_condition= ((event_type == DELETE_ROWS_EVENT ||
10161 event_type == UPDATE_ROWS_EVENT) &&
10162 get_flags(COMPLETE_ROWS_F) &&
10163 !m_table->file->rpl_lookup_rows())))
10164 {
10165 /**
10166 Only TokuDB engine can satisfy delete/update row lookup optimization,
10167 so we don't need to check engine type here.
10168 */
10169 if (delete_update_lookup_condition &&
10170 table->s->primary_key == MAX_KEY)
10171 {
10172 if (!table->s->rfr_lookup_warning)
10173 {
10174 sql_print_warning("Slave: read free replication is disabled "
10175 "for tokudb table `%s.%s` "
10176 "as it does not have implicit primary key, "
10177 "continue with rows lookup",
10178 print_slave_db_safe(table->s->db.str),
10179 m_table->s->table_name.str);
10180 table->s->rfr_lookup_warning= true;
10181 }
10182 }
10183 else
10184 DBUG_VOID_RETURN;
10185 }
10186
10187 if (!(slave_rows_search_algorithms_options & SLAVE_ROWS_INDEX_SCAN))
10188 goto TABLE_OR_INDEX_HASH_SCAN;
10189
10190 /* PK or UK => use LOOKUP_INDEX_SCAN */
10191 this->m_key_index= search_key_in_table(table, cols, (PRI_KEY_FLAG | UNIQUE_KEY_FLAG));
10192 if (this->m_key_index != MAX_KEY)
10193 {
10194 DBUG_PRINT("info", ("decide_row_lookup_algorithm_and_key: decided - INDEX_SCAN"));
10195 this->m_rows_lookup_algorithm= ROW_LOOKUP_INDEX_SCAN;
10196 goto end;
10197 }
10198
10199 TABLE_OR_INDEX_HASH_SCAN:
10200
10201 /*
10202 NOTE: Engines like Blackhole cannot use HASH_SCAN, because
10203 they do not syncronize reads .
10204 */
10205 if (!(slave_rows_search_algorithms_options & SLAVE_ROWS_HASH_SCAN) ||
10206 (table->file->ha_table_flags() & HA_READ_OUT_OF_SYNC))
10207 goto TABLE_OR_INDEX_FULL_SCAN;
10208
10209 /* search for a key to see if we can narrow the lookup domain further. */
10210 this->m_key_index= search_key_in_table(table, cols, (PRI_KEY_FLAG | UNIQUE_KEY_FLAG | MULTIPLE_KEY_FLAG));
10211 this->m_rows_lookup_algorithm= ROW_LOOKUP_HASH_SCAN;
10212 if (m_key_index < MAX_KEY)
10213 m_distinct_key_spare_buf= (uchar*) thd->alloc(table->key_info[m_key_index].key_length);
10214 DBUG_PRINT("info", ("decide_row_lookup_algorithm_and_key: decided - HASH_SCAN"));
10215 goto end;
10216
10217 TABLE_OR_INDEX_FULL_SCAN:
10218
10219 this->m_key_index= MAX_KEY;
10220
10221 /* If we can use an index, try to narrow the scan a bit further. */
10222 if (slave_rows_search_algorithms_options & SLAVE_ROWS_INDEX_SCAN)
10223 this->m_key_index= search_key_in_table(table, cols, (PRI_KEY_FLAG | UNIQUE_KEY_FLAG | MULTIPLE_KEY_FLAG));
10224
10225 if (this->m_key_index != MAX_KEY)
10226 {
10227 DBUG_PRINT("info", ("decide_row_lookup_algorithm_and_key: decided - INDEX_SCAN"));
10228 this->m_rows_lookup_algorithm= ROW_LOOKUP_INDEX_SCAN;
10229 }
10230 else
10231 {
10232 DBUG_PRINT("info", ("decide_row_lookup_algorithm_and_key: decided - TABLE_SCAN"));
10233 this->m_rows_lookup_algorithm= ROW_LOOKUP_TABLE_SCAN;
10234 }
10235
10236 end:
10237
10238 /* m_key_index is ready, set m_key_info now. */
10239 m_key_info= m_table->key_info + m_key_index;
10240 /*
10241 m_key_info will influence key comparison code in HASH_SCAN mode,
10242 so the m_distinct_keys set should still be empty.
10243 */
10244 DBUG_ASSERT(m_distinct_keys.empty());
10245
10246 #ifndef DBUG_OFF
10247 const char* s= ((m_rows_lookup_algorithm == Rows_log_event::ROW_LOOKUP_TABLE_SCAN) ? "TABLE_SCAN" :
10248 ((m_rows_lookup_algorithm == Rows_log_event::ROW_LOOKUP_HASH_SCAN) ? "HASH_SCAN" :
10249 "INDEX_SCAN"));
10250
10251 // only for testing purposes
10252 slave_rows_last_search_algorithm_used= m_rows_lookup_algorithm;
10253 DBUG_PRINT("debug", ("Row lookup method: %s", s));
10254 #endif
10255
10256 DBUG_VOID_RETURN;
10257 }
10258
10259 /*
10260 Encapsulates the operations to be done before applying
10261 row events for update and delete.
10262
10263 @ret value error code
10264 0 success
10265 */
10266 int
row_operations_scan_and_key_setup()10267 Rows_log_event::row_operations_scan_and_key_setup()
10268 {
10269 int error= 0;
10270 DBUG_ENTER("Row_log_event::row_operations_scan_and_key_setup");
10271
10272 /*
10273 Prepare memory structures for search operations. If
10274 search is performed:
10275
10276 1. using hash search => initialize the hash
10277 2. using key => decide on key to use and allocate mem structures
10278 3. using table scan => do nothing
10279 */
10280 decide_row_lookup_algorithm_and_key();
10281
10282 switch (m_rows_lookup_algorithm)
10283 {
10284 case ROW_LOOKUP_HASH_SCAN:
10285 {
10286 if (m_hash.init())
10287 error= HA_ERR_OUT_OF_MEM;
10288 goto err;
10289 }
10290 case ROW_LOOKUP_INDEX_SCAN:
10291 {
10292 DBUG_ASSERT (m_key_index < MAX_KEY);
10293 // Allocate buffer for key searches
10294 m_key= (uchar*)my_malloc(m_key_info->key_length, MYF(MY_WME));
10295 if (!m_key)
10296 error= HA_ERR_OUT_OF_MEM;
10297 goto err;
10298 }
10299 case ROW_LOOKUP_TABLE_SCAN:
10300 default: break;
10301 }
10302 err:
10303 DBUG_RETURN(error);
10304 }
10305
10306 /*
10307 Encapsulates the operations to be done after applying
10308 row events for update and delete.
10309
10310 @ret value error code
10311 0 success
10312 */
10313
10314 int
row_operations_scan_and_key_teardown(int error)10315 Rows_log_event::row_operations_scan_and_key_teardown(int error)
10316 {
10317 DBUG_ENTER("Rows_log_event::row_operations_scan_and_key_teardown");
10318
10319 DBUG_ASSERT(!m_table->file->inited);
10320 switch (m_rows_lookup_algorithm)
10321 {
10322 case ROW_LOOKUP_HASH_SCAN:
10323 {
10324 m_hash.deinit(); // we don't need the hash anymore.
10325 goto err;
10326 }
10327
10328 case ROW_LOOKUP_INDEX_SCAN:
10329 {
10330 if (m_table->s->keys > 0)
10331 {
10332 my_free(m_key); // Free for multi_malloc
10333 m_key= NULL;
10334 m_key_index= MAX_KEY;
10335 m_key_info= NULL;
10336 }
10337 goto err;
10338 }
10339
10340 case ROW_LOOKUP_TABLE_SCAN:
10341 default: break;
10342 }
10343
10344 err:
10345 m_rows_lookup_algorithm= ROW_LOOKUP_UNDEFINED;
10346 DBUG_RETURN(error);
10347 }
10348
10349 /*
10350 Compares table->record[0] and table->record[1]
10351
10352 Returns TRUE if different.
10353 */
record_compare(TABLE * table,MY_BITMAP * cols)10354 static bool record_compare(TABLE *table, MY_BITMAP *cols)
10355 {
10356 DBUG_ENTER("record_compare");
10357
10358 /*
10359 Need to set the X bit and the filler bits in both records since
10360 there are engines that do not set it correctly.
10361
10362 In addition, since MyISAM checks that one hasn't tampered with the
10363 record, it is necessary to restore the old bytes into the record
10364 after doing the comparison.
10365
10366 TODO[record format ndb]: Remove it once NDB returns correct
10367 records. Check that the other engines also return correct records.
10368 */
10369
10370 DBUG_DUMP("record[0]", table->record[0], table->s->reclength);
10371 DBUG_DUMP("record[1]", table->record[1], table->s->reclength);
10372
10373 bool result= false;
10374 uchar saved_x[2]= {0, 0}, saved_filler[2]= {0, 0};
10375
10376 if (table->s->null_bytes > 0)
10377 {
10378 for (int i = 0 ; i < 2 ; ++i)
10379 {
10380 /*
10381 If we have an X bit then we need to take care of it.
10382 */
10383 if (!(table->s->db_options_in_use & HA_OPTION_PACK_RECORD))
10384 {
10385 saved_x[i]= table->record[i][0];
10386 table->record[i][0]|= 1U;
10387 }
10388
10389 /*
10390 If (last_null_bit_pos == 0 && null_bytes > 1), then:
10391
10392 X bit (if any) + N nullable fields + M Field_bit fields = 8 bits
10393
10394 Ie, the entire byte is used.
10395 */
10396 if (table->s->last_null_bit_pos > 0)
10397 {
10398 saved_filler[i]= table->record[i][table->s->null_bytes - 1];
10399 table->record[i][table->s->null_bytes - 1]|=
10400 256U - (1U << table->s->last_null_bit_pos);
10401 }
10402 }
10403 }
10404
10405 /**
10406 Compare full record only if:
10407 - there are no blob fields (otherwise we would also need
10408 to compare blobs contents as well);
10409 - there are no varchar fields (otherwise we would also need
10410 to compare varchar contents as well);
10411 - there are no null fields, otherwise NULLed fields
10412 contents (i.e., the don't care bytes) may show arbitrary
10413 values, depending on how each engine handles internally.
10414 - if all the bitmap is set (both are full rows)
10415 */
10416 if ((table->s->blob_fields +
10417 table->s->varchar_fields +
10418 table->s->null_fields) == 0 &&
10419 bitmap_is_set_all(cols))
10420 {
10421 result= cmp_record(table,record[1]);
10422 }
10423
10424 /*
10425 Fallback to field-by-field comparison:
10426 1. start by checking if the field is signaled:
10427 2. if it is, first compare the null bit if the field is nullable
10428 3. then compare the contents of the field, if it is not
10429 set to null
10430 */
10431 else
10432 {
10433 for (Field **ptr=table->field ;
10434 *ptr && ((*ptr)->field_index < cols->n_bits) && !result;
10435 ptr++)
10436 {
10437 Field *field= *ptr;
10438 if (bitmap_is_set(cols, field->field_index))
10439 {
10440 /* compare null bit */
10441 if (field->is_null() != field->is_null_in_record(table->record[1]))
10442 result= true;
10443
10444 /* compare content, only if fields are not set to NULL */
10445 else if (!field->is_null())
10446 result= field->cmp_binary_offset(table->s->rec_buff_length);
10447 }
10448 }
10449 }
10450
10451 /*
10452 Restore the saved bytes.
10453
10454 TODO[record format ndb]: Remove this code once NDB returns the
10455 correct record format.
10456 */
10457 if (table->s->null_bytes > 0)
10458 {
10459 for (int i = 0 ; i < 2 ; ++i)
10460 {
10461 if (!(table->s->db_options_in_use & HA_OPTION_PACK_RECORD))
10462 table->record[i][0]= saved_x[i];
10463
10464 if (table->s->last_null_bit_pos)
10465 table->record[i][table->s->null_bytes - 1]= saved_filler[i];
10466 }
10467 }
10468
10469 DBUG_RETURN(result);
10470 }
10471
do_post_row_operations(Relay_log_info const * rli,int error)10472 void Rows_log_event::do_post_row_operations(Relay_log_info const *rli, int error)
10473 {
10474
10475 /*
10476 If m_curr_row_end was not set during event execution (e.g., because
10477 of errors) we can't proceed to the next row. If the error is transient
10478 (i.e., error==0 at this point) we must call unpack_current_row() to set
10479 m_curr_row_end.
10480 */
10481
10482 DBUG_PRINT("info", ("curr_row: 0x%lu; curr_row_end: 0x%lu; rows_end: 0x%lu",
10483 (ulong) m_curr_row, (ulong) m_curr_row_end, (ulong) m_rows_end));
10484
10485 if (!m_curr_row_end && !error)
10486 {
10487 const uchar *previous_m_curr_row= m_curr_row;
10488 error= unpack_current_row(rli, &m_cols);
10489
10490 if (!error && previous_m_curr_row == m_curr_row)
10491 {
10492 error= 1;
10493 }
10494 }
10495
10496 // at this moment m_curr_row_end should be set
10497 DBUG_ASSERT(error || m_curr_row_end != NULL);
10498 DBUG_ASSERT(error || m_curr_row <= m_curr_row_end);
10499 DBUG_ASSERT(error || m_curr_row_end <= m_rows_end);
10500
10501 m_curr_row= m_curr_row_end;
10502
10503 if (error == 0 && !m_table->file->has_transactions())
10504 {
10505 thd->transaction.all.set_unsafe_rollback_flags(TRUE);
10506 thd->transaction.stmt.set_unsafe_rollback_flags(TRUE);
10507 }
10508 }
10509
handle_idempotent_and_ignored_errors(Relay_log_info const * rli,int * err)10510 int Rows_log_event::handle_idempotent_and_ignored_errors(Relay_log_info const *rli, int *err)
10511 {
10512 int error= *err;
10513 if (error)
10514 {
10515 int actual_error= convert_handler_error(error, thd, m_table);
10516 bool idempotent_error= (idempotent_error_code(error) &&
10517 (slave_exec_mode == SLAVE_EXEC_MODE_IDEMPOTENT));
10518 bool ignored_error= (idempotent_error == 0 ?
10519 ignored_error_code(actual_error) : 0);
10520
10521 if (idempotent_error || ignored_error)
10522 {
10523 if ( (idempotent_error && log_warnings) ||
10524 (ignored_error && log_warnings > 1) )
10525 slave_rows_error_report(WARNING_LEVEL, error, rli, thd, m_table,
10526 get_type_str(),
10527 const_cast<Relay_log_info*>(rli)->get_rpl_log_name(),
10528 (ulong) log_pos);
10529 thd->get_stmt_da()->clear_warning_info(thd->query_id);
10530 clear_all_errors(thd, const_cast<Relay_log_info*>(rli));
10531 *err= 0;
10532 if (idempotent_error == 0)
10533 return ignored_error;
10534 }
10535 }
10536
10537 return *err;
10538 }
10539
do_apply_row(Relay_log_info const * rli)10540 int Rows_log_event::do_apply_row(Relay_log_info const *rli)
10541 {
10542 DBUG_ENTER("Rows_log_event::do_apply_row");
10543
10544 int error= 0;
10545
10546 /* in_use can have been set to NULL in close_tables_for_reopen */
10547 THD* old_thd= m_table->in_use;
10548 if (!m_table->in_use)
10549 m_table->in_use= thd;
10550
10551 error= do_exec_row(rli);
10552
10553 if(error)
10554 {
10555 DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
10556 DBUG_ASSERT(error != HA_ERR_RECORD_DELETED);
10557 }
10558
10559 m_table->in_use = old_thd;
10560
10561 DBUG_RETURN(error);
10562 }
10563
10564 /**
10565 Does the cleanup
10566 - closes the index if opened by open_record_scan
10567 - closes the table if opened for scanning.
10568 */
10569 int
close_record_scan()10570 Rows_log_event::close_record_scan()
10571 {
10572 DBUG_ENTER("Rows_log_event::close_record_scan");
10573 int error= 0;
10574
10575 // if there is something to actually close
10576 if (m_key_index < MAX_KEY)
10577 {
10578 if (m_table->file->inited)
10579 error= m_table->file->ha_index_end();
10580 }
10581 else if (m_table->file->inited)
10582 error= m_table->file->ha_rnd_end();
10583
10584 DBUG_RETURN(error);
10585 }
10586
10587 /**
10588 Fetches next row. If it is a HASH_SCAN over an index, it populates
10589 table->record[0] with the next row corresponding to the index. If
10590 the indexes are in non-contigous ranges it fetches record corresponding
10591 to the key value in the next range.
10592
10593 @parms: bool first_read : signifying if this is the first time we are reading a row
10594 over an index.
10595 @return_value: - error code when there are no more reeords to be fetched or some other
10596 error occured,
10597 - 0 otherwise.
10598 */
10599 int
next_record_scan(bool first_read)10600 Rows_log_event::next_record_scan(bool first_read)
10601 {
10602 DBUG_ENTER("Rows_log_event::next_record_scan");
10603 DBUG_ASSERT(m_table->file->inited);
10604 TABLE *table= m_table;
10605 int error= 0;
10606
10607 if (m_key_index >= MAX_KEY)
10608 error= table->file->ha_rnd_next(table->record[0]);
10609 else
10610 {
10611 /*
10612 We need to set the null bytes to ensure that the filler bit are
10613 all set when returning. There are storage engines that just set
10614 the necessary bits on the bytes and don't set the filler bits
10615 correctly.
10616 */
10617 if (table->s->null_bytes > 0)
10618 table->record[0][table->s->null_bytes - 1]|=
10619 256U - (1U << table->s->last_null_bit_pos);
10620
10621 if (!first_read)
10622 {
10623 /*
10624 if we fail to fetch next record corresponding to a key value, we
10625 move to the next key value. If we are out of key values as well an error
10626 will be returned.
10627 */
10628 error= table->file->ha_index_next_same(table->record[0], m_key,
10629 m_key_info->key_length);
10630 if(m_rows_lookup_algorithm == ROW_LOOKUP_HASH_SCAN)
10631 {
10632 /*
10633 if we are out of rows for this particular key value, we reposition the
10634 marker according to the next key value that we have in the list.
10635 */
10636 if (error)
10637 {
10638 if (m_itr != m_distinct_keys.end())
10639 {
10640 m_key= *m_itr;
10641 m_itr++;
10642 first_read= true;
10643 }
10644 else
10645 error= HA_ERR_KEY_NOT_FOUND;
10646 }
10647 }
10648 }
10649
10650 if (first_read)
10651 if ((error= table->file->ha_index_read_map(table->record[0], m_key,
10652 HA_WHOLE_KEY,
10653 HA_READ_KEY_EXACT)))
10654 {
10655 DBUG_PRINT("info",("no record matching the key found in the table"));
10656 if (error == HA_ERR_RECORD_DELETED)
10657 error= HA_ERR_KEY_NOT_FOUND;
10658 }
10659 }
10660
10661 DBUG_RETURN(error);
10662 }
10663
10664 /**
10665 Initializes scanning of rows. Opens an index and initializes an iterator
10666 over a list of distinct keys (m_distinct_keys) if it is a HASH_SCAN
10667 over an index or the table if its a HASH_SCAN over the table.
10668 */
10669 int
open_record_scan()10670 Rows_log_event::open_record_scan()
10671 {
10672 int error= 0;
10673 TABLE *table= m_table;
10674 DBUG_ENTER("Rows_log_event::open_record_scan");
10675
10676 if (m_key_index < MAX_KEY )
10677 {
10678 if(m_rows_lookup_algorithm == ROW_LOOKUP_HASH_SCAN)
10679 {
10680 /* initialize the iterator over the list of distinct keys that we have */
10681 m_itr= m_distinct_keys.begin();
10682
10683 /* get the first element from the list of keys and increment the
10684 iterator
10685 */
10686 m_key= *m_itr;
10687 m_itr++;
10688 }
10689 else {
10690 /* this is an INDEX_SCAN we need to store the key in m_key */
10691 DBUG_ASSERT((m_rows_lookup_algorithm == ROW_LOOKUP_INDEX_SCAN) && m_key);
10692 key_copy(m_key, m_table->record[0], m_key_info, 0);
10693 }
10694
10695 /*
10696 Save copy of the record in table->record[1]. It might be needed
10697 later if linear search is used to find exact match.
10698 */
10699 store_record(table,record[1]);
10700
10701 DBUG_PRINT("info",("locating record using a key (index_read)"));
10702
10703 /* The m_key_index'th key is active and usable: search the table using the index */
10704 if (!table->file->inited && (error= table->file->ha_index_init(m_key_index, FALSE)))
10705 {
10706 DBUG_PRINT("info",("ha_index_init returns error %d",error));
10707 goto end;
10708 }
10709
10710 /*
10711 Don't print debug messages when running valgrind since they can
10712 trigger false warnings.
10713 */
10714 #ifndef HAVE_purify
10715 DBUG_DUMP("key data", m_key, m_key_info->key_length);
10716 #endif
10717 }
10718 else
10719 {
10720 if ((error= table->file->ha_rnd_init(1)))
10721 {
10722 DBUG_PRINT("info",("error initializing table scan"
10723 " (ha_rnd_init returns %d)",error));
10724 table->file->print_error(error, MYF(0));
10725 }
10726 }
10727
10728 end:
10729 DBUG_RETURN(error);
10730 }
10731
10732 /**
10733 Populates the m_distinct_keys with unique keys to be modified
10734 during HASH_SCAN over keys.
10735 @return_value -0 success
10736 -Err_code
10737 */
10738 int
add_key_to_distinct_keyset()10739 Rows_log_event::add_key_to_distinct_keyset()
10740 {
10741 int error= 0;
10742 DBUG_ENTER("Rows_log_event::add_key_to_distinct_keyset");
10743 DBUG_ASSERT(m_key_index < MAX_KEY);
10744 key_copy(m_distinct_key_spare_buf, m_table->record[0], m_key_info, 0);
10745 std::pair<std::set<uchar *, Key_compare>::iterator,bool> ret=
10746 m_distinct_keys.insert(m_distinct_key_spare_buf);
10747 if (ret.second)
10748 {
10749 /* Insert is successful, so allocate a new buffer for next key */
10750 m_distinct_key_spare_buf= (uchar*) thd->alloc(m_key_info->key_length);
10751 if (!m_distinct_key_spare_buf)
10752 {
10753 error= HA_ERR_OUT_OF_MEM;
10754 goto err;
10755 }
10756 }
10757 err:
10758 DBUG_RETURN(error);
10759 }
10760
10761
do_index_scan_and_update(Relay_log_info const * rli)10762 int Rows_log_event::do_index_scan_and_update(Relay_log_info const *rli)
10763 {
10764 DBUG_ENTER("Rows_log_event::do_index_scan_and_update");
10765 DBUG_ASSERT(m_table && m_table->in_use != NULL);
10766
10767 int error= 0;
10768 const uchar *saved_m_curr_row= m_curr_row;
10769
10770 /*
10771 rpl_row_tabledefs.test specifies that
10772 if the extra field on the slave does not have a default value
10773 and this is okay with Delete or Update events.
10774 Todo: fix wl3228 hld that requires defaults for all types of events
10775 */
10776
10777 prepare_record(m_table, &m_cols, FALSE);
10778 if ((error= unpack_current_row(rli, &m_cols)))
10779 goto end;
10780
10781 // Temporary fix to find out why it fails [/Matz]
10782 memcpy(m_table->read_set->bitmap, m_cols.bitmap, (m_table->read_set->n_bits + 7) / 8);
10783
10784 /*
10785 Trying to do an index scan without a usable key
10786 This is a valid state because we allow the user
10787 to set Slave_rows_search_algorithm= 'INDEX_SCAN'.
10788
10789 Therefore on tables with no indexes we will end
10790 up here.
10791 */
10792 if (m_key_index >= MAX_KEY)
10793 {
10794 error= HA_ERR_END_OF_FILE;
10795 goto end;
10796 }
10797
10798 #ifndef DBUG_OFF
10799 DBUG_PRINT("info",("looking for the following record"));
10800 DBUG_DUMP("record[0]", m_table->record[0], m_table->s->reclength);
10801 #endif
10802
10803 if (m_key_index != m_table->s->primary_key)
10804 /* we dont have a PK, or PK is not usable */
10805 goto INDEX_SCAN;
10806
10807 if ((m_table->file->ha_table_flags() & HA_READ_BEFORE_WRITE_REMOVAL))
10808 {
10809 /*
10810 Read removal is possible since the engine supports write without
10811 previous read using full primary key
10812 */
10813 DBUG_PRINT("info", ("using read before write removal"));
10814 DBUG_ASSERT(m_key_index == m_table->s->primary_key);
10815
10816 /*
10817 Tell the handler to ignore if key exists or not, since it's
10818 not yet known if the key does exist(when using rbwr)
10819 */
10820 m_table->file->extra(HA_EXTRA_IGNORE_NO_KEY);
10821
10822 goto end;
10823 }
10824
10825 if ((m_table->file->ha_table_flags() & HA_PRIMARY_KEY_REQUIRED_FOR_POSITION))
10826 {
10827 /*
10828 Use a more efficient method to fetch the record given by
10829 table->record[0] if the engine allows it. We first compute a
10830 row reference using the position() member function (it will be
10831 stored in table->file->ref) and then use rnd_pos() to position
10832 the "cursor" (i.e., record[0] in this case) at the correct row.
10833
10834 TODO: Check that the correct record has been fetched by
10835 comparing it with the original record. Take into account that the
10836 record on the master and slave can be of different
10837 length. Something along these lines should work:
10838
10839 ADD>>> store_record(table,record[1]);
10840 int error= table->file->rnd_pos(table->record[0], table->file->ref);
10841 ADD>>> DBUG_ASSERT(memcmp(table->record[1], table->record[0],
10842 table->s->reclength) == 0);
10843
10844 */
10845
10846 DBUG_PRINT("info",("locating record using primary key (position)"));
10847 if (m_table->file->inited && (error= m_table->file->ha_index_end()))
10848 goto end;
10849
10850 error= m_table->file->rnd_pos_by_record(m_table->record[0]);
10851 if (error)
10852 {
10853 DBUG_PRINT("info",("rnd_pos returns error %d",error));
10854 if (error == HA_ERR_RECORD_DELETED)
10855 error= HA_ERR_KEY_NOT_FOUND;
10856 }
10857
10858 goto end;
10859 }
10860
10861 // We can't use position() - try other methods.
10862
10863 INDEX_SCAN:
10864
10865 /* Use the m_key_index'th key */
10866
10867 if ((error= open_record_scan()))
10868 goto end;
10869
10870 error= next_record_scan(true);
10871 if (error)
10872 {
10873 DBUG_PRINT("info",("no record matching the key found in the table"));
10874 if (error == HA_ERR_RECORD_DELETED)
10875 error= HA_ERR_KEY_NOT_FOUND;
10876 goto end;
10877 }
10878
10879
10880 /*
10881 Don't print debug messages when running valgrind since they can
10882 trigger false warnings.
10883 */
10884 #ifndef HAVE_purify
10885 DBUG_PRINT("info",("found first matching record"));
10886 DBUG_DUMP("record[0]", m_table->record[0], m_table->s->reclength);
10887 #endif
10888 /*
10889 Below is a minor "optimization". If the key (i.e., key number
10890 0) has the HA_NOSAME flag set, we know that we have found the
10891 correct record (since there can be no duplicates); otherwise, we
10892 have to compare the record with the one found to see if it is
10893 the correct one.
10894
10895 CAVEAT! This behaviour is essential for the replication of,
10896 e.g., the mysql.proc table since the correct record *shall* be
10897 found using the primary key *only*. There shall be no
10898 comparison of non-PK columns to decide if the correct record is
10899 found. I can see no scenario where it would be incorrect to
10900 chose the row to change only using a PK or an UNNI.
10901 */
10902 if (m_key_info->flags & HA_NOSAME || m_key_index == m_table->s->primary_key)
10903 {
10904 /* Unique does not have non nullable part */
10905 if (!(m_key_info->flags & (HA_NULL_PART_KEY)))
10906 goto end; // record found
10907 else
10908 {
10909 /*
10910 Unique has nullable part. We need to check if there is any field in the
10911 BI image that is null and part of UNNI.
10912 */
10913 bool null_found= FALSE;
10914 for (uint i=0; i < m_key_info->user_defined_key_parts && !null_found; i++)
10915 {
10916 uint fieldnr= m_key_info->key_part[i].fieldnr - 1;
10917 Field **f= m_table->field+fieldnr;
10918 null_found= (*f)->is_null();
10919 }
10920
10921 if (!null_found)
10922 goto end; // record found
10923
10924 /* else fall through to index scan */
10925 }
10926 }
10927
10928 /*
10929 In case key is not unique, we still have to iterate over records found
10930 and find the one which is identical to the row given. A copy of the
10931 record we are looking for is stored in record[1].
10932 */
10933 DBUG_PRINT("info",("non-unique index, scanning it to find matching record"));
10934
10935 while (record_compare(m_table, &m_cols))
10936 {
10937 while((error= next_record_scan(false)))
10938 {
10939 /* We just skip records that has already been deleted */
10940 if (error == HA_ERR_RECORD_DELETED)
10941 continue;
10942 DBUG_PRINT("info",("no record matching the given row found"));
10943 goto end;
10944 }
10945 }
10946
10947 end:
10948
10949 DBUG_ASSERT(error != HA_ERR_RECORD_DELETED);
10950
10951 if (error && error != HA_ERR_RECORD_DELETED)
10952 m_table->file->print_error(error, MYF(0));
10953 else
10954 error= do_apply_row(rli);
10955
10956 if (!error)
10957 error= close_record_scan();
10958 else
10959 /*
10960 we are already with errors. Keep the error code and
10961 try to close the scan anyway.
10962 */
10963 (void) close_record_scan();
10964
10965 if ((get_general_type_code() == UPDATE_ROWS_EVENT) &&
10966 (saved_m_curr_row == m_curr_row))
10967 {
10968 /* we need to unpack the AI so that positions get updated */
10969 m_curr_row= m_curr_row_end;
10970 unpack_current_row(rli, &m_cols_ai);
10971 }
10972 m_table->default_column_bitmaps();
10973 DBUG_RETURN(error);
10974
10975 }
10976
do_hash_row(Relay_log_info const * rli)10977 int Rows_log_event::do_hash_row(Relay_log_info const *rli)
10978 {
10979 DBUG_ENTER("Rows_log_event::do_hash_row");
10980 DBUG_ASSERT(m_table && m_table->in_use != NULL);
10981 int error= 0;
10982
10983 /* create an empty entry to add to the hash table */
10984 HASH_ROW_ENTRY* entry= m_hash.make_entry();
10985 if (entry == NULL)
10986 {
10987 error= 1;
10988 goto end;
10989 }
10990 /* Prepare the record, unpack and save positions. */
10991 entry->positions->bi_start= m_curr_row; // save the bi start pos
10992 prepare_record(m_table, &m_cols, false);
10993 if ((error= unpack_current_row(rli, &m_cols)))
10994 goto end;
10995 entry->positions->bi_ends= m_curr_row_end; // save the bi end pos
10996
10997 /*
10998 Now that m_table->record[0] is filled in, we can add the entry
10999 to the hash table. Note that the put operation calculates the
11000 key based on record[0] contents (including BLOB fields).
11001 */
11002 m_hash.put(m_table, &m_cols, entry);
11003
11004 if (m_key_index < MAX_KEY)
11005 add_key_to_distinct_keyset();
11006
11007 /*
11008 We need to unpack the AI to advance the positions, so we
11009 know when we have reached m_rows_end and that we do not
11010 unpack the AI in the next iteration as if it was a BI.
11011 */
11012 if (get_general_type_code() == UPDATE_ROWS_EVENT)
11013 {
11014 /* Save a copy of the BI. */
11015 store_record(m_table, record[1]);
11016
11017 /*
11018 This is the situation after hashing the BI:
11019
11020 ===|=== before image ====|=== after image ===|===
11021 ^ ^
11022 m_curr_row m_curr_row_end
11023 */
11024
11025 /* Set the position to the start of the record to be unpacked. */
11026 m_curr_row= m_curr_row_end;
11027
11028 /* We shouldn't need this, but lets not leave loose ends */
11029 prepare_record(m_table, &m_cols, false);
11030 error= unpack_current_row(rli, &m_cols_ai);
11031
11032 /*
11033 This is the situation after unpacking the AI:
11034
11035 ===|=== before image ====|=== after image ===|===
11036 ^ ^
11037 m_curr_row m_curr_row_end
11038 */
11039
11040 /* Restore back the copy of the BI. */
11041 restore_record(m_table, record[1]);
11042 }
11043
11044 end:
11045 DBUG_RETURN(error);
11046 }
11047
do_scan_and_update(Relay_log_info const * rli)11048 int Rows_log_event::do_scan_and_update(Relay_log_info const *rli)
11049 {
11050 DBUG_ENTER("Rows_log_event::do_scan_and_update");
11051 DBUG_ASSERT(m_table && m_table->in_use != NULL);
11052 DBUG_ASSERT(m_hash.is_empty() == false);
11053 TABLE *table= m_table;
11054 int error= 0;
11055 const uchar *saved_last_m_curr_row= NULL;
11056 const uchar *saved_last_m_curr_row_end= NULL;
11057 /* create an empty entry to add to the hash table */
11058 HASH_ROW_ENTRY* entry= NULL;
11059 int idempotent_errors= 0;
11060 int i= 0;
11061
11062 saved_last_m_curr_row=m_curr_row;
11063 saved_last_m_curr_row_end=m_curr_row_end;
11064
11065 DBUG_PRINT("info",("Hash was populated with %d records!", m_hash.size()));
11066
11067 /* open table or index depending on whether we have set m_key_index or not. */
11068 if ((error= open_record_scan()))
11069 goto err;
11070
11071 /*
11072 Scan the table only once and compare against entries in hash.
11073 When a match is found, apply the changes.
11074 */
11075 do
11076 {
11077 /* get the next record from the table */
11078 error= next_record_scan(i == 0);
11079 i++;
11080
11081 if(error)
11082 DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
11083 switch (error) {
11084 case 0:
11085 {
11086 entry= m_hash.get(table, &m_cols);
11087 store_record(table, record[1]);
11088
11089 /**
11090 If there are collisions we need to be sure that this is
11091 indeed the record we want. Loop through all records for
11092 the given key and explicitly compare them against the
11093 record we got from the storage engine.
11094 */
11095 while(entry)
11096 {
11097 m_curr_row= entry->positions->bi_start;
11098 m_curr_row_end= entry->positions->bi_ends;
11099
11100 prepare_record(table, &m_cols, false);
11101 if ((error= unpack_current_row(rli, &m_cols)))
11102 goto close_table;
11103
11104 if (record_compare(table, &m_cols))
11105 m_hash.next(&entry);
11106 else
11107 break; // we found a match
11108 }
11109
11110 /**
11111 We found the entry we needed, just apply the changes.
11112 */
11113 if (entry)
11114 {
11115 // just to be safe, copy the record from the SE to table->record[0]
11116 restore_record(table, record[1]);
11117
11118 /**
11119 At this point, both table->record[0] and
11120 table->record[1] have the SE row that matched the one
11121 in the hash table.
11122
11123 Thence if this is a DELETE we wouldn't need to mess
11124 around with positions anymore, but since this can be an
11125 update, we need to provide positions so that AI is
11126 unpacked correctly to table->record[0] in UPDATE
11127 implementation of do_exec_row().
11128 */
11129 m_curr_row= entry->positions->bi_start;
11130 m_curr_row_end= entry->positions->bi_ends;
11131
11132 /* we don't need this entry anymore, just delete it */
11133 if ((error= m_hash.del(entry)))
11134 goto err;
11135
11136 if ((error= do_apply_row(rli)))
11137 {
11138 if (handle_idempotent_and_ignored_errors(rli, &error))
11139 goto close_table;
11140
11141 do_post_row_operations(rli, error);
11142 }
11143 }
11144 }
11145 break;
11146
11147 case HA_ERR_RECORD_DELETED:
11148 // get next
11149 continue;
11150
11151 case HA_ERR_KEY_NOT_FOUND:
11152 /* If the slave exec mode is idempotent or the error is
11153 skipped error, then don't break */
11154 if (handle_idempotent_and_ignored_errors(rli, &error))
11155 goto close_table;
11156 idempotent_errors++;
11157 continue;
11158
11159 case HA_ERR_END_OF_FILE:
11160 default:
11161 // exception (hash is not empty and we have reached EOF or
11162 // other error happened)
11163 goto close_table;
11164 }
11165 }
11166 /**
11167 if the slave_exec_mode is set to Idempotent, we cannot expect the hash to
11168 be empty. In such cases we count the number of idempotent errors and check
11169 if it is equal to or greater than the number of rows left in the hash.
11170 */
11171 while (((idempotent_errors < m_hash.size()) && !m_hash.is_empty()) &&
11172 (!error || (error == HA_ERR_RECORD_DELETED)));
11173
11174 close_table:
11175 if (error == HA_ERR_RECORD_DELETED)
11176 error= 0;
11177
11178 if (error)
11179 {
11180 table->file->print_error(error, MYF(0));
11181 DBUG_PRINT("info", ("Failed to get next record"
11182 " (ha_rnd_next returns %d)",error));
11183 /*
11184 we are already with errors. Keep the error code and
11185 try to close the scan anyway.
11186 */
11187 (void) close_record_scan();
11188 }
11189 else
11190 error= close_record_scan();
11191
11192 DBUG_ASSERT((m_hash.is_empty() && !error) ||
11193 (!m_hash.is_empty() &&
11194 ((error) || (idempotent_errors >= m_hash.size()))));
11195
11196 err:
11197
11198 if ((m_hash.is_empty() && !error) || (idempotent_errors >= m_hash.size()))
11199 {
11200 /**
11201 Reset the last positions, because the positions are lost while
11202 handling entries in the hash.
11203 */
11204 m_curr_row= saved_last_m_curr_row;
11205 m_curr_row_end= saved_last_m_curr_row_end;
11206 }
11207
11208 DBUG_RETURN(error);
11209 }
11210
do_hash_scan_and_update(Relay_log_info const * rli)11211 int Rows_log_event::do_hash_scan_and_update(Relay_log_info const *rli)
11212 {
11213 DBUG_ENTER("Rows_log_event::do_hash_scan_and_update");
11214 DBUG_ASSERT(m_table && m_table->in_use != NULL);
11215
11216 // HASHING PART
11217
11218 /* unpack the BI (and AI, if it exists) and add it to the hash map. */
11219 if (int error= this->do_hash_row(rli))
11220 DBUG_RETURN(error);
11221
11222 /* We have not yet hashed all rows in the buffer. Do not proceed to the SCAN part. */
11223 if (m_curr_row_end < m_rows_end)
11224 DBUG_RETURN (0);
11225
11226 DBUG_PRINT("info",("Hash was populated with %d records!", m_hash.size()));
11227 DBUG_ASSERT(m_curr_row_end == m_rows_end);
11228
11229 // SCANNING & UPDATE PART
11230
11231 DBUG_RETURN(this->do_scan_and_update(rli));
11232 }
11233
do_table_scan_and_update(Relay_log_info const * rli)11234 int Rows_log_event::do_table_scan_and_update(Relay_log_info const *rli)
11235 {
11236 int error= 0;
11237 const uchar* saved_m_curr_row= m_curr_row;
11238 TABLE* table= m_table;
11239
11240 DBUG_ENTER("Rows_log_event::do_table_scan_and_update");
11241 DBUG_ASSERT(m_curr_row != m_rows_end);
11242 DBUG_PRINT("info",("locating record using table scan (ha_rnd_next)"));
11243
11244 saved_m_curr_row= m_curr_row;
11245
11246 /** unpack the before image */
11247 prepare_record(table, &m_cols, FALSE);
11248 if (!(error= unpack_current_row(rli, &m_cols)))
11249 {
11250 // Temporary fix to find out why it fails [/Matz]
11251 memcpy(m_table->read_set->bitmap, m_cols.bitmap, (m_table->read_set->n_bits + 7) / 8);
11252
11253 /** save a copy so that we can compare against it later */
11254 store_record(m_table, record[1]);
11255
11256 int restart_count= 0; // Number of times scanning has restarted from top
11257
11258 if ((error= m_table->file->ha_rnd_init(1)))
11259 {
11260 DBUG_PRINT("info",("error initializing table scan"
11261 " (ha_rnd_init returns %d)",error));
11262 goto end;
11263 }
11264
11265 /* Continue until we find the right record or have made a full loop */
11266 do
11267 {
11268 restart_ha_rnd_next:
11269 error= m_table->file->ha_rnd_next(m_table->record[0]);
11270 if (error)
11271 DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
11272 switch (error) {
11273 case HA_ERR_END_OF_FILE:
11274 // restart scan from top
11275 if (++restart_count < 2)
11276 {
11277 if ((error= m_table->file->ha_rnd_init(1)))
11278 goto end;
11279 goto restart_ha_rnd_next;
11280 }
11281 break;
11282
11283 case HA_ERR_RECORD_DELETED:
11284 // fetch next
11285 goto restart_ha_rnd_next;
11286 case 0:
11287 // we're good, check if record matches
11288 break;
11289
11290 default:
11291 // exception
11292 goto end;
11293 }
11294 }
11295 while (restart_count < 2 && record_compare(m_table, &m_cols));
11296 }
11297
11298 end:
11299
11300 DBUG_ASSERT(error != HA_ERR_RECORD_DELETED);
11301
11302 /* either we report error or apply the changes */
11303 if (error && error != HA_ERR_RECORD_DELETED)
11304 {
11305 DBUG_PRINT("info", ("Failed to get next record"
11306 " (ha_rnd_next returns %d)",error));
11307 m_table->file->print_error(error, MYF(0));
11308 }
11309 else
11310 error= do_apply_row(rli);
11311
11312
11313 if (!error)
11314 error= close_record_scan();
11315 else
11316 /*
11317 we are already with errors. Keep the error code and
11318 try to close the scan anyway.
11319 */
11320 (void) close_record_scan();
11321
11322 if ((get_general_type_code() == UPDATE_ROWS_EVENT) &&
11323 (saved_m_curr_row == m_curr_row)) // we need to unpack the AI
11324 {
11325 m_curr_row= m_curr_row_end;
11326 unpack_current_row(rli, &m_cols);
11327 }
11328
11329 table->default_column_bitmaps();
11330 DBUG_RETURN(error);
11331 }
11332
do_apply_event(Relay_log_info const * rli)11333 int Rows_log_event::do_apply_event(Relay_log_info const *rli)
11334 {
11335 DBUG_ENTER("Rows_log_event::do_apply_event(Relay_log_info*)");
11336 TABLE *table= NULL;
11337 int error= 0;
11338
11339 if (opt_bin_log)
11340 {
11341 enum_gtid_statement_status state= gtid_pre_statement_checks(thd);
11342 if (state == GTID_STATEMENT_CANCEL)
11343 // error has already been printed; don't print anything more here
11344 DBUG_RETURN(-1);
11345 else if (state == GTID_STATEMENT_SKIP)
11346 DBUG_RETURN(0);
11347 }
11348
11349 /*
11350 'thd' has been set by exec_relay_log_event(), just before calling
11351 do_apply_event(). We still check here to prevent future coding
11352 errors.
11353 */
11354 DBUG_ASSERT(rli->info_thd == thd);
11355
11356 /*
11357 If there is no locks taken, this is the first binrow event seen
11358 after the table map events. We should then lock all the tables
11359 used in the transaction and proceed with execution of the actual
11360 event.
11361 */
11362 if (!thd->lock)
11363 {
11364 /*
11365 Lock_tables() reads the contents of thd->lex, so they must be
11366 initialized.
11367
11368 We also call the mysql_reset_thd_for_next_command(), since this
11369 is the logical start of the next "statement". Note that this
11370 call might reset the value of current_stmt_binlog_format, so
11371 we need to do any changes to that value after this function.
11372 */
11373 lex_start(thd);
11374 mysql_reset_thd_for_next_command(thd);
11375 /*
11376 The current statement is just about to begin and
11377 has not yet modified anything. Note, all.modified is reset
11378 by mysql_reset_thd_for_next_command.
11379 */
11380 thd->transaction.stmt.reset_unsafe_rollback_flags();
11381 /*
11382 This is a row injection, so we flag the "statement" as
11383 such. Note that this code is called both when the slave does row
11384 injections and when the BINLOG statement is used to do row
11385 injections.
11386 */
11387 thd->lex->set_stmt_row_injection();
11388
11389 /*
11390 There are a few flags that are replicated with each row event.
11391 Make sure to set/clear them before executing the main body of
11392 the event.
11393 */
11394 if (get_flags(NO_FOREIGN_KEY_CHECKS_F))
11395 thd->variables.option_bits|= OPTION_NO_FOREIGN_KEY_CHECKS;
11396 else
11397 thd->variables.option_bits&= ~OPTION_NO_FOREIGN_KEY_CHECKS;
11398
11399 if (get_flags(RELAXED_UNIQUE_CHECKS_F))
11400 thd->variables.option_bits|= OPTION_RELAXED_UNIQUE_CHECKS;
11401 else
11402 thd->variables.option_bits&= ~OPTION_RELAXED_UNIQUE_CHECKS;
11403
11404 thd->binlog_row_event_extra_data = m_extra_row_data;
11405
11406 /* A small test to verify that objects have consistent types */
11407 DBUG_ASSERT(sizeof(thd->variables.option_bits) == sizeof(OPTION_RELAXED_UNIQUE_CHECKS));
11408 DBUG_EXECUTE_IF("rows_log_event_before_open_table",
11409 {
11410 const char action[] = "now SIGNAL before_open_table WAIT_FOR go_ahead_sql";
11411 DBUG_ASSERT(!debug_sync_set_action(thd, STRING_WITH_LEN(action)));
11412 };);
11413 if (open_and_lock_tables(thd, rli->tables_to_lock, FALSE, 0))
11414 {
11415 if (thd->is_error())
11416 {
11417 uint actual_error= thd->get_stmt_da()->sql_errno();
11418 if (ignored_error_code(actual_error))
11419 {
11420 if (log_warnings > 1)
11421 rli->report(WARNING_LEVEL, actual_error,
11422 "Error executing row event: '%s'",
11423 thd->get_stmt_da()->message());
11424 thd->get_stmt_da()->clear_warning_info(thd->query_id);
11425 clear_all_errors(thd, const_cast<Relay_log_info*>(rli));
11426 error= 0;
11427 goto end;
11428 }
11429 else
11430 {
11431 rli->report(ERROR_LEVEL, actual_error,
11432 "Error executing row event: '%s'",
11433 thd->get_stmt_da()->message());
11434 thd->is_slave_error= 1;
11435 }
11436 }
11437 DBUG_RETURN(1);
11438 }
11439 /*
11440 When the open and locking succeeded, we check all tables to
11441 ensure that they still have the correct type.
11442 */
11443
11444 {
11445 DBUG_PRINT("debug", ("Checking compability of tables to lock - tables_to_lock: %p",
11446 rli->tables_to_lock));
11447
11448 /**
11449 When using RBR and MyISAM MERGE tables the base tables that make
11450 up the MERGE table can be appended to the list of tables to lock.
11451
11452 Thus, we just check compatibility for those that tables that have
11453 a correspondent table map event (ie, those that are actually going
11454 to be accessed while applying the event). That's why the loop stops
11455 at rli->tables_to_lock_count .
11456
11457 NOTE: The base tables are added here are removed when
11458 close_thread_tables is called.
11459 */
11460 TABLE_LIST *table_list_ptr= rli->tables_to_lock;
11461 for (uint i=0 ; table_list_ptr && (i < rli->tables_to_lock_count);
11462 table_list_ptr= table_list_ptr->next_global, i++)
11463 {
11464 /*
11465 Below if condition takes care of skipping base tables that
11466 make up the MERGE table (which are added by open_tables()
11467 call). They are added next to the merge table in the list.
11468 For eg: If RPL_TABLE_LIST is t3->t1->t2 (where t1 and t2
11469 are base tables for merge table 't3'), open_tables will modify
11470 the list by adding t1 and t2 again immediately after t3 in the
11471 list (*not at the end of the list*). New table_to_lock list will
11472 look like t3->t1'->t2'->t1->t2 (where t1' and t2' are TABLE_LIST
11473 objects added by open_tables() call). There is no flag(or logic) in
11474 open_tables() that can skip adding these base tables to the list.
11475 So the logic here should take care of skipping them.
11476
11477 tables_to_lock_count logic will take care of skipping base tables
11478 that are added at the end of the list.
11479 For eg: If RPL_TABLE_LIST is t1->t2->t3, open_tables will modify
11480 the list into t1->t2->t3->t1'->t2'. t1' and t2' will be skipped
11481 because tables_to_lock_count logic in this for loop.
11482 */
11483 if (table_list_ptr->parent_l)
11484 continue;
11485 /*
11486 We can use a down cast here since we know that every table added
11487 to the tables_to_lock is a RPL_TABLE_LIST (or child table which is
11488 skipped above).
11489 */
11490 RPL_TABLE_LIST *ptr= static_cast<RPL_TABLE_LIST*>(table_list_ptr);
11491 DBUG_ASSERT(ptr->m_tabledef_valid);
11492 TABLE *conv_table;
11493 if (!ptr->m_tabledef.compatible_with(thd, const_cast<Relay_log_info*>(rli),
11494 ptr->table, &conv_table))
11495 {
11496 DBUG_PRINT("debug", ("Table: %s.%s is not compatible with master",
11497 ptr->table->s->db.str,
11498 ptr->table->s->table_name.str));
11499 if (thd->is_slave_error)
11500 {
11501 const_cast<Relay_log_info*>(rli)->slave_close_thread_tables(thd);
11502 DBUG_RETURN(ERR_BAD_TABLE_DEF);
11503 }
11504 else
11505 {
11506 thd->get_stmt_da()->clear_warning_info(thd->query_id);
11507 clear_all_errors(thd, const_cast<Relay_log_info*>(rli));
11508 error= 0;
11509 goto end;
11510 }
11511 }
11512 DBUG_PRINT("debug", ("Table: %s.%s is compatible with master"
11513 " - conv_table: %p",
11514 ptr->table->s->db.str,
11515 ptr->table->s->table_name.str, conv_table));
11516 ptr->m_conv_table= conv_table;
11517 }
11518 }
11519
11520 /*
11521 ... and then we add all the tables to the table map and but keep
11522 them in the tables to lock list.
11523
11524 We also invalidate the query cache for all the tables, since
11525 they will now be changed.
11526
11527 TODO [/Matz]: Maybe the query cache should not be invalidated
11528 here? It might be that a table is not changed, even though it
11529 was locked for the statement. We do know that each
11530 Rows_log_event contain at least one row, so after processing one
11531 Rows_log_event, we can invalidate the query cache for the
11532 associated table.
11533 */
11534 TABLE_LIST *ptr= rli->tables_to_lock;
11535 for (uint i=0 ; ptr && (i < rli->tables_to_lock_count); ptr= ptr->next_global, i++)
11536 {
11537 /*
11538 Please see comment in above 'for' loop to know the reason
11539 for this if condition
11540 */
11541 if (ptr->parent_l)
11542 continue;
11543 const_cast<Relay_log_info*>(rli)->m_table_map.set_table(ptr->table_id, ptr->table);
11544 }
11545
11546 #ifdef HAVE_QUERY_CACHE
11547 query_cache.invalidate_locked_for_write(rli->tables_to_lock);
11548 #endif
11549 }
11550
11551 table=
11552 m_table= const_cast<Relay_log_info*>(rli)->m_table_map.get_table(m_table_id);
11553
11554 DBUG_PRINT("debug", ("m_table: 0x%lx, m_table_id: %llu", (ulong) m_table,
11555 m_table_id.id()));
11556
11557 /*
11558 A row event comprising of a P_S table
11559 - should not be replicated (i.e executed) by the slave SQL thread.
11560 - should not be executed by the client in the form BINLOG '...' stmts.
11561 */
11562 if (table && table->s->table_category == TABLE_CATEGORY_PERFORMANCE)
11563 table= NULL;
11564
11565 if (table)
11566 {
11567 /*
11568 table == NULL means that this table should not be replicated
11569 (this was set up by Table_map_log_event::do_apply_event()
11570 which tested replicate-* rules).
11571 */
11572
11573 /*
11574 It's not needed to set_time() but
11575 1) it continues the property that "Time" in SHOW PROCESSLIST shows how
11576 much slave is behind
11577 2) it will be needed when we allow replication from a table with no
11578 TIMESTAMP column to a table with one.
11579 So we call set_time(), like in SBR. Presently it changes nothing.
11580 */
11581 thd->set_time(&when);
11582
11583 thd->binlog_row_event_extra_data = m_extra_row_data;
11584
11585 /*
11586 Now we are in a statement and will stay in a statement until we
11587 see a STMT_END_F.
11588
11589 We set this flag here, before actually applying any rows, in
11590 case the SQL thread is stopped and we need to detect that we're
11591 inside a statement and halting abruptly might cause problems
11592 when restarting.
11593 */
11594 const_cast<Relay_log_info*>(rli)->set_flag(Relay_log_info::IN_STMT);
11595
11596 if ( m_width == table->s->fields && bitmap_is_set_all(&m_cols))
11597 set_flags(COMPLETE_ROWS_F);
11598
11599 /*
11600 Set tables write and read sets.
11601
11602 Read_set contains all slave columns (in case we are going to fetch
11603 a complete record from slave)
11604
11605 Write_set equals the m_cols bitmap sent from master but it can be
11606 longer if slave has extra columns.
11607 */
11608
11609 DBUG_PRINT_BITSET("debug", "Setting table's read_set from: %s", &m_cols);
11610
11611 bitmap_set_all(table->read_set);
11612 if (get_general_type_code() == DELETE_ROWS_EVENT ||
11613 get_general_type_code() == UPDATE_ROWS_EVENT)
11614 bitmap_intersect(table->read_set,&m_cols);
11615
11616 bitmap_set_all(table->write_set);
11617
11618 /* WRITE ROWS EVENTS store the bitmap in m_cols instead of m_cols_ai */
11619 MY_BITMAP *after_image= ((get_general_type_code() == UPDATE_ROWS_EVENT) ?
11620 &m_cols_ai : &m_cols);
11621 bitmap_intersect(table->write_set, after_image);
11622
11623 this->slave_exec_mode= slave_exec_mode_options; // fix the mode
11624
11625 // Do event specific preparations
11626 error= do_before_row_operations(rli);
11627
11628 /*
11629 Bug#56662 Assertion failed: next_insert_id == 0, file handler.cc
11630 Don't allow generation of auto_increment value when processing
11631 rows event by setting 'MODE_NO_AUTO_VALUE_ON_ZERO'. The exception
11632 to this rule happens when the auto_inc column exists on some
11633 extra columns on the slave. In that case, do not force
11634 MODE_NO_AUTO_VALUE_ON_ZERO.
11635 */
11636 ulong saved_sql_mode= thd->variables.sql_mode;
11637 if (!is_auto_inc_in_extra_columns())
11638 thd->variables.sql_mode= MODE_NO_AUTO_VALUE_ON_ZERO;
11639
11640 // row processing loop
11641
11642 /*
11643 set the initial time of this ROWS statement if it was not done
11644 before in some other ROWS event.
11645 */
11646 const_cast<Relay_log_info*>(rli)->set_row_stmt_start_timestamp();
11647
11648 const uchar *saved_m_curr_row= m_curr_row;
11649
11650 int (Rows_log_event::*do_apply_row_ptr)(Relay_log_info const *)= NULL;
11651
11652 /**
11653 Skip update rows events that don't have data for this slave's
11654 table.
11655 */
11656 if ((get_general_type_code() == UPDATE_ROWS_EVENT) &&
11657 !is_any_column_signaled_for_table(table, &m_cols_ai))
11658 goto AFTER_MAIN_EXEC_ROW_LOOP;
11659
11660 /**
11661 If there are no columns marked in the read_set for this table,
11662 that means that we cannot lookup any row using the available BI
11663 in the binarr log. Thence, we immediatly raise an error:
11664 HA_ERR_END_OF_FILE.
11665 */
11666
11667 if ((m_rows_lookup_algorithm != ROW_LOOKUP_NOT_NEEDED) &&
11668 !is_any_column_signaled_for_table(table, &m_cols))
11669 {
11670 error= HA_ERR_END_OF_FILE;
11671 goto AFTER_MAIN_EXEC_ROW_LOOP;
11672 }
11673 switch (m_rows_lookup_algorithm)
11674 {
11675 case ROW_LOOKUP_HASH_SCAN:
11676 do_apply_row_ptr= &Rows_log_event::do_hash_scan_and_update;
11677 break;
11678
11679 case ROW_LOOKUP_INDEX_SCAN:
11680 do_apply_row_ptr= &Rows_log_event::do_index_scan_and_update;
11681 break;
11682
11683 case ROW_LOOKUP_TABLE_SCAN:
11684 do_apply_row_ptr= &Rows_log_event::do_table_scan_and_update;
11685 break;
11686
11687 case ROW_LOOKUP_NOT_NEEDED:
11688 DBUG_ASSERT(get_general_type_code() == WRITE_ROWS_EVENT ||
11689 get_general_type_code() == DELETE_ROWS_EVENT ||
11690 get_general_type_code() == UPDATE_ROWS_EVENT);
11691
11692 /* No need to scan for rows, just apply it */
11693 do_apply_row_ptr= &Rows_log_event::do_apply_row;
11694 break;
11695
11696 default:
11697 DBUG_ASSERT(0);
11698 error= 1;
11699 goto AFTER_MAIN_EXEC_ROW_LOOP;
11700 break;
11701 }
11702
11703 do {
11704
11705 error= (this->*do_apply_row_ptr)(rli);
11706
11707 if (!error)
11708 thd->updated_row_count++;
11709
11710 if (handle_idempotent_and_ignored_errors(rli, &error))
11711 break;
11712
11713 /* this advances m_curr_row */
11714 do_post_row_operations(rli, error);
11715
11716 } while (!error && (m_curr_row != m_rows_end));
11717
11718 if (unlikely(opt_userstat))
11719 {
11720 thd->update_stats(false);
11721 #ifndef EMBEDDED_LIBRARY
11722 update_global_user_stats(thd, true, time(NULL));
11723 #endif
11724 }
11725
11726 AFTER_MAIN_EXEC_ROW_LOOP:
11727
11728 if (saved_m_curr_row != m_curr_row && !table->file->has_transactions())
11729 {
11730 /*
11731 Usually, the trans_commit_stmt() propagates unsafe_rollback_flags
11732 from statement to transaction level. However, we cannot rely on
11733 this when row format is in use as several events can be processed
11734 before calling this function. This happens because it is called
11735 only when the latest event generated by a statement is processed.
11736
11737 There are however upper level functions that execute per event
11738 and check transaction's status. So if the unsafe_rollback_flags
11739 are not propagated here, this can lead to errors.
11740
11741 For example, a transaction that updates non-transactional tables
11742 may be stopped in the middle thus leading to inconsistencies
11743 after a restart.
11744 */
11745 thd->transaction.stmt.mark_modified_non_trans_table();
11746 thd->transaction.merge_unsafe_rollback_flags();
11747 }
11748
11749 /*
11750 Restore the sql_mode after the rows event is processed.
11751 */
11752 thd->variables.sql_mode= saved_sql_mode;
11753
11754 {/*
11755 The following failure injecion works in cooperation with tests
11756 setting @@global.debug= 'd,stop_slave_middle_group'.
11757 The sql thread receives the killed status and will proceed
11758 to shutdown trying to finish incomplete events group.
11759 */
11760 DBUG_EXECUTE_IF("stop_slave_middle_group",
11761 if (thd->transaction.all.cannot_safely_rollback())
11762 const_cast<Relay_log_info*>(rli)->abort_slave= 1;);
11763 }
11764
11765 if ((error= do_after_row_operations(rli, error)) &&
11766 ignored_error_code(convert_handler_error(error, thd, table)))
11767 {
11768
11769 if (log_warnings > 1)
11770 slave_rows_error_report(WARNING_LEVEL, error, rli, thd, table,
11771 get_type_str(),
11772 const_cast<Relay_log_info*>(rli)->get_rpl_log_name(),
11773 (ulong) log_pos);
11774 thd->get_stmt_da()->clear_warning_info(thd->query_id);
11775 clear_all_errors(thd, const_cast<Relay_log_info*>(rli));
11776 error= 0;
11777 }
11778 } // if (table)
11779
11780 if (error)
11781 {
11782 slave_rows_error_report(ERROR_LEVEL, error, rli, thd, table,
11783 get_type_str(),
11784 const_cast<Relay_log_info*>(rli)->get_rpl_log_name(),
11785 (ulong) log_pos);
11786 /*
11787 @todo We should probably not call
11788 reset_current_stmt_binlog_format_row() from here.
11789
11790 Note: this applies to log_event_old.cc too.
11791 /Sven
11792 */
11793 thd->reset_current_stmt_binlog_format_row();
11794 thd->is_slave_error= 1;
11795 DBUG_RETURN(error);
11796 }
11797 end:
11798 if (get_flags(STMT_END_F))
11799 {
11800 if((error= rows_event_stmt_cleanup(rli, thd)))
11801 {
11802 if (table)
11803 slave_rows_error_report(ERROR_LEVEL,
11804 thd->is_error() ? 0 : error,
11805 rli, thd, table,
11806 get_type_str(),
11807 const_cast<Relay_log_info*>(rli)->get_rpl_log_name(),
11808 (ulong) log_pos);
11809 else
11810 {
11811 rli->report(ERROR_LEVEL,
11812 thd->is_error() ? thd->get_stmt_da()->sql_errno() : error,
11813 "Error in cleaning up after an event of type:%s; %s; the group"
11814 " log file/position: %s %lu", get_type_str(),
11815 thd->is_error() ? thd->get_stmt_da()->message() : "unexpected error",
11816 const_cast<Relay_log_info*>(rli)->get_rpl_log_name(),
11817 (ulong) log_pos);
11818 }
11819 }
11820 /* We are at end of the statement (STMT_END_F flag), lets clean
11821 the memory which was used from thd's mem_root now.
11822 This needs to be done only if we are here in SQL thread context.
11823 In other flow ( in case of a regular thread which can happen
11824 when the thread is applying BINLOG'...' row event) we should
11825 *not* try to free the memory here. It will be done latter
11826 in dispatch_command() after command execution is completed.
11827 */
11828 if (thd->slave_thread)
11829 free_root(thd->mem_root, MYF(MY_KEEP_PREALLOC));
11830 }
11831 DBUG_RETURN(error);
11832 }
11833
11834 Log_event::enum_skip_reason
do_shall_skip(Relay_log_info * rli)11835 Rows_log_event::do_shall_skip(Relay_log_info *rli)
11836 {
11837 /*
11838 If the slave skip counter is 1 and this event does not end a
11839 statement, then we should not start executing on the next event.
11840 Otherwise, we defer the decision to the normal skipping logic.
11841 */
11842 if (rli->slave_skip_counter == 1 && !get_flags(STMT_END_F))
11843 return Log_event::EVENT_SKIP_IGNORE;
11844 else
11845 return Log_event::do_shall_skip(rli);
11846 }
11847
11848 /**
11849 The function is called at Rows_log_event statement commit time,
11850 normally from Rows_log_event::do_update_pos() and possibly from
11851 Query_log_event::do_apply_event() of the COMMIT.
11852 The function commits the last statement for engines, binlog and
11853 releases resources have been allocated for the statement.
11854
11855 @retval 0 Ok.
11856 @retval non-zero Error at the commit.
11857 */
11858
rows_event_stmt_cleanup(Relay_log_info const * rli,THD * thd)11859 static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD * thd)
11860 {
11861 DBUG_EXECUTE_IF("simulate_rows_event_cleanup_failure",
11862 {
11863 my_error(ER_ERROR_DURING_COMMIT, MYF(0), 1);
11864 return (1);
11865 });
11866 int error;
11867 {
11868 /*
11869 This is the end of a statement or transaction, so close (and
11870 unlock) the tables we opened when processing the
11871 Table_map_log_event starting the statement.
11872
11873 OBSERVER. This will clear *all* mappings, not only those that
11874 are open for the table. There is not good handle for on-close
11875 actions for tables.
11876
11877 NOTE. Even if we have no table ('table' == 0) we still need to be
11878 here, so that we increase the group relay log position. If we didn't, we
11879 could have a group relay log position which lags behind "forever"
11880 (assume the last master's transaction is ignored by the slave because of
11881 replicate-ignore rules).
11882 */
11883 error= thd->binlog_flush_pending_rows_event(TRUE);
11884
11885 /*
11886 If this event is not in a transaction, the call below will, if some
11887 transactional storage engines are involved, commit the statement into
11888 them and flush the pending event to binlog.
11889 If this event is in a transaction, the call will do nothing, but a
11890 Xid_log_event will come next which will, if some transactional engines
11891 are involved, commit the transaction and flush the pending event to the
11892 binlog.
11893 If there was a deadlock the transaction should have been rolled back
11894 already. So there should be no need to rollback the transaction.
11895 */
11896 DBUG_ASSERT(! thd->transaction_rollback_request);
11897 error|= (error ? trans_rollback_stmt(thd) : trans_commit_stmt(thd));
11898
11899 /*
11900 Now what if this is not a transactional engine? we still need to
11901 flush the pending event to the binlog; we did it with
11902 thd->binlog_flush_pending_rows_event(). Note that we imitate
11903 what is done for real queries: a call to
11904 ha_autocommit_or_rollback() (sometimes only if involves a
11905 transactional engine), and a call to be sure to have the pending
11906 event flushed.
11907 */
11908
11909 /*
11910 @todo We should probably not call
11911 reset_current_stmt_binlog_format_row() from here.
11912
11913 Note: this applies to log_event_old.cc too
11914
11915 Btw, the previous comment about transactional engines does not
11916 seem related to anything that happens here.
11917 /Sven
11918 */
11919 thd->reset_current_stmt_binlog_format_row();
11920
11921 const_cast<Relay_log_info*>(rli)->cleanup_context(thd, 0);
11922
11923 /*
11924 Clean sql_command value
11925 */
11926 thd->lex->sql_command= SQLCOM_END;
11927
11928 }
11929 return error;
11930 }
11931
11932 /**
11933 The method either increments the relay log position or
11934 commits the current statement and increments the master group
11935 possition if the event is STMT_END_F flagged and
11936 the statement corresponds to the autocommit query (i.e replicated
11937 without wrapping in BEGIN/COMMIT)
11938
11939 @retval 0 Success
11940 @retval non-zero Error in the statement commit
11941 */
11942 int
do_update_pos(Relay_log_info * rli)11943 Rows_log_event::do_update_pos(Relay_log_info *rli)
11944 {
11945 DBUG_ENTER("Rows_log_event::do_update_pos");
11946 int error= 0;
11947
11948 DBUG_PRINT("info", ("flags: %s",
11949 get_flags(STMT_END_F) ? "STMT_END_F " : ""));
11950
11951 /* Worker does not execute binlog update position logics */
11952 DBUG_ASSERT(!is_mts_worker(rli->info_thd));
11953
11954 if (get_flags(STMT_END_F))
11955 {
11956 /*
11957 Indicate that a statement is finished.
11958 Step the group log position if we are not in a transaction,
11959 otherwise increase the event log position.
11960 */
11961 error= rli->stmt_done(log_pos);
11962 }
11963 else
11964 {
11965 rli->inc_event_relay_log_pos();
11966 }
11967
11968 DBUG_RETURN(error);
11969 }
11970
11971 #endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */
11972
11973 #ifndef MYSQL_CLIENT
write_data_header(IO_CACHE * file)11974 bool Rows_log_event::write_data_header(IO_CACHE *file)
11975 {
11976 uchar buf[ROWS_HEADER_LEN_V2]; // No need to init the buffer
11977 DBUG_ASSERT(m_table_id.is_valid());
11978 DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master",
11979 {
11980 int4store(buf + 0, (ulong) m_table_id.id());
11981 int2store(buf + 4, m_flags);
11982 return (wrapper_my_b_safe_write(file, buf, 6));
11983 });
11984 int6store(buf + RW_MAPID_OFFSET, m_table_id.id());
11985 int2store(buf + RW_FLAGS_OFFSET, m_flags);
11986 int rc = 0;
11987 if (likely(!log_bin_use_v1_row_events))
11988 {
11989 /*
11990 v2 event, with variable header portion.
11991 Determine length of variable header payload
11992 */
11993 uint16 vhlen= 2;
11994 uint16 vhpayloadlen= 0;
11995 uint16 extra_data_len= 0;
11996 if (m_extra_row_data)
11997 {
11998 extra_data_len= m_extra_row_data[EXTRA_ROW_INFO_LEN_OFFSET];
11999 vhpayloadlen= RW_V_TAG_LEN + extra_data_len;
12000 }
12001
12002 /* Var-size header len includes len itself */
12003 int2store(buf + RW_VHLEN_OFFSET, vhlen + vhpayloadlen);
12004 rc= wrapper_my_b_safe_write(file, buf, ROWS_HEADER_LEN_V2);
12005
12006 /* Write var-sized payload, if any */
12007 if ((vhpayloadlen > 0) &&
12008 (rc == 0))
12009 {
12010 /* Add tag and extra row info */
12011 uchar type_code= RW_V_EXTRAINFO_TAG;
12012 rc= wrapper_my_b_safe_write(file, &type_code, RW_V_TAG_LEN);
12013 if (rc==0)
12014 rc= wrapper_my_b_safe_write(file, m_extra_row_data, extra_data_len);
12015 }
12016 }
12017 else
12018 {
12019 rc= wrapper_my_b_safe_write(file, buf, ROWS_HEADER_LEN_V1);
12020 }
12021
12022 return (rc != 0);
12023 }
12024
write_data_body(IO_CACHE * file)12025 bool Rows_log_event::write_data_body(IO_CACHE*file)
12026 {
12027 /*
12028 Note that this should be the number of *bits*, not the number of
12029 bytes.
12030 */
12031 uchar sbuf[sizeof(m_width) + 1];
12032 my_ptrdiff_t const data_size= m_rows_cur - m_rows_buf;
12033 bool res= false;
12034 uchar *const sbuf_end= net_store_length(sbuf, (size_t) m_width);
12035 DBUG_ASSERT(static_cast<size_t>(sbuf_end - sbuf) <= sizeof(sbuf));
12036
12037 DBUG_DUMP("m_width", sbuf, (size_t) (sbuf_end - sbuf));
12038 res= res || wrapper_my_b_safe_write(file, sbuf, (size_t) (sbuf_end - sbuf));
12039
12040 DBUG_DUMP("m_cols", (uchar*) m_cols.bitmap, no_bytes_in_map(&m_cols));
12041 res= res || wrapper_my_b_safe_write(file, (uchar*) m_cols.bitmap,
12042 no_bytes_in_map(&m_cols));
12043 /*
12044 TODO[refactor write]: Remove the "down cast" here (and elsewhere).
12045 */
12046 if (get_general_type_code() == UPDATE_ROWS_EVENT)
12047 {
12048 DBUG_DUMP("m_cols_ai", (uchar*) m_cols_ai.bitmap,
12049 no_bytes_in_map(&m_cols_ai));
12050 res= res || wrapper_my_b_safe_write(file, (uchar*) m_cols_ai.bitmap,
12051 no_bytes_in_map(&m_cols_ai));
12052 }
12053 DBUG_DUMP("rows", m_rows_buf, data_size);
12054 res= res || wrapper_my_b_safe_write(file, m_rows_buf, (size_t) data_size);
12055
12056 return res;
12057
12058 }
12059 #endif
12060
12061 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
pack_info(Protocol * protocol)12062 int Rows_log_event::pack_info(Protocol *protocol)
12063 {
12064 char buf[256];
12065 char const *const flagstr=
12066 get_flags(STMT_END_F) ? " flags: STMT_END_F" : "";
12067 size_t bytes= my_snprintf(buf, sizeof(buf),
12068 "table_id: %llu%s", m_table_id.id(), flagstr);
12069 protocol->store(buf, bytes, &my_charset_bin);
12070 return 0;
12071 }
12072 #endif
12073
12074 #ifdef MYSQL_CLIENT
print_helper(FILE * file,PRINT_EVENT_INFO * print_event_info,char const * const name)12075 void Rows_log_event::print_helper(FILE *file,
12076 PRINT_EVENT_INFO *print_event_info,
12077 char const *const name)
12078 {
12079 IO_CACHE *const head= &print_event_info->head_cache;
12080 IO_CACHE *const body= &print_event_info->body_cache;
12081 if (!print_event_info->short_form)
12082 {
12083 bool const last_stmt_event= get_flags(STMT_END_F);
12084 print_header(head, print_event_info, !last_stmt_event);
12085 my_b_printf(head, "\t%s: table id %llu%s\n",
12086 name, m_table_id.id(),
12087 last_stmt_event ? " flags: STMT_END_F" : "");
12088 print_base64(body, print_event_info, !last_stmt_event);
12089 }
12090 }
12091 #endif
12092
12093 /**************************************************************************
12094 Table_map_log_event member functions and support functions
12095 **************************************************************************/
12096
12097 /**
12098 @page How replication of field metadata works.
12099
12100 When a table map is created, the master first calls
12101 Table_map_log_event::save_field_metadata() which calculates how many
12102 values will be in the field metadata. Only those fields that require the
12103 extra data are added. The method also loops through all of the fields in
12104 the table calling the method Field::save_field_metadata() which returns the
12105 values for the field that will be saved in the metadata and replicated to
12106 the slave. Once all fields have been processed, the table map is written to
12107 the binlog adding the size of the field metadata and the field metadata to
12108 the end of the body of the table map.
12109
12110 When a table map is read on the slave, the field metadata is read from the
12111 table map and passed to the table_def class constructor which saves the
12112 field metadata from the table map into an array based on the type of the
12113 field. Field metadata values not present (those fields that do not use extra
12114 data) in the table map are initialized as zero (0). The array size is the
12115 same as the columns for the table on the slave.
12116
12117 Additionally, values saved for field metadata on the master are saved as a
12118 string of bytes (uchar) in the binlog. A field may require 1 or more bytes
12119 to store the information. In cases where values require multiple bytes
12120 (e.g. values > 255), the endian-safe methods are used to properly encode
12121 the values on the master and decode them on the slave. When the field
12122 metadata values are captured on the slave, they are stored in an array of
12123 type uint16. This allows the least number of casts to prevent casting bugs
12124 when the field metadata is used in comparisons of field attributes. When
12125 the field metadata is used for calculating addresses in pointer math, the
12126 type used is uint32.
12127 */
12128
12129 #if !defined(MYSQL_CLIENT)
12130 /**
12131 Save the field metadata based on the real_type of the field.
12132 The metadata saved depends on the type of the field. Some fields
12133 store a single byte for pack_length() while others store two bytes
12134 for field_length (max length).
12135
12136 @retval 0 Ok.
12137
12138 @todo
12139 We may want to consider changing the encoding of the information.
12140 Currently, the code attempts to minimize the number of bytes written to
12141 the tablemap. There are at least two other alternatives; 1) using
12142 net_store_length() to store the data allowing it to choose the number of
12143 bytes that are appropriate thereby making the code much easier to
12144 maintain (only 1 place to change the encoding), or 2) use a fixed number
12145 of bytes for each field. The problem with option 1 is that net_store_length()
12146 will use one byte if the value < 251, but 3 bytes if it is > 250. Thus,
12147 for fields like CHAR which can be no larger than 255 characters, the method
12148 will use 3 bytes when the value is > 250. Further, every value that is
12149 encoded using 2 parts (e.g., pack_length, field_length) will be numerically
12150 > 250 therefore will use 3 bytes for eah value. The problem with option 2
12151 is less wasteful for space but does waste 1 byte for every field that does
12152 not encode 2 parts.
12153 */
save_field_metadata()12154 int Table_map_log_event::save_field_metadata()
12155 {
12156 DBUG_ENTER("Table_map_log_event::save_field_metadata");
12157 int index= 0;
12158 for (unsigned int i= 0 ; i < m_table->s->fields ; i++)
12159 {
12160 DBUG_PRINT("debug", ("field_type: %d", m_coltype[i]));
12161 index+= m_table->s->field[i]->save_field_metadata(&m_field_metadata[index]);
12162 }
12163 DBUG_RETURN(index);
12164 }
12165 #endif /* !defined(MYSQL_CLIENT) */
12166
12167 /*
12168 Constructor used to build an event for writing to the binary log.
12169 Mats says tbl->s lives longer than this event so it's ok to copy pointers
12170 (tbl->s->db etc) and not pointer content.
12171 */
12172 #if !defined(MYSQL_CLIENT)
Table_map_log_event(THD * thd,TABLE * tbl,const Table_id & tid,bool using_trans)12173 Table_map_log_event::Table_map_log_event(THD *thd, TABLE *tbl,
12174 const Table_id& tid,
12175 bool using_trans)
12176 : Log_event(thd, 0,
12177 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
12178 Log_event::EVENT_STMT_CACHE,
12179 Log_event::EVENT_NORMAL_LOGGING),
12180 m_table(tbl),
12181 m_dbnam(tbl->s->db.str),
12182 m_dblen(m_dbnam ? tbl->s->db.length : 0),
12183 m_tblnam(tbl->s->table_name.str),
12184 m_tbllen(tbl->s->table_name.length),
12185 m_colcnt(tbl->s->fields),
12186 m_memory(NULL),
12187 m_table_id(tid),
12188 m_flags(TM_BIT_LEN_EXACT_F),
12189 m_data_size(0),
12190 m_field_metadata(0),
12191 m_field_metadata_size(0),
12192 m_null_bits(0),
12193 m_meta_memory(NULL)
12194 {
12195 uchar cbuf[sizeof(m_colcnt) + 1];
12196 uchar *cbuf_end;
12197 DBUG_ASSERT(m_table_id.is_valid());
12198 /*
12199 In TABLE_SHARE, "db" and "table_name" are 0-terminated (see this comment in
12200 table.cc / alloc_table_share():
12201 Use the fact the key is db/0/table_name/0
12202 As we rely on this let's assert it.
12203 */
12204 DBUG_ASSERT((tbl->s->db.str == 0) ||
12205 (tbl->s->db.str[tbl->s->db.length] == 0));
12206 DBUG_ASSERT(tbl->s->table_name.str[tbl->s->table_name.length] == 0);
12207
12208
12209 m_data_size= TABLE_MAP_HEADER_LEN;
12210 DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master", m_data_size= 6;);
12211 m_data_size+= m_dblen + 2; // Include length and terminating \0
12212 m_data_size+= m_tbllen + 2; // Include length and terminating \0
12213 cbuf_end= net_store_length(cbuf, (size_t) m_colcnt);
12214 DBUG_ASSERT(static_cast<size_t>(cbuf_end - cbuf) <= sizeof(cbuf));
12215 m_data_size+= (cbuf_end - cbuf) + m_colcnt; // COLCNT and column types
12216
12217 /* If malloc fails, caught in is_valid() */
12218 if ((m_memory= (uchar*) my_malloc(m_colcnt, MYF(MY_WME))))
12219 {
12220 m_coltype= reinterpret_cast<uchar*>(m_memory);
12221 for (unsigned int i= 0 ; i < m_table->s->fields ; ++i)
12222 m_coltype[i]= m_table->field[i]->binlog_type();
12223 }
12224
12225 /*
12226 Calculate a bitmap for the results of maybe_null() for all columns.
12227 The bitmap is used to determine when there is a column from the master
12228 that is not on the slave and is null and thus not in the row data during
12229 replication.
12230 */
12231 uint num_null_bytes= (m_table->s->fields + 7) / 8;
12232 m_data_size+= num_null_bytes;
12233 m_meta_memory= (uchar *)my_multi_malloc(MYF(MY_WME),
12234 &m_null_bits, num_null_bytes,
12235 &m_field_metadata, (m_colcnt * 2),
12236 NULL);
12237
12238 memset(m_field_metadata, 0, (m_colcnt * 2));
12239
12240 /*
12241 Create an array for the field metadata and store it.
12242 */
12243 m_field_metadata_size= save_field_metadata();
12244 DBUG_ASSERT(m_field_metadata_size <= (m_colcnt * 2));
12245
12246 /*
12247 Now set the size of the data to the size of the field metadata array
12248 plus one or three bytes (see pack.c:net_store_length) for number of
12249 elements in the field metadata array.
12250 */
12251 if (m_field_metadata_size < 251)
12252 m_data_size+= m_field_metadata_size + 1;
12253 else
12254 m_data_size+= m_field_metadata_size + 3;
12255
12256 memset(m_null_bits, 0, num_null_bytes);
12257 for (unsigned int i= 0 ; i < m_table->s->fields ; ++i)
12258 if (m_table->field[i]->maybe_null())
12259 m_null_bits[(i / 8)]+= 1 << (i % 8);
12260 /*
12261 Marking event to require sequential execution in MTS
12262 if the query might have updated FK-referenced db.
12263 Unlike Query_log_event where this fact is encoded through
12264 the accessed db list in the Table_map case m_flags is exploited.
12265 */
12266 uchar dbs= thd->get_binlog_accessed_db_names() ?
12267 thd->get_binlog_accessed_db_names()->elements : 0;
12268 if (dbs == 1)
12269 {
12270 char *db_name= thd->get_binlog_accessed_db_names()->head();
12271 if (!strcmp(db_name, ""))
12272 m_flags |= TM_REFERRED_FK_DB_F;
12273 }
12274 }
12275 #endif /* !defined(MYSQL_CLIENT) */
12276
12277 /*
12278 Constructor used by slave to read the event from the binary log.
12279 */
12280 #if defined(HAVE_REPLICATION)
Table_map_log_event(const char * buf,uint event_len,const Format_description_log_event * description_event)12281 Table_map_log_event::Table_map_log_event(const char *buf, uint event_len,
12282 const Format_description_log_event
12283 *description_event)
12284
12285 : Log_event(buf, description_event),
12286 #ifndef MYSQL_CLIENT
12287 m_table(NULL),
12288 #endif
12289 m_dbnam(NULL), m_dblen(0), m_tblnam(NULL), m_tbllen(0),
12290 m_colcnt(0), m_coltype(0),
12291 m_memory(NULL), m_table_id(ULONGLONG_MAX), m_flags(0),
12292 m_data_size(0), m_field_metadata(0), m_field_metadata_size(0),
12293 m_null_bits(0), m_meta_memory(NULL)
12294 {
12295 unsigned int bytes_read= 0;
12296 DBUG_ENTER("Table_map_log_event::Table_map_log_event(const char*,uint,...)");
12297
12298 uint8 common_header_len= description_event->common_header_len;
12299 uint8 post_header_len= description_event->post_header_len[TABLE_MAP_EVENT-1];
12300 DBUG_PRINT("info",("event_len: %u common_header_len: %d post_header_len: %d",
12301 event_len, common_header_len, post_header_len));
12302
12303 /*
12304 Don't print debug messages when running valgrind since they can
12305 trigger false warnings.
12306 */
12307 #ifndef HAVE_purify
12308 DBUG_DUMP("event buffer", (uchar*) buf, event_len);
12309 #endif
12310
12311 /* Read the post-header */
12312 const char *post_start= buf + common_header_len;
12313
12314 post_start+= TM_MAPID_OFFSET;
12315 if (post_header_len == 6)
12316 {
12317 /* Master is of an intermediate source tree before 5.1.4. Id is 4 bytes */
12318 m_table_id= uint4korr(post_start);
12319 post_start+= 4;
12320 }
12321 else
12322 {
12323 DBUG_ASSERT(post_header_len == TABLE_MAP_HEADER_LEN);
12324 m_table_id= uint6korr(post_start);
12325 post_start+= TM_FLAGS_OFFSET;
12326 }
12327
12328 m_flags= uint2korr(post_start);
12329
12330 /* Read the variable part of the event */
12331 const char *const vpart= buf + common_header_len + post_header_len;
12332
12333 /* Extract the length of the various parts from the buffer */
12334 uchar const *const ptr_dblen= (uchar const*)vpart + 0;
12335 m_dblen= *(uchar*) ptr_dblen;
12336
12337 /* Length of database name + counter + terminating null */
12338 uchar const *const ptr_tbllen= ptr_dblen + m_dblen + 2;
12339 m_tbllen= *(uchar*) ptr_tbllen;
12340
12341 /* Length of table name + counter + terminating null */
12342 uchar const *const ptr_colcnt= ptr_tbllen + m_tbllen + 2;
12343 uchar *ptr_after_colcnt= (uchar*) ptr_colcnt;
12344 m_colcnt= net_field_length(&ptr_after_colcnt);
12345
12346 DBUG_PRINT("info",("m_dblen: %lu off: %ld m_tbllen: %lu off: %ld m_colcnt: %lu off: %ld",
12347 (ulong) m_dblen, (long) (ptr_dblen-(const uchar*)vpart),
12348 (ulong) m_tbllen, (long) (ptr_tbllen-(const uchar*)vpart),
12349 m_colcnt, (long) (ptr_colcnt-(const uchar*)vpart)));
12350
12351 bytes_read= (unsigned int) (ptr_after_colcnt - (unsigned char *)buf);
12352 /* Avoid reading out of buffer */
12353 if (event_len <= bytes_read || event_len - bytes_read < m_colcnt)
12354 {
12355 m_coltype= NULL;
12356 m_memory= NULL;
12357 DBUG_VOID_RETURN;
12358 }
12359
12360 /* Allocate mem for all fields in one go. If fails, caught in is_valid() */
12361 m_memory= (uchar*) my_multi_malloc(MYF(MY_WME),
12362 &m_dbnam, (uint) m_dblen + 1,
12363 &m_tblnam, (uint) m_tbllen + 1,
12364 &m_coltype, (uint) m_colcnt,
12365 NullS);
12366
12367 if (m_memory)
12368 {
12369 /* Copy the different parts into their memory */
12370 strncpy(const_cast<char*>(m_dbnam), (const char*)ptr_dblen + 1, m_dblen + 1);
12371 strncpy(const_cast<char*>(m_tblnam), (const char*)ptr_tbllen + 1, m_tbllen + 1);
12372 memcpy(m_coltype, ptr_after_colcnt, m_colcnt);
12373
12374 ptr_after_colcnt= ptr_after_colcnt + m_colcnt;
12375 bytes_read= (uint) (ptr_after_colcnt - (uchar *)buf);
12376 DBUG_PRINT("info", ("Bytes read: %d.\n", bytes_read));
12377 if (bytes_read < event_len)
12378 {
12379 m_field_metadata_size= net_field_length(&ptr_after_colcnt);
12380 if (m_field_metadata_size <= (m_colcnt * 2))
12381 {
12382 uint num_null_bytes= (m_colcnt + 7) / 8;
12383 m_meta_memory= (uchar *)my_multi_malloc(MYF(MY_WME),
12384 &m_null_bits, num_null_bytes,
12385 &m_field_metadata, m_field_metadata_size,
12386 NULL);
12387 memcpy(m_field_metadata, ptr_after_colcnt, m_field_metadata_size);
12388 ptr_after_colcnt= (uchar*)ptr_after_colcnt + m_field_metadata_size;
12389 memcpy(m_null_bits, ptr_after_colcnt, num_null_bytes);
12390 }
12391 else
12392 {
12393 m_coltype= NULL;
12394 my_free(m_memory);
12395 m_memory= NULL;
12396 DBUG_VOID_RETURN;
12397 }
12398 }
12399 }
12400
12401 DBUG_VOID_RETURN;
12402 }
12403 #endif
12404
~Table_map_log_event()12405 Table_map_log_event::~Table_map_log_event()
12406 {
12407 if (m_meta_memory != NULL)
12408 my_free(m_meta_memory);
12409 if (m_memory != NULL)
12410 my_free(m_memory);
12411 }
12412
12413 #ifdef MYSQL_CLIENT
12414
12415 /*
12416 Rewrite database name for the event to name specified by new_db
12417 SYNOPSIS
12418 new_db Database name to change to
12419 new_len Length
12420 desc Event describing binlog that we're writing to.
12421
12422 DESCRIPTION
12423 Reset db name. This function assumes that temp_buf member contains event
12424 representation taken from a binary log. It resets m_dbnam and m_dblen and
12425 rewrites temp_buf with new db name.
12426
12427 RETURN
12428 0 - Success
12429 other - Error
12430 */
12431
rewrite_db(const char * new_db,size_t new_len,const Format_description_log_event * desc)12432 int Table_map_log_event::rewrite_db(const char* new_db, size_t new_len,
12433 const Format_description_log_event* desc)
12434 {
12435 DBUG_ENTER("Table_map_log_event::rewrite_db");
12436 DBUG_ASSERT(temp_buf);
12437
12438 uint header_len= min((unsigned)desc->common_header_len,
12439 (unsigned)LOG_EVENT_MINIMAL_HEADER_LEN) + TABLE_MAP_HEADER_LEN;
12440 int len_diff;
12441
12442 if (!(len_diff= new_len - m_dblen))
12443 {
12444 memcpy((void*) (temp_buf + header_len + 1), new_db, m_dblen + 1);
12445 memcpy((void*) m_dbnam, new_db, m_dblen + 1);
12446 DBUG_RETURN(0);
12447 }
12448
12449 // Create new temp_buf
12450 ulong event_cur_len= uint4korr(temp_buf + EVENT_LEN_OFFSET);
12451 ulong event_new_len= event_cur_len + len_diff;
12452 char* new_temp_buf= (char*) my_malloc(event_new_len, MYF(MY_WME));
12453
12454 if (!new_temp_buf)
12455 {
12456 sql_print_error("Table_map_log_event::rewrite_db: "
12457 "failed to allocate new temp_buf (%d bytes required)",
12458 event_new_len);
12459 DBUG_RETURN(-1);
12460 }
12461
12462 // Rewrite temp_buf
12463 char* ptr= new_temp_buf;
12464 ulong cnt= 0;
12465
12466 // Copy header and change event length
12467 memcpy(ptr, temp_buf, header_len);
12468 int4store(ptr + EVENT_LEN_OFFSET, event_new_len);
12469 ptr += header_len;
12470 cnt += header_len;
12471
12472 // Write new db name length and new name
12473 *ptr++ = new_len;
12474 memcpy(ptr, new_db, new_len + 1);
12475 ptr += new_len + 1;
12476 cnt += m_dblen + 2;
12477
12478 // Copy rest part
12479 memcpy(ptr, temp_buf + cnt, event_cur_len - cnt);
12480
12481 // Reregister temp buf
12482 free_temp_buf();
12483 register_temp_buf(new_temp_buf);
12484
12485 // Reset m_dbnam and m_dblen members
12486 m_dblen= new_len;
12487
12488 // m_dbnam resides in m_memory together with m_tblnam and m_coltype
12489 uchar* memory= m_memory;
12490 char const* tblnam= m_tblnam;
12491 uchar* coltype= m_coltype;
12492
12493 m_memory= (uchar*) my_multi_malloc(MYF(MY_WME),
12494 &m_dbnam, (uint) m_dblen + 1,
12495 &m_tblnam, (uint) m_tbllen + 1,
12496 &m_coltype, (uint) m_colcnt,
12497 NullS);
12498
12499 if (!m_memory)
12500 {
12501 sql_print_error("Table_map_log_event::rewrite_db: "
12502 "failed to allocate new m_memory (%d + %d + %d bytes required)",
12503 m_dblen + 1, m_tbllen + 1, m_colcnt);
12504 DBUG_RETURN(-1);
12505 }
12506
12507 memcpy((void*)m_dbnam, new_db, m_dblen + 1);
12508 memcpy((void*)m_tblnam, tblnam, m_tbllen + 1);
12509 memcpy(m_coltype, coltype, m_colcnt);
12510
12511 my_free(memory);
12512 DBUG_RETURN(0);
12513 }
12514 #endif /* MYSQL_CLIENT */
12515 /*
12516 Return value is an error code, one of:
12517
12518 -1 Failure to open table [from open_tables()]
12519 0 Success
12520 1 No room for more tables [from set_table()]
12521 2 Out of memory [from set_table()]
12522 3 Wrong table definition
12523 4 Daisy-chaining RBR with SBR not possible
12524 */
12525
12526 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
12527
12528 enum enum_tbl_map_status
12529 {
12530 /* no duplicate identifier found */
12531 OK_TO_PROCESS= 0,
12532
12533 /* this table map must be filtered out */
12534 FILTERED_OUT= 1,
12535
12536 /* identifier mapping table with different properties */
12537 SAME_ID_MAPPING_DIFFERENT_TABLE= 2,
12538
12539 /* a duplicate identifier was found mapping the same table */
12540 SAME_ID_MAPPING_SAME_TABLE= 3
12541 };
12542
12543 /*
12544 Checks if this table map event should be processed or not. First
12545 it checks the filtering rules, and then looks for duplicate identifiers
12546 in the existing list of rli->tables_to_lock.
12547
12548 It checks that there hasn't been any corruption by verifying that there
12549 are no duplicate entries with different properties.
12550
12551 In some cases, some binary logs could get corrupted, showing several
12552 tables mapped to the same table_id, 0 (see: BUG#56226). Thus we do this
12553 early sanity check for such cases and avoid that the server crashes
12554 later.
12555
12556 In some corner cases, the master logs duplicate table map events, i.e.,
12557 same id, same database name, same table name (see: BUG#37137). This is
12558 different from the above as it's the same table that is mapped again
12559 to the same identifier. Thus we cannot just check for same ids and
12560 assume that the event is corrupted we need to check every property.
12561
12562 NOTE: in the event that BUG#37137 ever gets fixed, this extra check
12563 will still be valid because we would need to support old binary
12564 logs anyway.
12565
12566 @param rli The relay log info reference.
12567 @param table_list A list element containing the table to check against.
12568 @return OK_TO_PROCESS
12569 if there was no identifier already in rli->tables_to_lock
12570
12571 FILTERED_OUT
12572 if the event is filtered according to the filtering rules
12573
12574 SAME_ID_MAPPING_DIFFERENT_TABLE
12575 if the same identifier already maps a different table in
12576 rli->tables_to_lock
12577
12578 SAME_ID_MAPPING_SAME_TABLE
12579 if the same identifier already maps the same table in
12580 rli->tables_to_lock.
12581 */
12582 static enum_tbl_map_status
check_table_map(Relay_log_info const * rli,RPL_TABLE_LIST * table_list)12583 check_table_map(Relay_log_info const *rli, RPL_TABLE_LIST *table_list)
12584 {
12585 DBUG_ENTER("check_table_map");
12586 enum_tbl_map_status res= OK_TO_PROCESS;
12587
12588 if (rli->info_thd->slave_thread /* filtering is for slave only */ &&
12589 (!rpl_filter->db_ok(table_list->db) ||
12590 (rpl_filter->is_on() && !rpl_filter->tables_ok("", table_list))))
12591 res= FILTERED_OUT;
12592 else
12593 {
12594 RPL_TABLE_LIST *ptr= static_cast<RPL_TABLE_LIST*>(rli->tables_to_lock);
12595 for(uint i=0 ; ptr && (i< rli->tables_to_lock_count);
12596 ptr= static_cast<RPL_TABLE_LIST*>(ptr->next_local), i++)
12597 {
12598 if (ptr->table_id == table_list->table_id)
12599 {
12600
12601 if (strcmp(ptr->db, table_list->db) ||
12602 strcmp(ptr->alias, table_list->table_name) ||
12603 ptr->lock_type != TL_WRITE) // the ::do_apply_event always sets TL_WRITE
12604 res= SAME_ID_MAPPING_DIFFERENT_TABLE;
12605 else
12606 res= SAME_ID_MAPPING_SAME_TABLE;
12607
12608 break;
12609 }
12610 }
12611 }
12612
12613 DBUG_PRINT("debug", ("check of table map ended up with: %u", res));
12614
12615 DBUG_RETURN(res);
12616 }
12617
do_apply_event(Relay_log_info const * rli)12618 int Table_map_log_event::do_apply_event(Relay_log_info const *rli)
12619 {
12620 RPL_TABLE_LIST *table_list;
12621 char *db_mem, *tname_mem, *ptr;
12622 size_t dummy_len;
12623 void *memory;
12624 DBUG_ENTER("Table_map_log_event::do_apply_event(Relay_log_info*)");
12625 DBUG_ASSERT(rli->info_thd == thd);
12626
12627 /* Step the query id to mark what columns that are actually used. */
12628 thd->set_query_id(next_query_id());
12629
12630 if (!(memory= my_multi_malloc(MYF(MY_WME),
12631 &table_list, (uint) sizeof(RPL_TABLE_LIST),
12632 &db_mem, (uint) NAME_LEN + 1,
12633 &tname_mem, (uint) NAME_LEN + 1,
12634 NullS)))
12635 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
12636
12637 strmov(db_mem, m_dbnam);
12638 strmov(tname_mem, m_tblnam);
12639
12640 if (lower_case_table_names == 1)
12641 {
12642 my_casedn_str(system_charset_info, db_mem);
12643 my_casedn_str(system_charset_info, tname_mem);
12644 }
12645
12646 /* rewrite rules changed the database */
12647 if (((ptr= (char*) rpl_filter->get_rewrite_db(db_mem, &dummy_len)) != db_mem))
12648 strmov(db_mem, ptr);
12649
12650 table_list->init_one_table(db_mem, strlen(db_mem),
12651 tname_mem, strlen(tname_mem),
12652 tname_mem, TL_WRITE);
12653
12654 table_list->table_id=
12655 DBUG_EVALUATE_IF("inject_tblmap_same_id_maps_diff_table", 0, m_table_id.id());
12656 table_list->updating= 1;
12657 table_list->required_type= FRMTYPE_TABLE;
12658 DBUG_PRINT("debug", ("table: %s is mapped to %llu", table_list->table_name,
12659 table_list->table_id.id()));
12660
12661 enum_tbl_map_status tblmap_status= check_table_map(rli, table_list);
12662 if (tblmap_status == OK_TO_PROCESS)
12663 {
12664 DBUG_ASSERT(thd->lex->query_tables != table_list);
12665
12666 /*
12667 Use placement new to construct the table_def instance in the
12668 memory allocated for it inside table_list.
12669
12670 The memory allocated by the table_def structure (i.e., not the
12671 memory allocated *for* the table_def structure) is released
12672 inside Relay_log_info::clear_tables_to_lock() by calling the
12673 table_def destructor explicitly.
12674 */
12675 new (&table_list->m_tabledef)
12676 table_def(m_coltype, m_colcnt,
12677 m_field_metadata, m_field_metadata_size,
12678 m_null_bits, m_flags);
12679 table_list->m_tabledef_valid= TRUE;
12680 table_list->m_conv_table= NULL;
12681 table_list->open_type= OT_BASE_ONLY;
12682
12683 /*
12684 We record in the slave's information that the table should be
12685 locked by linking the table into the list of tables to lock.
12686 */
12687 table_list->next_global= table_list->next_local= rli->tables_to_lock;
12688 const_cast<Relay_log_info*>(rli)->tables_to_lock= table_list;
12689 const_cast<Relay_log_info*>(rli)->tables_to_lock_count++;
12690 /* 'memory' is freed in clear_tables_to_lock */
12691 }
12692 else // FILTERED_OUT, SAME_ID_MAPPING_*
12693 {
12694 /*
12695 If mapped already but with different properties, we raise an
12696 error.
12697 If mapped already but with same properties we skip the event.
12698 If filtered out we skip the event.
12699
12700 In all three cases, we need to free the memory previously
12701 allocated.
12702 */
12703 if (tblmap_status == SAME_ID_MAPPING_DIFFERENT_TABLE)
12704 {
12705 /*
12706 Something bad has happened. We need to stop the slave as strange things
12707 could happen if we proceed: slave crash, wrong table being updated, ...
12708 As a consequence we push an error in this case.
12709 */
12710
12711 char buf[256];
12712
12713 my_snprintf(buf, sizeof(buf),
12714 "Found table map event mapping table id %llu which "
12715 "was already mapped but with different settings.",
12716 table_list->table_id.id());
12717
12718 if (thd->slave_thread)
12719 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
12720 ER(ER_SLAVE_FATAL_ERROR), buf);
12721 else
12722 /*
12723 For the cases in which a 'BINLOG' statement is set to
12724 execute in a user session
12725 */
12726 my_printf_error(ER_SLAVE_FATAL_ERROR, ER(ER_SLAVE_FATAL_ERROR),
12727 MYF(0), buf);
12728 }
12729
12730 my_free(memory);
12731 }
12732
12733 DBUG_RETURN(tblmap_status == SAME_ID_MAPPING_DIFFERENT_TABLE);
12734 }
12735
12736 Log_event::enum_skip_reason
do_shall_skip(Relay_log_info * rli)12737 Table_map_log_event::do_shall_skip(Relay_log_info *rli)
12738 {
12739 /*
12740 If the slave skip counter is 1, then we should not start executing
12741 on the next event.
12742 */
12743 return continue_group(rli);
12744 }
12745
do_update_pos(Relay_log_info * rli)12746 int Table_map_log_event::do_update_pos(Relay_log_info *rli)
12747 {
12748 rli->inc_event_relay_log_pos();
12749 return 0;
12750 }
12751
12752 #endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */
12753
12754 #ifndef MYSQL_CLIENT
write_data_header(IO_CACHE * file)12755 bool Table_map_log_event::write_data_header(IO_CACHE *file)
12756 {
12757 DBUG_ASSERT(m_table_id.is_valid());
12758 uchar buf[TABLE_MAP_HEADER_LEN];
12759 DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master",
12760 {
12761 int4store(buf + 0, m_table_id.id());
12762 int2store(buf + 4, m_flags);
12763 return (wrapper_my_b_safe_write(file, buf, 6));
12764 });
12765 int6store(buf + TM_MAPID_OFFSET, m_table_id.id());
12766 int2store(buf + TM_FLAGS_OFFSET, m_flags);
12767 return (wrapper_my_b_safe_write(file, buf, TABLE_MAP_HEADER_LEN));
12768 }
12769
write_data_body(IO_CACHE * file)12770 bool Table_map_log_event::write_data_body(IO_CACHE *file)
12771 {
12772 DBUG_ASSERT(m_dbnam != NULL);
12773 DBUG_ASSERT(m_tblnam != NULL);
12774 /* We use only one byte per length for storage in event: */
12775 DBUG_ASSERT(m_dblen < 128);
12776 DBUG_ASSERT(m_tbllen < 128);
12777
12778 uchar const dbuf[]= { (uchar) m_dblen };
12779 uchar const tbuf[]= { (uchar) m_tbllen };
12780
12781 uchar cbuf[sizeof(m_colcnt) + 1];
12782 uchar *const cbuf_end= net_store_length(cbuf, (size_t) m_colcnt);
12783 DBUG_ASSERT(static_cast<size_t>(cbuf_end - cbuf) <= sizeof(cbuf));
12784
12785 /*
12786 Store the size of the field metadata.
12787 */
12788 uchar mbuf[sizeof(m_field_metadata_size)];
12789 uchar *const mbuf_end= net_store_length(mbuf, m_field_metadata_size);
12790
12791 return (wrapper_my_b_safe_write(file, dbuf, sizeof(dbuf)) ||
12792 wrapper_my_b_safe_write(file, (const uchar*)m_dbnam, m_dblen+1) ||
12793 wrapper_my_b_safe_write(file, tbuf, sizeof(tbuf)) ||
12794 wrapper_my_b_safe_write(file, (const uchar*)m_tblnam, m_tbllen+1) ||
12795 wrapper_my_b_safe_write(file, cbuf, (size_t) (cbuf_end - cbuf)) ||
12796 wrapper_my_b_safe_write(file, m_coltype, m_colcnt) ||
12797 wrapper_my_b_safe_write(file, mbuf, (size_t) (mbuf_end - mbuf)) ||
12798 wrapper_my_b_safe_write(file, m_field_metadata, m_field_metadata_size),
12799 wrapper_my_b_safe_write(file, m_null_bits, (m_colcnt + 7) / 8));
12800 }
12801 #endif
12802
12803 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
12804
12805 /*
12806 Print some useful information for the SHOW BINARY LOG information
12807 field.
12808 */
12809
12810 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
pack_info(Protocol * protocol)12811 int Table_map_log_event::pack_info(Protocol *protocol)
12812 {
12813 char buf[256];
12814 size_t bytes= my_snprintf(buf, sizeof(buf),
12815 "table_id: %llu (%s.%s)",
12816 m_table_id.id(), m_dbnam, m_tblnam);
12817 protocol->store(buf, bytes, &my_charset_bin);
12818 return 0;
12819 }
12820 #endif
12821
12822
12823 #endif
12824
12825
12826 #ifdef MYSQL_CLIENT
print(FILE *,PRINT_EVENT_INFO * print_event_info)12827 void Table_map_log_event::print(FILE *, PRINT_EVENT_INFO *print_event_info)
12828 {
12829 if (!print_event_info->short_form)
12830 {
12831 print_header(&print_event_info->head_cache, print_event_info, TRUE);
12832 my_b_printf(&print_event_info->head_cache,
12833 "\tTable_map: `%s`.`%s` mapped to number %llu\n",
12834 m_dbnam, m_tblnam, m_table_id.id());
12835 print_base64(&print_event_info->body_cache, print_event_info, TRUE);
12836 }
12837 }
12838 #endif
12839
12840 /**************************************************************************
12841 Write_rows_log_event member functions
12842 **************************************************************************/
12843
12844 /*
12845 Constructor used to build an event for writing to the binary log.
12846 */
12847 #if !defined(MYSQL_CLIENT)
Write_rows_log_event(THD * thd_arg,TABLE * tbl_arg,const Table_id & tid_arg,bool is_transactional,const uchar * extra_row_info)12848 Write_rows_log_event::Write_rows_log_event(THD *thd_arg, TABLE *tbl_arg,
12849 const Table_id& tid_arg,
12850 bool is_transactional,
12851 const uchar* extra_row_info)
12852 : Rows_log_event(thd_arg, tbl_arg, tid_arg, tbl_arg->write_set, is_transactional,
12853 log_bin_use_v1_row_events?
12854 WRITE_ROWS_EVENT_V1:
12855 WRITE_ROWS_EVENT,
12856 extra_row_info)
12857 {
12858 }
12859 #endif
12860
12861 /*
12862 Constructor used by slave to read the event from the binary log.
12863 */
12864 #ifdef HAVE_REPLICATION
Write_rows_log_event(const char * buf,uint event_len,const Format_description_log_event * description_event)12865 Write_rows_log_event::Write_rows_log_event(const char *buf, uint event_len,
12866 const Format_description_log_event
12867 *description_event)
12868 : Rows_log_event(buf, event_len, description_event)
12869 {
12870 }
12871 #endif
12872
12873 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
12874 int
do_before_row_operations(const Slave_reporting_capability * const)12875 Write_rows_log_event::do_before_row_operations(const Slave_reporting_capability *const)
12876 {
12877 int error= 0;
12878
12879 m_table->file->rpl_before_write_rows();
12880
12881 /*
12882 Increment the global status insert count variable
12883 */
12884 if (get_flags(STMT_END_F))
12885 status_var_increment(thd->status_var.com_stat[SQLCOM_INSERT]);
12886
12887 /*
12888 Let storage engines treat this event as an INSERT command.
12889
12890 Set 'sql_command' as SQLCOM_INSERT after the tables are locked.
12891 When locking the tables, it should be SQLCOM_END.
12892 THD::decide_binlog_format which is called from "lock tables"
12893 assumes that row_events will have 'sql_command' as SQLCOM_END.
12894 */
12895 thd->lex->sql_command= SQLCOM_INSERT;
12896
12897 /**
12898 todo: to introduce a property for the event (handler?) which forces
12899 applying the event in the replace (idempotent) fashion.
12900 */
12901 if ((slave_exec_mode == SLAVE_EXEC_MODE_IDEMPOTENT) ||
12902 (m_table->s->db_type()->db_type == DB_TYPE_NDBCLUSTER))
12903 {
12904 /*
12905 We are using REPLACE semantics and not INSERT IGNORE semantics
12906 when writing rows, that is: new rows replace old rows. We need to
12907 inform the storage engine that it should use this behaviour.
12908 */
12909
12910 /* Tell the storage engine that we are using REPLACE semantics. */
12911 thd->lex->duplicates= DUP_REPLACE;
12912
12913 /*
12914 Pretend we're executing a REPLACE command: this is needed for
12915 InnoDB and NDB Cluster since they are not (properly) checking the
12916 lex->duplicates flag.
12917 */
12918 thd->lex->sql_command= SQLCOM_REPLACE;
12919 /*
12920 Do not raise the error flag in case of hitting to an unique attribute
12921 */
12922 m_table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
12923 /*
12924 NDB specific: update from ndb master wrapped as Write_rows
12925 so that the event should be applied to replace slave's row
12926 */
12927 m_table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
12928 /*
12929 NDB specific: if update from ndb master wrapped as Write_rows
12930 does not find the row it's assumed idempotent binlog applying
12931 is taking place; don't raise the error.
12932 */
12933 m_table->file->extra(HA_EXTRA_IGNORE_NO_KEY);
12934 /*
12935 TODO: the cluster team (Tomas?) says that it's better if the engine knows
12936 how many rows are going to be inserted, then it can allocate needed memory
12937 from the start.
12938 */
12939 }
12940
12941
12942 /* Honor next number column if present */
12943 m_table->next_number_field= m_table->found_next_number_field;
12944 /*
12945 * Fixed Bug#45999, In RBR, Store engine of Slave auto-generates new
12946 * sequence numbers for auto_increment fields if the values of them are 0.
12947 * If generateing a sequence number is decided by the values of
12948 * table->auto_increment_field_not_null and SQL_MODE(if includes
12949 * MODE_NO_AUTO_VALUE_ON_ZERO) in update_auto_increment function.
12950 * SQL_MODE of slave sql thread is always consistency with master's.
12951 * In RBR, auto_increment fields never are NULL, except if the auto_inc
12952 * column exists only on the slave side (i.e., in an extra column
12953 * on the slave's table).
12954 */
12955 if (!is_auto_inc_in_extra_columns())
12956 m_table->auto_increment_field_not_null= TRUE;
12957 else
12958 {
12959 /*
12960 Here we have checked that there is an extra field
12961 on this server's table that has an auto_inc column.
12962
12963 Mark that the auto_increment field is null and mark
12964 the read and write set bits.
12965
12966 (There can only be one AUTO_INC column, it is always
12967 indexed and it cannot have a DEFAULT value).
12968 */
12969 m_table->auto_increment_field_not_null= FALSE;
12970 m_table->mark_auto_increment_column();
12971 }
12972
12973 /**
12974 Sets it to ROW_LOOKUP_NOT_NEEDED.
12975 */
12976 decide_row_lookup_algorithm_and_key();
12977 DBUG_ASSERT(m_rows_lookup_algorithm==ROW_LOOKUP_NOT_NEEDED);
12978
12979 return error;
12980 }
12981
12982 int
do_after_row_operations(const Slave_reporting_capability * const,int error)12983 Write_rows_log_event::do_after_row_operations(const Slave_reporting_capability *const,
12984 int error)
12985 {
12986 int local_error= 0;
12987
12988 /**
12989 Clear the write_set bit for auto_inc field that only
12990 existed on the destination table as an extra column.
12991 */
12992 if (is_auto_inc_in_extra_columns())
12993 {
12994 bitmap_clear_bit(m_table->write_set, m_table->next_number_field->field_index);
12995 bitmap_clear_bit( m_table->read_set, m_table->next_number_field->field_index);
12996
12997 if (get_flags(STMT_END_F))
12998 m_table->file->ha_release_auto_increment();
12999 }
13000 m_table->next_number_field=0;
13001 m_table->auto_increment_field_not_null= FALSE;
13002 if ((slave_exec_mode == SLAVE_EXEC_MODE_IDEMPOTENT) ||
13003 m_table->s->db_type()->db_type == DB_TYPE_NDBCLUSTER)
13004 {
13005 m_table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
13006 m_table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
13007 /*
13008 resetting the extra with
13009 table->file->extra(HA_EXTRA_NO_IGNORE_NO_KEY);
13010 fires bug#27077
13011 explanation: file->reset() performs this duty
13012 ultimately. Still todo: fix
13013 */
13014 }
13015 if ((local_error= m_table->file->ha_end_bulk_insert()))
13016 {
13017 m_table->file->print_error(local_error, MYF(0));
13018 }
13019
13020 m_rows_lookup_algorithm= ROW_LOOKUP_UNDEFINED;
13021 m_table->file->rpl_after_write_rows();
13022
13023 return error? error : local_error;
13024 }
13025
13026 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
13027
13028 /*
13029 Check if there are more UNIQUE keys after the given key.
13030 */
13031 static int
last_uniq_key(TABLE * table,uint keyno)13032 last_uniq_key(TABLE *table, uint keyno)
13033 {
13034 while (++keyno < table->s->keys)
13035 if (table->key_info[keyno].flags & HA_NOSAME)
13036 return 0;
13037 return 1;
13038 }
13039
13040 /**
13041 Check if an error is a duplicate key error.
13042
13043 This function is used to check if an error code is one of the
13044 duplicate key error, i.e., and error code for which it is sensible
13045 to do a <code>get_dup_key()</code> to retrieve the duplicate key.
13046
13047 @param errcode The error code to check.
13048
13049 @return <code>true</code> if the error code is such that
13050 <code>get_dup_key()</code> will return true, <code>false</code>
13051 otherwise.
13052 */
13053 bool
is_duplicate_key_error(int errcode)13054 is_duplicate_key_error(int errcode)
13055 {
13056 switch (errcode)
13057 {
13058 case HA_ERR_FOUND_DUPP_KEY:
13059 case HA_ERR_FOUND_DUPP_UNIQUE:
13060 return true;
13061 }
13062 return false;
13063 }
13064
13065 /**
13066 Write the current row into event's table.
13067
13068 The row is located in the row buffer, pointed by @c m_curr_row member.
13069 Number of columns of the row is stored in @c m_width member (it can be
13070 different from the number of columns in the table to which we insert).
13071 Bitmap @c m_cols indicates which columns are present in the row. It is assumed
13072 that event's table is already open and pointed by @c m_table.
13073
13074 If the same record already exists in the table it can be either overwritten
13075 or an error is reported depending on the value of @c overwrite flag
13076 (error reporting not yet implemented). Note that the matching record can be
13077 different from the row we insert if we use primary keys to identify records in
13078 the table.
13079
13080 The row to be inserted can contain values only for selected columns. The
13081 missing columns are filled with default values using @c prepare_record()
13082 function. If a matching record is found in the table and @c overwritte is
13083 true, the missing columns are taken from it.
13084
13085 @param rli Relay log info (needed for row unpacking).
13086 @param overwrite
13087 Shall we overwrite if the row already exists or signal
13088 error (currently ignored).
13089
13090 @returns Error code on failure, 0 on success.
13091
13092 This method, if successful, sets @c m_curr_row_end pointer to point at the
13093 next row in the rows buffer. This is done when unpacking the row to be
13094 inserted.
13095
13096 @note If a matching record is found, it is either updated using
13097 @c ha_update_row() or first deleted and then new record written.
13098 */
13099
13100 int
write_row(const Relay_log_info * const rli,const bool overwrite)13101 Write_rows_log_event::write_row(const Relay_log_info *const rli,
13102 const bool overwrite)
13103 {
13104 DBUG_ENTER("write_row");
13105 DBUG_ASSERT(m_table != NULL && thd != NULL);
13106
13107 TABLE *table= m_table; // pointer to event's table
13108 int error;
13109 int UNINIT_VAR(keynum);
13110 auto_afree_ptr<char> key(NULL);
13111
13112 prepare_record(table, &m_cols,
13113 table->file->ht->db_type != DB_TYPE_NDBCLUSTER);
13114
13115 /* unpack row into table->record[0] */
13116 if ((error= unpack_current_row(rli, &m_cols)))
13117 DBUG_RETURN(error);
13118
13119 /*
13120 When m_curr_row == m_curr_row_end, it means a row that contains nothing,
13121 so all the pointers shall be pointing to the same address, or else
13122 we have corrupt data and shall throw the error.
13123 */
13124 DBUG_PRINT("debug",("m_rows_buf= %p, m_rows_cur= %p, m_rows_end= %p",
13125 m_rows_buf, m_rows_cur, m_rows_end));
13126 DBUG_PRINT("debug",("m_curr_row= %p, m_curr_row_end= %p",
13127 m_curr_row, m_curr_row_end));
13128 if (m_curr_row == m_curr_row_end &&
13129 !((m_rows_buf == m_rows_cur) && (m_rows_cur == m_rows_end)))
13130 {
13131 my_error(ER_SLAVE_CORRUPT_EVENT, MYF(0));
13132 DBUG_RETURN(ER_SLAVE_CORRUPT_EVENT);
13133 }
13134
13135 if (m_curr_row == m_rows_buf)
13136 {
13137 /* this is the first row to be inserted, we estimate the rows with
13138 the size of the first row and use that value to initialize
13139 storage engine for bulk insertion */
13140 DBUG_ASSERT(!(m_curr_row > m_curr_row_end));
13141 ulong estimated_rows= 0;
13142 if (m_curr_row < m_curr_row_end)
13143 estimated_rows= (m_rows_end - m_curr_row) / (m_curr_row_end - m_curr_row);
13144 else if (m_curr_row == m_curr_row_end)
13145 estimated_rows= 1;
13146
13147 m_table->file->ha_start_bulk_insert(estimated_rows);
13148 }
13149
13150 /*
13151 Explicitly set the auto_inc to null to make sure that
13152 it gets an auto_generated value.
13153 */
13154 if (is_auto_inc_in_extra_columns())
13155 m_table->next_number_field->set_null();
13156
13157 #ifndef DBUG_OFF
13158 DBUG_DUMP("record[0]", table->record[0], table->s->reclength);
13159 DBUG_PRINT_BITSET("debug", "write_set = %s", table->write_set);
13160 DBUG_PRINT_BITSET("debug", "read_set = %s", table->read_set);
13161 #endif
13162
13163 /*
13164 Try to write record. If a corresponding record already exists in the table,
13165 we try to change it using ha_update_row() if possible. Otherwise we delete
13166 it and repeat the whole process again.
13167
13168 TODO: Add safety measures against infinite looping.
13169 */
13170
13171 m_table->mark_columns_per_binlog_row_image();
13172
13173 while ((error= table->file->ha_write_row(table->record[0])))
13174 {
13175 if (error == HA_ERR_LOCK_DEADLOCK ||
13176 error == HA_ERR_LOCK_WAIT_TIMEOUT ||
13177 (keynum= table->file->get_dup_key(error)) < 0 ||
13178 !overwrite)
13179 {
13180 DBUG_PRINT("info",("get_dup_key returns %d)", keynum));
13181 /*
13182 Deadlock, waiting for lock or just an error from the handler
13183 such as HA_ERR_FOUND_DUPP_KEY when overwrite is false.
13184 Retrieval of the duplicate key number may fail
13185 - either because the error was not "duplicate key" error
13186 - or because the information which key is not available
13187 */
13188 table->file->print_error(error, MYF(0));
13189 goto error;
13190 }
13191 /*
13192 We need to retrieve the old row into record[1] to be able to
13193 either update or delete the offending record. We either:
13194
13195 - use ha_rnd_pos() with a row-id (available as dupp_row) to the
13196 offending row, if that is possible (MyISAM and Blackhole), or else
13197
13198 - use ha_index_read_idx_map() with the key that is duplicated, to
13199 retrieve the offending row.
13200 */
13201 if (table->file->ha_table_flags() & HA_DUPLICATE_POS)
13202 {
13203 DBUG_PRINT("info",("Locating offending record using ha_rnd_pos()"));
13204
13205 if (table->file->inited && (error= table->file->ha_index_end()))
13206 {
13207 table->file->print_error(error, MYF(0));
13208 goto error;
13209 }
13210 if ((error= table->file->ha_rnd_init(FALSE)))
13211 {
13212 table->file->print_error(error, MYF(0));
13213 goto error;
13214 }
13215
13216 error= table->file->ha_rnd_pos(table->record[1], table->file->dup_ref);
13217
13218 table->file->ha_rnd_end();
13219 if (error)
13220 {
13221 DBUG_PRINT("info",("ha_rnd_pos() returns error %d",error));
13222 if (error == HA_ERR_RECORD_DELETED)
13223 error= HA_ERR_KEY_NOT_FOUND;
13224 table->file->print_error(error, MYF(0));
13225 goto error;
13226 }
13227 }
13228 else
13229 {
13230 DBUG_PRINT("info",("Locating offending record using index_read_idx()"));
13231
13232 if (table->file->extra(HA_EXTRA_FLUSH_CACHE))
13233 {
13234 DBUG_PRINT("info",("Error when setting HA_EXTRA_FLUSH_CACHE"));
13235 error= my_errno;
13236 goto error;
13237 }
13238
13239 if (key.get() == NULL)
13240 {
13241 key.assign(static_cast<char*>(my_alloca(table->s->max_unique_length)));
13242 if (key.get() == NULL)
13243 {
13244 DBUG_PRINT("info",("Can't allocate key buffer"));
13245 error= ENOMEM;
13246 goto error;
13247 }
13248 }
13249
13250 key_copy((uchar*)key.get(), table->record[0], table->key_info + keynum,
13251 0);
13252 error= table->file->ha_index_read_idx_map(table->record[1], keynum,
13253 (const uchar*)key.get(),
13254 HA_WHOLE_KEY,
13255 HA_READ_KEY_EXACT);
13256 if (error)
13257 {
13258 DBUG_PRINT("info",("ha_index_read_idx_map() returns %s", HA_ERR(error)));
13259 if (error == HA_ERR_RECORD_DELETED)
13260 error= HA_ERR_KEY_NOT_FOUND;
13261 table->file->print_error(error, MYF(0));
13262 goto error;
13263 }
13264 }
13265
13266 /*
13267 Now, record[1] should contain the offending row. That
13268 will enable us to update it or, alternatively, delete it (so
13269 that we can insert the new row afterwards).
13270 */
13271
13272 /*
13273 If row is incomplete we will use the record found to fill
13274 missing columns.
13275 */
13276 if (!get_flags(COMPLETE_ROWS_F))
13277 {
13278 restore_record(table,record[1]);
13279 error= unpack_current_row(rli, &m_cols);
13280 }
13281
13282 #ifndef DBUG_OFF
13283 DBUG_PRINT("debug",("preparing for update: before and after image"));
13284 DBUG_DUMP("record[1] (before)", table->record[1], table->s->reclength);
13285 DBUG_DUMP("record[0] (after)", table->record[0], table->s->reclength);
13286 #endif
13287
13288 /*
13289 REPLACE is defined as either INSERT or DELETE + INSERT. If
13290 possible, we can replace it with an UPDATE, but that will not
13291 work on InnoDB if FOREIGN KEY checks are necessary.
13292
13293 I (Matz) am not sure of the reason for the last_uniq_key()
13294 check as, but I'm guessing that it's something along the
13295 following lines.
13296
13297 Suppose that we got the duplicate key to be a key that is not
13298 the last unique key for the table and we perform an update:
13299 then there might be another key for which the unique check will
13300 fail, so we're better off just deleting the row and inserting
13301 the correct row.
13302 */
13303 if (last_uniq_key(table, keynum) &&
13304 !table->file->referenced_by_foreign_key())
13305 {
13306 DBUG_PRINT("info",("Updating row using ha_update_row()"));
13307 error=table->file->ha_update_row(table->record[1],
13308 table->record[0]);
13309 switch (error) {
13310
13311 case HA_ERR_RECORD_IS_THE_SAME:
13312 DBUG_PRINT("info",("ignoring HA_ERR_RECORD_IS_THE_SAME error from"
13313 " ha_update_row()"));
13314 error= 0;
13315
13316 case 0:
13317 break;
13318
13319 default:
13320 DBUG_PRINT("info",("ha_update_row() returns error %d",error));
13321 table->file->print_error(error, MYF(0));
13322 }
13323
13324 goto error;
13325 }
13326 else
13327 {
13328 DBUG_PRINT("info",("Deleting offending row and trying to write new one again"));
13329 if ((error= table->file->ha_delete_row(table->record[1])))
13330 {
13331 DBUG_PRINT("info",("ha_delete_row() returns error %d",error));
13332 table->file->print_error(error, MYF(0));
13333 goto error;
13334 }
13335 /* Will retry ha_write_row() with the offending row removed. */
13336 }
13337 }
13338
13339 error:
13340 m_table->default_column_bitmaps();
13341 DBUG_RETURN(error);
13342 }
13343
13344 #endif
13345
13346 int
do_exec_row(const Relay_log_info * const rli)13347 Write_rows_log_event::do_exec_row(const Relay_log_info *const rli)
13348 {
13349 DBUG_ASSERT(m_table != NULL);
13350 int error= write_row(rli, slave_exec_mode == SLAVE_EXEC_MODE_IDEMPOTENT);
13351
13352 if (error && !thd->is_error())
13353 {
13354 DBUG_ASSERT(0);
13355 my_error(ER_UNKNOWN_ERROR, MYF(0));
13356 }
13357
13358 return error;
13359 }
13360
13361 #endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */
13362
13363 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)13364 void Write_rows_log_event::print(FILE *file, PRINT_EVENT_INFO* print_event_info)
13365 {
13366 DBUG_EXECUTE_IF("simulate_cache_read_error",
13367 {DBUG_SET("+d,simulate_my_b_fill_error");});
13368 Rows_log_event::print_helper(file, print_event_info, "Write_rows");
13369 }
13370 #endif
13371
13372 /**************************************************************************
13373 Delete_rows_log_event member functions
13374 **************************************************************************/
13375
13376 /*
13377 Constructor used to build an event for writing to the binary log.
13378 */
13379
13380 #ifndef MYSQL_CLIENT
Delete_rows_log_event(THD * thd_arg,TABLE * tbl_arg,const Table_id & tid,bool is_transactional,const uchar * extra_row_info)13381 Delete_rows_log_event::Delete_rows_log_event(THD *thd_arg, TABLE *tbl_arg,
13382 const Table_id& tid,
13383 bool is_transactional,
13384 const uchar* extra_row_info)
13385 : Rows_log_event(thd_arg, tbl_arg, tid, tbl_arg->read_set, is_transactional,
13386 log_bin_use_v1_row_events?
13387 DELETE_ROWS_EVENT_V1:
13388 DELETE_ROWS_EVENT,
13389 extra_row_info)
13390 {
13391 }
13392 #endif /* #if !defined(MYSQL_CLIENT) */
13393
13394 /*
13395 Constructor used by slave to read the event from the binary log.
13396 */
13397 #ifdef HAVE_REPLICATION
Delete_rows_log_event(const char * buf,uint event_len,const Format_description_log_event * description_event)13398 Delete_rows_log_event::Delete_rows_log_event(const char *buf, uint event_len,
13399 const Format_description_log_event
13400 *description_event)
13401 : Rows_log_event(buf, event_len, description_event)
13402 {
13403 }
13404 #endif
13405
13406 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
13407
13408 int
do_before_row_operations(const Slave_reporting_capability * const)13409 Delete_rows_log_event::do_before_row_operations(const Slave_reporting_capability *const)
13410 {
13411 int error= 0;
13412 DBUG_ENTER("Delete_rows_log_event::do_before_row_operations");
13413 m_table->file->rpl_before_delete_rows();
13414 /*
13415 Increment the global status delete count variable
13416 */
13417 if (get_flags(STMT_END_F))
13418 status_var_increment(thd->status_var.com_stat[SQLCOM_DELETE]);
13419
13420 /*
13421 Let storage engines treat this event as a DELETE command.
13422
13423 Set 'sql_command' as SQLCOM_UPDATE after the tables are locked.
13424 When locking the tables, it should be SQLCOM_END.
13425 THD::decide_binlog_format which is called from "lock tables"
13426 assumes that row_events will have 'sql_command' as SQLCOM_END.
13427 */
13428 thd->lex->sql_command= SQLCOM_DELETE;
13429
13430 error= row_operations_scan_and_key_setup();
13431 DBUG_RETURN(error);
13432
13433 }
13434
13435 int
do_after_row_operations(const Slave_reporting_capability * const,int error)13436 Delete_rows_log_event::do_after_row_operations(const Slave_reporting_capability *const,
13437 int error)
13438 {
13439 DBUG_ENTER("Delete_rows_log_event::do_after_row_operations");
13440 error= row_operations_scan_and_key_teardown(error);
13441 m_table->file->rpl_after_delete_rows();
13442 DBUG_RETURN(error);
13443 }
13444
do_exec_row(const Relay_log_info * const rli)13445 int Delete_rows_log_event::do_exec_row(const Relay_log_info *const rli)
13446 {
13447 int error;
13448 DBUG_ASSERT(m_table != NULL);
13449 if (m_rows_lookup_algorithm == ROW_LOOKUP_NOT_NEEDED) {
13450 error= unpack_current_row(rli, &m_cols);
13451 if (error)
13452 return error;
13453 }
13454 /* m_table->record[0] contains the BI */
13455 m_table->mark_columns_per_binlog_row_image();
13456 error= m_table->file->ha_delete_row(m_table->record[0]);
13457 m_table->default_column_bitmaps();
13458 return error;
13459 }
13460
13461 #endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */
13462
13463 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)13464 void Delete_rows_log_event::print(FILE *file,
13465 PRINT_EVENT_INFO* print_event_info)
13466 {
13467 Rows_log_event::print_helper(file, print_event_info, "Delete_rows");
13468 }
13469 #endif
13470
13471
13472 /**************************************************************************
13473 Update_rows_log_event member functions
13474 **************************************************************************/
13475
13476 /*
13477 Constructor used to build an event for writing to the binary log.
13478 */
13479 #if !defined(MYSQL_CLIENT)
Update_rows_log_event(THD * thd_arg,TABLE * tbl_arg,const Table_id & tid,bool is_transactional,const uchar * extra_row_info)13480 Update_rows_log_event::Update_rows_log_event(THD *thd_arg, TABLE *tbl_arg,
13481 const Table_id& tid,
13482 bool is_transactional,
13483 const uchar* extra_row_info)
13484 : Rows_log_event(thd_arg, tbl_arg, tid, tbl_arg->read_set, is_transactional,
13485 log_bin_use_v1_row_events?
13486 UPDATE_ROWS_EVENT_V1:
13487 UPDATE_ROWS_EVENT,
13488 extra_row_info)
13489 {
13490 init(tbl_arg->write_set);
13491 }
13492
init(MY_BITMAP const * cols)13493 void Update_rows_log_event::init(MY_BITMAP const *cols)
13494 {
13495 /* if bitmap_init fails, caught in is_valid() */
13496 if (likely(!bitmap_init(&m_cols_ai,
13497 m_width <= sizeof(m_bitbuf_ai)*8 ? m_bitbuf_ai : NULL,
13498 m_width,
13499 false)))
13500 {
13501 /* Cols can be zero if this is a dummy binrows event */
13502 if (likely(cols != NULL))
13503 {
13504 memcpy(m_cols_ai.bitmap, cols->bitmap, no_bytes_in_map(cols));
13505 create_last_word_mask(&m_cols_ai);
13506 }
13507 }
13508 }
13509 #endif /* !defined(MYSQL_CLIENT) */
13510
13511
~Update_rows_log_event()13512 Update_rows_log_event::~Update_rows_log_event()
13513 {
13514 if (m_cols_ai.bitmap == m_bitbuf_ai) // no my_malloc happened
13515 m_cols_ai.bitmap= 0; // so no my_free in bitmap_free
13516 bitmap_free(&m_cols_ai); // To pair with bitmap_init().
13517 }
13518
13519
13520 /*
13521 Constructor used by slave to read the event from the binary log.
13522 */
13523 #ifdef HAVE_REPLICATION
Update_rows_log_event(const char * buf,uint event_len,const Format_description_log_event * description_event)13524 Update_rows_log_event::Update_rows_log_event(const char *buf, uint event_len,
13525 const
13526 Format_description_log_event
13527 *description_event)
13528 : Rows_log_event(buf, event_len, description_event)
13529 {
13530 }
13531 #endif
13532
13533 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
13534
13535 int
do_before_row_operations(const Slave_reporting_capability * const)13536 Update_rows_log_event::do_before_row_operations(const Slave_reporting_capability *const)
13537 {
13538 int error= 0;
13539 DBUG_ENTER("Update_rows_log_event::do_before_row_operations");
13540 m_table->file->rpl_before_update_rows();
13541 /*
13542 Increment the global status update count variable
13543 */
13544 if (get_flags(STMT_END_F))
13545 status_var_increment(thd->status_var.com_stat[SQLCOM_UPDATE]);
13546
13547 /*
13548 Let storage engines treat this event as an UPDATE command.
13549
13550 Set 'sql_command' as SQLCOM_UPDATE after the tables are locked.
13551 When locking the tables, it should be SQLCOM_END.
13552 THD::decide_binlog_format which is called from "lock tables"
13553 assumes that row_events will have 'sql_command' as SQLCOM_END.
13554 */
13555 thd->lex->sql_command= SQLCOM_UPDATE;
13556
13557 error= row_operations_scan_and_key_setup();
13558 DBUG_RETURN(error);
13559
13560 }
13561
13562 int
do_after_row_operations(const Slave_reporting_capability * const,int error)13563 Update_rows_log_event::do_after_row_operations(const Slave_reporting_capability *const,
13564 int error)
13565 {
13566 DBUG_ENTER("Update_rows_log_event::do_after_row_operations");
13567 error= row_operations_scan_and_key_teardown(error);
13568 m_table->file->rpl_after_update_rows();
13569 DBUG_RETURN(error);
13570 }
13571
13572 int
do_exec_row(const Relay_log_info * const rli)13573 Update_rows_log_event::do_exec_row(const Relay_log_info *const rli)
13574 {
13575 DBUG_ASSERT(m_table != NULL);
13576 int error= 0;
13577
13578 if (m_rows_lookup_algorithm == ROW_LOOKUP_NOT_NEEDED) {
13579 error= unpack_current_row(rli, &m_cols);
13580 if (error)
13581 return error;
13582 }
13583
13584 /*
13585 This is the situation after locating BI:
13586
13587 ===|=== before image ====|=== after image ===|===
13588 ^ ^
13589 m_curr_row m_curr_row_end
13590
13591 BI found in the table is stored in record[0]. We copy it to record[1]
13592 and unpack AI to record[0].
13593 */
13594
13595 store_record(m_table,record[1]);
13596
13597 m_curr_row= m_curr_row_end;
13598 /* this also updates m_curr_row_end */
13599 if ((error= unpack_current_row(rli, &m_cols_ai)))
13600 return error;
13601
13602 /*
13603 Now we have the right row to update. The old row (the one we're
13604 looking for) is in record[1] and the new row is in record[0].
13605 */
13606 #ifndef HAVE_purify
13607 /*
13608 Don't print debug messages when running valgrind since they can
13609 trigger false warnings.
13610 */
13611 DBUG_PRINT("info",("Updating row in table"));
13612 DBUG_DUMP("old record", m_table->record[1], m_table->s->reclength);
13613 DBUG_DUMP("new values", m_table->record[0], m_table->s->reclength);
13614 #endif
13615
13616 // Temporary fix to find out why it fails [/Matz]
13617 memcpy(m_table->read_set->bitmap, m_cols.bitmap, (m_table->read_set->n_bits + 7) / 8);
13618 memcpy(m_table->write_set->bitmap, m_cols_ai.bitmap, (m_table->write_set->n_bits + 7) / 8);
13619
13620 m_table->mark_columns_per_binlog_row_image();
13621 error= m_table->file->ha_update_row(m_table->record[1], m_table->record[0]);
13622 if (error == HA_ERR_RECORD_IS_THE_SAME)
13623 error= 0;
13624 m_table->default_column_bitmaps();
13625
13626 return error;
13627 }
13628
13629 #endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */
13630
13631 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)13632 void Update_rows_log_event::print(FILE *file,
13633 PRINT_EVENT_INFO* print_event_info)
13634 {
13635 Rows_log_event::print_helper(file, print_event_info, "Update_rows");
13636 }
13637 #endif
13638
13639
Incident_log_event(const char * buf,uint event_len,const Format_description_log_event * descr_event)13640 Incident_log_event::Incident_log_event(const char *buf, uint event_len,
13641 const Format_description_log_event *descr_event)
13642 : Log_event(buf, descr_event)
13643 {
13644 DBUG_ENTER("Incident_log_event::Incident_log_event");
13645 uint8 const common_header_len=
13646 descr_event->common_header_len;
13647 uint8 const post_header_len=
13648 descr_event->post_header_len[INCIDENT_EVENT-1];
13649
13650 DBUG_PRINT("info",("event_len: %u; common_header_len: %d; post_header_len: %d",
13651 event_len, common_header_len, post_header_len));
13652
13653 m_message.str= NULL;
13654 m_message.length= 0;
13655 int incident_number= uint2korr(buf + common_header_len);
13656 if (incident_number >= INCIDENT_COUNT ||
13657 incident_number <= INCIDENT_NONE)
13658 {
13659 // If the incident is not recognized, this binlog event is
13660 // invalid. If we set incident_number to INCIDENT_NONE, the
13661 // invalidity will be detected by is_valid().
13662 m_incident= INCIDENT_NONE;
13663 DBUG_VOID_RETURN;
13664 }
13665 m_incident= static_cast<Incident>(incident_number);
13666 char const *ptr= buf + common_header_len + post_header_len;
13667 char const *const str_end= buf + event_len;
13668 uint8 len= 0; // Assignment to keep compiler happy
13669 const char *str= NULL; // Assignment to keep compiler happy
13670 read_str_at_most_255_bytes(&ptr, str_end, &str, &len);
13671 if (!(m_message.str= (char*) my_malloc(len+1, MYF(MY_WME))))
13672 {
13673 /* Mark this event invalid */
13674 m_incident= INCIDENT_NONE;
13675 DBUG_VOID_RETURN;
13676 }
13677 strmake(m_message.str, str, len);
13678 m_message.length= len;
13679 DBUG_PRINT("info", ("m_incident: %d", m_incident));
13680 DBUG_VOID_RETURN;
13681 }
13682
13683
~Incident_log_event()13684 Incident_log_event::~Incident_log_event()
13685 {
13686 if (m_message.str)
13687 my_free(m_message.str);
13688 }
13689
13690
13691 const char *
description() const13692 Incident_log_event::description() const
13693 {
13694 static const char *const description[]= {
13695 "NOTHING", // Not used
13696 "LOST_EVENTS"
13697 };
13698
13699 DBUG_PRINT("info", ("m_incident: %d", m_incident));
13700
13701 return description[m_incident];
13702 }
13703
13704
13705 #ifndef MYSQL_CLIENT
pack_info(Protocol * protocol)13706 int Incident_log_event::pack_info(Protocol *protocol)
13707 {
13708 char buf[256];
13709 size_t bytes;
13710 if (m_message.length > 0)
13711 bytes= my_snprintf(buf, sizeof(buf), "#%d (%s)",
13712 m_incident, description());
13713 else
13714 bytes= my_snprintf(buf, sizeof(buf), "#%d (%s): %s",
13715 m_incident, description(), m_message.str);
13716 protocol->store(buf, bytes, &my_charset_bin);
13717 return 0;
13718 }
13719 #endif
13720
13721
13722 #ifdef MYSQL_CLIENT
13723 void
print(FILE * file,PRINT_EVENT_INFO * print_event_info)13724 Incident_log_event::print(FILE *file,
13725 PRINT_EVENT_INFO *print_event_info)
13726 {
13727 if (print_event_info->short_form)
13728 return;
13729
13730 print_header(&print_event_info->head_cache, print_event_info, FALSE);
13731 my_b_printf(&print_event_info->head_cache,
13732 "\n# Incident: %s\nRELOAD DATABASE; # Shall generate syntax error\n",
13733 description());
13734 }
13735 #endif
13736
13737 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
13738 int
do_apply_event(Relay_log_info const * rli)13739 Incident_log_event::do_apply_event(Relay_log_info const *rli)
13740 {
13741 DBUG_ENTER("Incident_log_event::do_apply_event");
13742
13743 if (ignored_error_code(ER_SLAVE_INCIDENT))
13744 {
13745 DBUG_PRINT("info", ("Ignoring Incident"));
13746 DBUG_RETURN(0);
13747 }
13748
13749 rli->report(ERROR_LEVEL, ER_SLAVE_INCIDENT,
13750 ER(ER_SLAVE_INCIDENT),
13751 description(),
13752 m_message.length > 0 ? m_message.str : "<none>");
13753 DBUG_RETURN(1);
13754 }
13755 #endif
13756
13757 bool
write_data_header(IO_CACHE * file)13758 Incident_log_event::write_data_header(IO_CACHE *file)
13759 {
13760 DBUG_ENTER("Incident_log_event::write_data_header");
13761 DBUG_PRINT("enter", ("m_incident: %d", m_incident));
13762 uchar buf[sizeof(int16)];
13763 int2store(buf, (int16) m_incident);
13764 #ifndef MYSQL_CLIENT
13765 DBUG_RETURN(wrapper_my_b_safe_write(file, buf, sizeof(buf)));
13766 #else
13767 DBUG_RETURN(my_b_safe_write(file, buf, sizeof(buf)));
13768 #endif
13769 }
13770
13771 bool
write_data_body(IO_CACHE * file)13772 Incident_log_event::write_data_body(IO_CACHE *file)
13773 {
13774 uchar tmp[1];
13775 DBUG_ENTER("Incident_log_event::write_data_body");
13776 tmp[0]= (uchar) m_message.length;
13777 crc= my_checksum(crc, (uchar*) tmp, 1);
13778 if (m_message.length > 0)
13779 {
13780 crc= my_checksum(crc, (uchar*) m_message.str, m_message.length);
13781 // todo: report a bug on write_str accepts uint but treats it as uchar
13782 }
13783 DBUG_RETURN(write_str_at_most_255_bytes(file, m_message.str, (uint) m_message.length));
13784 }
13785
13786
Ignorable_log_event(const char * buf,const Format_description_log_event * descr_event)13787 Ignorable_log_event::Ignorable_log_event(const char *buf,
13788 const Format_description_log_event *descr_event)
13789 : Log_event(buf, descr_event)
13790 {
13791 DBUG_ENTER("Ignorable_log_event::Ignorable_log_event");
13792 DBUG_VOID_RETURN;
13793 }
13794
~Ignorable_log_event()13795 Ignorable_log_event::~Ignorable_log_event()
13796 {
13797 }
13798
13799 #ifndef MYSQL_CLIENT
13800 /* Pack info for its unrecognized ignorable event */
pack_info(Protocol * protocol)13801 int Ignorable_log_event::pack_info(Protocol *protocol)
13802 {
13803 char buf[256];
13804 size_t bytes;
13805 bytes= my_snprintf(buf, sizeof(buf), "# Unrecognized ignorable event");
13806 protocol->store(buf, bytes, &my_charset_bin);
13807 return 0;
13808 }
13809 #endif
13810
13811 #ifdef MYSQL_CLIENT
13812 /* Print for its unrecognized ignorable event */
13813 void
print(FILE * file,PRINT_EVENT_INFO * print_event_info)13814 Ignorable_log_event::print(FILE *file,
13815 PRINT_EVENT_INFO *print_event_info)
13816 {
13817 if (print_event_info->short_form)
13818 return;
13819
13820 print_header(&print_event_info->head_cache, print_event_info, FALSE);
13821 my_b_printf(&print_event_info->head_cache, "\tIgnorable\n");
13822 my_b_printf(&print_event_info->head_cache,
13823 "# Unrecognized ignorable event\n");
13824 }
13825 #endif
13826
13827
Rows_query_log_event(const char * buf,uint event_len,const Format_description_log_event * descr_event)13828 Rows_query_log_event::Rows_query_log_event(const char *buf, uint event_len,
13829 const Format_description_log_event *descr_event)
13830 : Ignorable_log_event(buf, descr_event)
13831 {
13832 DBUG_ENTER("Rows_query_log_event::Rows_query_log_event");
13833 uint8 const common_header_len=
13834 descr_event->common_header_len;
13835 uint8 const post_header_len=
13836 descr_event->post_header_len[ROWS_QUERY_LOG_EVENT-1];
13837
13838 m_rows_query= NULL;
13839
13840 DBUG_PRINT("info",("event_len: %u; common_header_len: %d; post_header_len: %d",
13841 event_len, common_header_len, post_header_len));
13842
13843 /*
13844 m_rows_query length is stored using only one byte, but that length is
13845 ignored and the complete query is read.
13846 */
13847 unsigned int offset= common_header_len + post_header_len + 1;
13848 /* Avoid reading out of buffer */
13849 if (offset > event_len)
13850 DBUG_VOID_RETURN;
13851
13852 unsigned int len= event_len - offset;
13853 if (!(m_rows_query= (char*) my_malloc(len+1, MYF(MY_WME))))
13854 return;
13855 strmake(m_rows_query, buf + offset, len);
13856 DBUG_PRINT("info", ("m_rows_query: %s", m_rows_query));
13857 DBUG_VOID_RETURN;
13858 }
13859
~Rows_query_log_event()13860 Rows_query_log_event::~Rows_query_log_event()
13861 {
13862 my_free(m_rows_query);
13863 }
13864
13865 #ifndef MYSQL_CLIENT
pack_info(Protocol * protocol)13866 int Rows_query_log_event::pack_info(Protocol *protocol)
13867 {
13868 char *buf;
13869 size_t bytes;
13870 ulong len= sizeof("# ") + (ulong) strlen(m_rows_query);
13871 if (!(buf= (char*) my_malloc(len, MYF(MY_WME))))
13872 return 1;
13873 bytes= my_snprintf(buf, len, "# %s", m_rows_query);
13874 protocol->store(buf, bytes, &my_charset_bin);
13875 my_free(buf);
13876 return 0;
13877 }
13878 #endif
13879
13880 #ifdef MYSQL_CLIENT
13881 void
print(FILE * file,PRINT_EVENT_INFO * print_event_info)13882 Rows_query_log_event::print(FILE *file,
13883 PRINT_EVENT_INFO *print_event_info)
13884 {
13885 if (!print_event_info->short_form && print_event_info->verbose > 1)
13886 {
13887 IO_CACHE *const head= &print_event_info->head_cache;
13888 IO_CACHE *const body= &print_event_info->body_cache;
13889 char *token= NULL, *saveptr= NULL;
13890 char *rows_query_copy= NULL;
13891 if (!(rows_query_copy= my_strdup(m_rows_query, MYF(MY_WME))))
13892 return;
13893
13894 print_header(head, print_event_info, FALSE);
13895 my_b_printf(head, "\tRows_query\n");
13896 /*
13897 Prefix every line of a multi-line query with '#' to prevent the
13898 statement from being executed when binary log will be processed
13899 using 'mysqlbinlog --verbose --verbose'.
13900 */
13901 for (token= strtok_r(rows_query_copy, "\n", &saveptr); token;
13902 token= strtok_r(NULL, "\n", &saveptr))
13903 my_b_printf(head, "# %s\n", token);
13904 my_free(rows_query_copy);
13905 print_base64(body, print_event_info, true);
13906 }
13907 }
13908 #endif
13909
13910 bool
write_data_body(IO_CACHE * file)13911 Rows_query_log_event::write_data_body(IO_CACHE *file)
13912 {
13913 DBUG_ENTER("Rows_query_log_event::write_data_body");
13914 /*
13915 m_rows_query length will be stored using only one byte, but on read
13916 that length will be ignored and the complete query will be read.
13917 */
13918 DBUG_RETURN(write_str_at_most_255_bytes(file, m_rows_query,
13919 (uint) strlen(m_rows_query)));
13920 }
13921
13922 #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION)
do_apply_event(Relay_log_info const * rli)13923 int Rows_query_log_event::do_apply_event(Relay_log_info const *rli)
13924 {
13925 DBUG_ENTER("Rows_query_log_event::do_apply_event");
13926 DBUG_ASSERT(rli->info_thd == thd);
13927 /* Set query for writing Rows_query log event into binlog later.*/
13928 thd->set_query(m_rows_query, (uint32) strlen(m_rows_query));
13929 thd->set_query_for_display(m_rows_query, strlen(m_rows_query));
13930
13931 DBUG_ASSERT(rli->rows_query_ev == NULL);
13932
13933 const_cast<Relay_log_info*>(rli)->rows_query_ev= this;
13934
13935 DBUG_RETURN(0);
13936 }
13937 #endif
13938
13939
13940 const char *Gtid_log_event::SET_STRING_PREFIX= "SET @@SESSION.GTID_NEXT= '";
13941
13942
Gtid_log_event(const char * buffer,uint event_len,const Format_description_log_event * descr_event)13943 Gtid_log_event::Gtid_log_event(const char *buffer, uint event_len,
13944 const Format_description_log_event *descr_event)
13945 : Log_event(buffer, descr_event)
13946 {
13947 DBUG_ENTER("Gtid_log_event::Gtid_log_event(const char *, uint, const Format_description_log_event *");
13948 uint8 const common_header_len=
13949 descr_event->common_header_len;
13950
13951 #ifndef DBUG_OFF
13952 uint8 const post_header_len=
13953 buffer[EVENT_TYPE_OFFSET] == ANONYMOUS_GTID_LOG_EVENT ?
13954 descr_event->post_header_len[ANONYMOUS_GTID_LOG_EVENT - 1] :
13955 descr_event->post_header_len[GTID_LOG_EVENT - 1];
13956 DBUG_PRINT("info",("event_len: %u; common_header_len: %d; post_header_len: %d",
13957 event_len, common_header_len, post_header_len));
13958 #endif
13959
13960 char const *ptr_buffer= buffer + common_header_len;
13961
13962 spec.type= buffer[EVENT_TYPE_OFFSET] == ANONYMOUS_GTID_LOG_EVENT ?
13963 ANONYMOUS_GROUP : GTID_GROUP;
13964
13965 commit_flag= *ptr_buffer != 0;
13966 ptr_buffer+= ENCODED_FLAG_LENGTH;
13967
13968 sid.copy_from((uchar *)ptr_buffer);
13969 ptr_buffer+= ENCODED_SID_LENGTH;
13970
13971 // SIDNO is only generated if needed, in get_sidno().
13972 spec.gtid.sidno= -1;
13973
13974 spec.gtid.gno= uint8korr(ptr_buffer);
13975 ptr_buffer+= ENCODED_GNO_LENGTH;
13976
13977 DBUG_VOID_RETURN;
13978 }
13979
13980 #ifndef MYSQL_CLIENT
Gtid_log_event(THD * thd_arg,bool using_trans,const Gtid_specification * spec_arg)13981 Gtid_log_event::Gtid_log_event(THD* thd_arg, bool using_trans,
13982 const Gtid_specification *spec_arg)
13983 : Log_event(thd_arg, thd_arg->variables.gtid_next.type == ANONYMOUS_GROUP ?
13984 LOG_EVENT_IGNORABLE_F : 0,
13985 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
13986 Log_event::EVENT_STMT_CACHE, Log_event::EVENT_NORMAL_LOGGING),
13987 commit_flag(true)
13988 {
13989 DBUG_ENTER("Gtid_log_event::Gtid_log_event(THD *)");
13990 spec= spec_arg ? *spec_arg : thd_arg->variables.gtid_next;
13991 if (spec.type == GTID_GROUP)
13992 {
13993 global_sid_lock->rdlock();
13994 sid= global_sid_map->sidno_to_sid(spec.gtid.sidno);
13995 global_sid_lock->unlock();
13996 }
13997 else
13998 sid.clear();
13999 #ifndef DBUG_OFF
14000 char buf[MAX_SET_STRING_LENGTH + 1];
14001 to_string(buf);
14002 DBUG_PRINT("info", ("%s", buf));
14003 #endif
14004 DBUG_VOID_RETURN;
14005 }
14006 #endif
14007
14008 #ifndef MYSQL_CLIENT
pack_info(Protocol * protocol)14009 int Gtid_log_event::pack_info(Protocol *protocol)
14010 {
14011 char buffer[MAX_SET_STRING_LENGTH + 1];
14012 size_t len= to_string(buffer);
14013 protocol->store(buffer, len, &my_charset_bin);
14014 return 0;
14015 }
14016 #endif
14017
to_string(char * buf) const14018 size_t Gtid_log_event::to_string(char *buf) const
14019 {
14020 char *p= buf;
14021 DBUG_ASSERT(strlen(SET_STRING_PREFIX) == SET_STRING_PREFIX_LENGTH);
14022 strcpy(p, SET_STRING_PREFIX);
14023 p+= SET_STRING_PREFIX_LENGTH;
14024 p+= spec.to_string(&sid, p);
14025 *p++= '\'';
14026 *p= '\0';
14027 return p - buf;
14028 }
14029
14030 #ifdef MYSQL_CLIENT
14031 void
print(FILE * file,PRINT_EVENT_INFO * print_event_info)14032 Gtid_log_event::print(FILE *file, PRINT_EVENT_INFO *print_event_info)
14033 {
14034 char buffer[MAX_SET_STRING_LENGTH + 1];
14035 IO_CACHE *const head= &print_event_info->head_cache;
14036 if (!print_event_info->short_form)
14037 {
14038 print_header(head, print_event_info, FALSE);
14039 my_b_printf(head, "\tGTID [commit=%s]\n", commit_flag ? "yes" : "no");
14040 }
14041 to_string(buffer);
14042 my_b_printf(head, "%s%s\n", buffer, print_event_info->delimiter);
14043 }
14044 #endif
14045
14046 #ifdef MYSQL_SERVER
write_data_header(IO_CACHE * file)14047 bool Gtid_log_event::write_data_header(IO_CACHE *file)
14048 {
14049 DBUG_ENTER("Gtid_log_event::write_data_header");
14050 char buffer[POST_HEADER_LENGTH];
14051 char* ptr_buffer= buffer;
14052
14053 *ptr_buffer= commit_flag ? 1 : 0;
14054 ptr_buffer+= ENCODED_FLAG_LENGTH;
14055
14056 #ifndef DBUG_OFF
14057 char buf[rpl_sid::TEXT_LENGTH + 1];
14058 sid.to_string(buf);
14059 DBUG_PRINT("info", ("sid=%s sidno=%d gno=%lld",
14060 buf, spec.gtid.sidno, spec.gtid.gno));
14061 #endif
14062
14063 sid.copy_to((uchar *)ptr_buffer);
14064 ptr_buffer+= ENCODED_SID_LENGTH;
14065
14066 int8store(ptr_buffer, spec.gtid.gno);
14067 ptr_buffer+= ENCODED_GNO_LENGTH;
14068
14069 DBUG_ASSERT(ptr_buffer == (buffer + sizeof(buffer)));
14070 DBUG_RETURN(wrapper_my_b_safe_write(file, (uchar *) buffer, sizeof(buffer)));
14071 }
14072 #endif // MYSQL_SERVER
14073
14074 #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION)
do_apply_event(Relay_log_info const * rli)14075 int Gtid_log_event::do_apply_event(Relay_log_info const *rli)
14076 {
14077 DBUG_ENTER("Gtid_log_event::do_apply_event");
14078 DBUG_ASSERT(rli->info_thd == thd);
14079
14080 if (get_type_code() == ANONYMOUS_GTID_LOG_EVENT)
14081 {
14082 if (gtid_mode == GTID_MODE_ON)
14083 {
14084 my_error(ER_CANT_SET_GTID_NEXT_TO_ANONYMOUS_WHEN_GTID_MODE_IS_ON, MYF(0));
14085 DBUG_RETURN(1);
14086 }
14087 thd->variables.gtid_next.set_anonymous();
14088 /*
14089 We do not need to write the anonymous gtid log event into binary log,
14090 since we should not add new fields to include logical timestamps used
14091 for applying transactions in parallel in the GA version.
14092 */
14093 DBUG_RETURN(0);
14094 }
14095
14096 /* Applying Gtid_log_event should report an error when GTID_MODE is OFF */
14097 if (gtid_mode == GTID_MODE_OFF)
14098 {
14099 my_error(ER_CANT_SET_GTID_NEXT_TO_GTID_WHEN_GTID_MODE_IS_OFF, MYF(0));
14100 DBUG_RETURN(1);
14101 }
14102
14103 rpl_sidno sidno= get_sidno(true);
14104 if (sidno < 0)
14105 DBUG_RETURN(1); // out of memory
14106 if (thd->owned_gtid.sidno)
14107 {
14108 /*
14109 Slave will execute this code if a previous Gtid_log_event was applied
14110 but the GTID wasn't consumed yet (the transaction was not committed
14111 nor rolled back).
14112 On a client session we cannot do consecutive SET GTID_NEXT without
14113 a COMMIT or a ROLLBACK in the middle.
14114 Applying this event without rolling back the current transaction may
14115 lead to problems, as a "BEGIN" event following this GTID will
14116 implicitly commit the "partial transaction" and will consume the
14117 GTID. If this "partial transaction" was left in the relay log by the
14118 IO thread restarting in the middle of a transaction, you could have
14119 the partial transaction being logged with the GTID on the slave,
14120 causing data corruption on replication.
14121 */
14122 if (thd->transaction.all.ha_list)
14123 {
14124 /* This is not an error (XA is safe), just an information */
14125 rli->report(INFORMATION_LEVEL, 0,
14126 "Rolling back unfinished transaction (no COMMIT "
14127 "or ROLLBACK in relay log). A probable cause is partial "
14128 "transaction left on relay log because of restarting IO "
14129 "thread with auto-positioning protocol.");
14130 const_cast<Relay_log_info*>(rli)->cleanup_context(thd, 1);
14131 }
14132 gtid_rollback(thd);
14133 }
14134 thd->variables.gtid_next.set(sidno, spec.gtid.gno);
14135 DBUG_PRINT("info", ("setting gtid_next=%d:%lld",
14136 sidno, spec.gtid.gno));
14137
14138 if (gtid_acquire_ownership_single(thd))
14139 DBUG_RETURN(1);
14140
14141 DBUG_RETURN(0);
14142 }
14143
do_update_pos(Relay_log_info * rli)14144 int Gtid_log_event::do_update_pos(Relay_log_info *rli)
14145 {
14146 /*
14147 This event does not increment group positions. This means
14148 that if there is a failure after it has been processed,
14149 it will be automatically re-executed.
14150 */
14151 rli->inc_event_relay_log_pos();
14152 DBUG_EXECUTE_IF("crash_after_update_pos_gtid",
14153 sql_print_information("Crashing crash_after_update_pos_gtid.");
14154 DBUG_SUICIDE(););
14155 return 0;
14156 }
14157 #endif
14158
Previous_gtids_log_event(const char * buffer,uint event_len,const Format_description_log_event * descr_event)14159 Previous_gtids_log_event::Previous_gtids_log_event(
14160 const char *buffer, uint event_len,
14161 const Format_description_log_event *descr_event)
14162 : Log_event(buffer, descr_event)
14163 {
14164 DBUG_ENTER("Previous_gtids_log_event::Previous_gtids_log_event");
14165 uint8 const common_header_len=
14166 descr_event->common_header_len;
14167 uint8 const post_header_len=
14168 descr_event->post_header_len[PREVIOUS_GTIDS_LOG_EVENT - 1];
14169
14170 DBUG_PRINT("info",("event_len: %u; common_header_len: %d; post_header_len: %d",
14171 event_len, common_header_len, post_header_len));
14172
14173 buf= (const uchar *)buffer + common_header_len + post_header_len;
14174 buf_size= (const uchar *)buffer + event_len - buf;
14175 DBUG_PRINT("info", ("data size of the event: %d", buf_size));
14176 DBUG_VOID_RETURN;
14177 }
14178
14179 #ifndef MYSQL_CLIENT
Previous_gtids_log_event(const Gtid_set * set)14180 Previous_gtids_log_event::Previous_gtids_log_event(const Gtid_set *set)
14181 : Log_event(Log_event::EVENT_NO_CACHE,
14182 Log_event::EVENT_IMMEDIATE_LOGGING)
14183 {
14184 DBUG_ENTER("Previous_gtids_log_event::Previous_gtids_log_event(THD *, const Gtid_set *)");
14185 global_sid_lock->assert_some_lock();
14186 buf_size= set->get_encoded_length();
14187 uchar *buffer= (uchar *) my_malloc(buf_size, MYF(MY_WME));
14188 if (buffer != NULL)
14189 {
14190 set->encode(buffer);
14191 register_temp_buf((char *)buffer);
14192 }
14193 this->buf= buffer;
14194 // if buf == NULL, is_valid will return false
14195 DBUG_VOID_RETURN;
14196 }
14197 #endif
14198
14199 #ifndef MYSQL_CLIENT
pack_info(Protocol * protocol)14200 int Previous_gtids_log_event::pack_info(Protocol *protocol)
14201 {
14202 size_t length= 0;
14203 global_sid_lock->rdlock();
14204 char *str= get_str(&length, &Gtid_set::default_string_format);
14205 global_sid_lock->unlock();
14206 if (str == NULL)
14207 return 1;
14208 protocol->store(str, length, &my_charset_bin);
14209 my_free(str);
14210 return 0;
14211 }
14212 #endif
14213
14214 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)14215 void Previous_gtids_log_event::print(FILE *file,
14216 PRINT_EVENT_INFO *print_event_info)
14217 {
14218 IO_CACHE *const head= &print_event_info->head_cache;
14219
14220 global_sid_lock->rdlock();
14221 char *str= get_str(NULL, &Gtid_set::commented_string_format);
14222 global_sid_lock->unlock();
14223 if (str != NULL)
14224 {
14225 if (!print_event_info->short_form)
14226 {
14227 print_header(head, print_event_info, FALSE);
14228 my_b_printf(head, "\tPrevious-GTIDs\n");
14229 }
14230 my_b_printf(head, "%s\n", str);
14231 my_free(str);
14232 }
14233 }
14234 #endif
14235
add_to_set(Gtid_set * target) const14236 int Previous_gtids_log_event::add_to_set(Gtid_set *target) const
14237 {
14238 DBUG_ENTER("Previous_gtids_log_event::add_to_set(Gtid_set *)");
14239 size_t end_pos= 0;
14240 size_t add_size= DBUG_EVALUATE_IF("gtid_has_extra_data", 10, 0);
14241 /* Silently ignore additional unknown data at the end of the encoding */
14242 PROPAGATE_REPORTED_ERROR_INT(target->add_gtid_encoding(buf,
14243 buf_size + add_size,
14244 &end_pos));
14245 DBUG_ASSERT(end_pos <= (size_t) buf_size);
14246 DBUG_RETURN(0);
14247 }
14248
get_str(size_t * length_p,const Gtid_set::String_format * string_format) const14249 char *Previous_gtids_log_event::get_str(
14250 size_t *length_p, const Gtid_set::String_format *string_format) const
14251 {
14252 DBUG_ENTER("Previous_gtids_log_event::get_str(size_t *)");
14253 Sid_map sid_map(NULL);
14254 Gtid_set set(&sid_map, NULL);
14255 DBUG_PRINT("info", ("temp_buf=%p buf=%p", temp_buf, buf));
14256 if (set.add_gtid_encoding(buf, buf_size) != RETURN_STATUS_OK)
14257 DBUG_RETURN(NULL);
14258 set.dbug_print("set");
14259 size_t length= set.get_string_length(string_format);
14260 DBUG_PRINT("info", ("string length= %lu", (ulong) length));
14261 char* str= (char *)my_malloc(length + 1, MYF(MY_WME));
14262 if (str != NULL)
14263 {
14264 set.to_string(str, string_format);
14265 if (length_p != NULL)
14266 *length_p= length;
14267 }
14268 DBUG_RETURN(str);
14269 }
14270
14271 #ifndef MYSQL_CLIENT
write_data_body(IO_CACHE * file)14272 bool Previous_gtids_log_event::write_data_body(IO_CACHE *file)
14273 {
14274 DBUG_ENTER("Previous_gtids_log_event::write_data_body");
14275 DBUG_PRINT("info", ("size=%d", buf_size));
14276 bool ret= wrapper_my_b_safe_write(file, buf, buf_size);
14277 DBUG_RETURN(ret);
14278 }
14279 #endif
14280
14281 #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION)
do_update_pos(Relay_log_info * rli)14282 int Previous_gtids_log_event::do_update_pos(Relay_log_info *rli)
14283 {
14284 rli->inc_event_relay_log_pos();
14285 return 0;
14286 }
14287 #endif
14288
14289
14290 #ifdef MYSQL_CLIENT
14291 /**
14292 The default values for these variables should be values that are
14293 *incorrect*, i.e., values that cannot occur in an event. This way,
14294 they will always be printed for the first event.
14295 */
st_print_event_info()14296 st_print_event_info::st_print_event_info()
14297 :flags2_inited(0), sql_mode_inited(0), sql_mode(0),
14298 auto_increment_increment(0),auto_increment_offset(0), charset_inited(0),
14299 lc_time_names_number(~0),
14300 charset_database_number(ILLEGAL_CHARSET_INFO_NUMBER),
14301 thread_id(0), thread_id_printed(false),server_id_from_fd_event(0),
14302 base64_output_mode(BASE64_OUTPUT_UNSPEC), printed_fd_event(FALSE),
14303 have_unflushed_events(false), skipped_event_in_transaction(false),
14304 is_gtid_next_set(false), is_gtid_next_valid(true)
14305 {
14306 /*
14307 Currently we only use static PRINT_EVENT_INFO objects, so zeroed at
14308 program's startup, but these explicit memset() is for the day someone
14309 creates dynamic instances.
14310 */
14311 memset(db, 0, sizeof(db));
14312 memset(charset, 0, sizeof(charset));
14313 memset(time_zone_str, 0, sizeof(time_zone_str));
14314 delimiter[0]= ';';
14315 delimiter[1]= 0;
14316 myf const flags = MYF(MY_WME | MY_NABP);
14317 open_cached_file(&head_cache, NULL, NULL, 0, flags);
14318 open_cached_file(&body_cache, NULL, NULL, 0, flags);
14319 }
14320 #endif
14321
14322
14323 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
Heartbeat_log_event(const char * buf,uint event_len,const Format_description_log_event * description_event)14324 Heartbeat_log_event::Heartbeat_log_event(const char* buf, uint event_len,
14325 const Format_description_log_event* description_event)
14326 :Log_event(buf, description_event)
14327 {
14328 uint8 header_size= description_event->common_header_len;
14329 ident_len = event_len - header_size;
14330 set_if_smaller(ident_len,FN_REFLEN-1);
14331 log_ident= buf + header_size;
14332 }
14333 #endif
14334
14335 #ifdef MYSQL_SERVER
14336 /*
14337 This is a utility function that adds a quoted identifier into the a buffer.
14338 This also escapes any existance of the quote string inside the identifier.
14339
14340 SYNOPSIS
14341 my_strmov_quoted_identifier
14342 thd thread handler
14343 buffer target buffer
14344 identifier the identifier to be quoted
14345 length length of the identifier
14346 */
my_strmov_quoted_identifier(THD * thd,char * buffer,const char * identifier,uint length)14347 size_t my_strmov_quoted_identifier(THD* thd, char *buffer,
14348 const char* identifier,
14349 uint length)
14350 {
14351 int q= thd ? get_quote_char_for_identifier(thd, identifier, length) : '`';
14352 return my_strmov_quoted_identifier_helper(q, buffer, identifier, length);
14353 }
14354 #else
my_strmov_quoted_identifier(char * buffer,const char * identifier)14355 size_t my_strmov_quoted_identifier(char *buffer, const char* identifier)
14356 {
14357 int q= '`';
14358 return my_strmov_quoted_identifier_helper(q, buffer, identifier, 0);
14359 }
14360
14361 #endif
14362
my_strmov_quoted_identifier_helper(int q,char * buffer,const char * identifier,uint length)14363 size_t my_strmov_quoted_identifier_helper(int q, char *buffer,
14364 const char* identifier,
14365 uint length)
14366 {
14367 size_t written= 0;
14368 char quote_char;
14369 uint id_length= (length) ? length : strlen(identifier);
14370
14371 if (q == EOF)
14372 {
14373 (void) strncpy(buffer, identifier, id_length);
14374 return id_length;
14375 }
14376 quote_char= (char) q;
14377 *buffer++= quote_char;
14378 written++;
14379 while (id_length--)
14380 {
14381 if (*identifier == quote_char)
14382 {
14383 *buffer++= quote_char;
14384 written++;
14385 }
14386 *buffer++= *identifier++;
14387 written++;
14388 }
14389 *buffer++= quote_char;
14390 return ++written;
14391 }
14392
14393