1 /*
2 Copyright (c) 2000, 2021, Oracle and/or its affiliates.
3 Copyright (c) 2018, Percona and/or its affiliates. All rights reserved.
4 Copyright (c) 2009, 2016, MariaDB
5
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License, version 2.0,
8 as published by the Free Software Foundation.
9
10 This program is also distributed with certain software (including
11 but not limited to OpenSSL) that is licensed under separate terms,
12 as designated in a particular file or component or in included license
13 documentation. The authors of MySQL hereby grant you an additional
14 permission to link the program and your derivative works with the
15 separately licensed software that they have included with MySQL.
16
17 This program is distributed in the hope that it will be useful,
18 but WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 GNU General Public License, version 2.0, for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
25
26 #include "log_event.h"
27
28 #include "base64.h" // base64_encode
29 #include "binary_log_funcs.h" // my_timestamp_binary_length
30
31 #ifndef MYSQL_CLIENT
32 #include "debug_sync.h" // debug_sync_set_action
33 #include "my_dir.h" // my_dir
34 #include "log.h" // Log_throttle
35 #include "rpl_mts_submode.h" // Mts_submode
36 #include "rpl_rli.h" // Relay_log_info
37 #include "rpl_rli_pdb.h" // Slave_job_group
38 #include "rpl_slave.h" // use_slave_mask
39 #include "sql_base.h" // close_thread_tables
40 #include "sql_cache.h" // QUERY_CACHE_FLAGS_SIZE
41 #include "sql_db.h" // load_db_opt_by_name
42 #include "sql_load.h" // mysql_load
43 #include "sql_locale.h" // my_locale_by_number
44 #include "sql_parse.h" // mysql_test_parse_for_slave
45 #include "sql_show.h" // append_identifier
46 #include "transaction.h" // trans_rollback_stmt
47 #include "tztime.h" // Time_zone
48 #include "rpl_msr.h" // channel_map
49 #include "binary_log.h" // binary_log
50 #include "rpl_thd_raii.h" // Disable_index_extensions_switch_guard
51
52 #include "pfs_file_provider.h"
53 #include "mysql/psi/mysql_file.h"
54
55 #include <mysql/psi/mysql_statement.h>
56 #include "transaction_info.h"
57 #include "sql_class.h"
58 #include "mysql/psi/mysql_transaction.h"
59 #include "sql_plugin.h" // plugin_foreach
60 #define window_size Log_throttle::LOG_THROTTLE_WINDOW_SIZE
61 Error_log_throttle
62 slave_ignored_err_throttle(window_size,
63 sql_print_information,
64 "Error log throttle: %lu time(s) Error_code: 1237"
65 " \"Slave SQL thread ignored the query because of"
66 " replicate-*-table rules\" got suppressed.");
67 #endif /* MYSQL_CLIENT */
68
69 #include <base64.h>
70 #include <my_bitmap.h>
71 #include <map>
72 #include "rpl_utility.h"
73 /* This is necessary for the List manipuation */
74 #include "sql_list.h" /* I_List */
75 #include "hash.h"
76 #include "sql_digest.h"
77 #include "rpl_gtid.h"
78 #include "xa_aux.h"
79
80 PSI_memory_key key_memory_log_event;
81 PSI_memory_key key_memory_Incident_log_event_message;
82 PSI_memory_key key_memory_Rows_query_log_event_rows_query;
83
84 #ifndef EMBEDDED_LIBRARY
85 #include "sql_connect.h" //update_global_user_stats
86 #endif
87
88 using std::min;
89 using std::max;
90
91 /**
92 BINLOG_CHECKSUM variable.
93 */
94 const char *binlog_checksum_type_names[]= {
95 "NONE",
96 "CRC32",
97 NullS
98 };
99
100 unsigned int binlog_checksum_type_length[]= {
101 sizeof("NONE") - 1,
102 sizeof("CRC32") - 1,
103 0
104 };
105
106 TYPELIB binlog_checksum_typelib=
107 {
108 array_elements(binlog_checksum_type_names) - 1, "",
109 binlog_checksum_type_names,
110 binlog_checksum_type_length
111 };
112
113
114 #define log_cs &my_charset_latin1
115
116 /*
117 Size of buffer for printing a double in format %.<PREC>g
118
119 optional '-' + optional zero + '.' + PREC digits + 'e' + sign +
120 exponent digits + '\0'
121 */
122 #define FMT_G_BUFSIZE(PREC) (3 + (PREC) + 5 + 1)
123
124 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
125 static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD* thd);
126
HA_ERR(int i)127 static const char *HA_ERR(int i)
128 {
129 /*
130 This function should only be called in case of an error
131 was detected
132 */
133 assert(i != 0);
134 switch (i) {
135 case HA_ERR_KEY_NOT_FOUND: return "HA_ERR_KEY_NOT_FOUND";
136 case HA_ERR_FOUND_DUPP_KEY: return "HA_ERR_FOUND_DUPP_KEY";
137 case HA_ERR_RECORD_CHANGED: return "HA_ERR_RECORD_CHANGED";
138 case HA_ERR_WRONG_INDEX: return "HA_ERR_WRONG_INDEX";
139 case HA_ERR_CRASHED: return "HA_ERR_CRASHED";
140 case HA_ERR_WRONG_IN_RECORD: return "HA_ERR_WRONG_IN_RECORD";
141 case HA_ERR_OUT_OF_MEM: return "HA_ERR_OUT_OF_MEM";
142 case HA_ERR_NOT_A_TABLE: return "HA_ERR_NOT_A_TABLE";
143 case HA_ERR_WRONG_COMMAND: return "HA_ERR_WRONG_COMMAND";
144 case HA_ERR_OLD_FILE: return "HA_ERR_OLD_FILE";
145 case HA_ERR_NO_ACTIVE_RECORD: return "HA_ERR_NO_ACTIVE_RECORD";
146 case HA_ERR_RECORD_DELETED: return "HA_ERR_RECORD_DELETED";
147 case HA_ERR_RECORD_FILE_FULL: return "HA_ERR_RECORD_FILE_FULL";
148 case HA_ERR_INDEX_FILE_FULL: return "HA_ERR_INDEX_FILE_FULL";
149 case HA_ERR_END_OF_FILE: return "HA_ERR_END_OF_FILE";
150 case HA_ERR_UNSUPPORTED: return "HA_ERR_UNSUPPORTED";
151 case HA_ERR_TOO_BIG_ROW: return "HA_ERR_TOO_BIG_ROW";
152 case HA_WRONG_CREATE_OPTION: return "HA_WRONG_CREATE_OPTION";
153 case HA_ERR_FOUND_DUPP_UNIQUE: return "HA_ERR_FOUND_DUPP_UNIQUE";
154 case HA_ERR_UNKNOWN_CHARSET: return "HA_ERR_UNKNOWN_CHARSET";
155 case HA_ERR_WRONG_MRG_TABLE_DEF: return "HA_ERR_WRONG_MRG_TABLE_DEF";
156 case HA_ERR_CRASHED_ON_REPAIR: return "HA_ERR_CRASHED_ON_REPAIR";
157 case HA_ERR_CRASHED_ON_USAGE: return "HA_ERR_CRASHED_ON_USAGE";
158 case HA_ERR_LOCK_WAIT_TIMEOUT: return "HA_ERR_LOCK_WAIT_TIMEOUT";
159 case HA_ERR_LOCK_TABLE_FULL: return "HA_ERR_LOCK_TABLE_FULL";
160 case HA_ERR_READ_ONLY_TRANSACTION: return "HA_ERR_READ_ONLY_TRANSACTION";
161 case HA_ERR_LOCK_DEADLOCK: return "HA_ERR_LOCK_DEADLOCK";
162 case HA_ERR_CANNOT_ADD_FOREIGN: return "HA_ERR_CANNOT_ADD_FOREIGN";
163 case HA_ERR_NO_REFERENCED_ROW: return "HA_ERR_NO_REFERENCED_ROW";
164 case HA_ERR_ROW_IS_REFERENCED: return "HA_ERR_ROW_IS_REFERENCED";
165 case HA_ERR_NO_SAVEPOINT: return "HA_ERR_NO_SAVEPOINT";
166 case HA_ERR_NON_UNIQUE_BLOCK_SIZE: return "HA_ERR_NON_UNIQUE_BLOCK_SIZE";
167 case HA_ERR_NO_SUCH_TABLE: return "HA_ERR_NO_SUCH_TABLE";
168 case HA_ERR_TABLE_EXIST: return "HA_ERR_TABLE_EXIST";
169 case HA_ERR_NO_CONNECTION: return "HA_ERR_NO_CONNECTION";
170 case HA_ERR_NULL_IN_SPATIAL: return "HA_ERR_NULL_IN_SPATIAL";
171 case HA_ERR_TABLE_DEF_CHANGED: return "HA_ERR_TABLE_DEF_CHANGED";
172 case HA_ERR_NO_PARTITION_FOUND: return "HA_ERR_NO_PARTITION_FOUND";
173 case HA_ERR_RBR_LOGGING_FAILED: return "HA_ERR_RBR_LOGGING_FAILED";
174 case HA_ERR_DROP_INDEX_FK: return "HA_ERR_DROP_INDEX_FK";
175 case HA_ERR_FOREIGN_DUPLICATE_KEY: return "HA_ERR_FOREIGN_DUPLICATE_KEY";
176 case HA_ERR_TABLE_NEEDS_UPGRADE: return "HA_ERR_TABLE_NEEDS_UPGRADE";
177 case HA_ERR_TABLE_READONLY: return "HA_ERR_TABLE_READONLY";
178 case HA_ERR_AUTOINC_READ_FAILED: return "HA_ERR_AUTOINC_READ_FAILED";
179 case HA_ERR_AUTOINC_ERANGE: return "HA_ERR_AUTOINC_ERANGE";
180 case HA_ERR_GENERIC: return "HA_ERR_GENERIC";
181 case HA_ERR_RECORD_IS_THE_SAME: return "HA_ERR_RECORD_IS_THE_SAME";
182 case HA_ERR_LOGGING_IMPOSSIBLE: return "HA_ERR_LOGGING_IMPOSSIBLE";
183 case HA_ERR_CORRUPT_EVENT: return "HA_ERR_CORRUPT_EVENT";
184 case HA_ERR_ROWS_EVENT_APPLY : return "HA_ERR_ROWS_EVENT_APPLY";
185 case HA_ERR_FK_DEPTH_EXCEEDED : return "HA_ERR_FK_DEPTH_EXCEEDED";
186 case HA_ERR_INNODB_READ_ONLY: return "HA_ERR_INNODB_READ_ONLY";
187 case HA_ERR_COMPUTE_FAILED: return "HA_ERR_COMPUTE_FAILED";
188 case HA_ERR_FTS_TOO_MANY_NESTED_EXP: return "HA_ERR_FTS_TOO_MANY_NESTED_EXP";
189 }
190 return "No Error!";
191 }
192
193 /**
194 Error reporting facility for Rows_log_event::do_apply_event
195
196 @param level error, warning or info
197 @param ha_error HA_ERR_ code
198 @param rli pointer to the active Relay_log_info instance
199 @param thd pointer to the slave thread's thd
200 @param table pointer to the event's table object
201 @param type the type of the event
202 @param log_name the master binlog file name
203 @param pos the master binlog file pos (the next after the event)
204
205 */
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)206 static void inline slave_rows_error_report(enum loglevel level, int ha_error,
207 Relay_log_info const *rli, THD *thd,
208 TABLE *table, const char * type,
209 const char *log_name, ulong pos)
210 {
211 const char *handler_error= (ha_error ? HA_ERR(ha_error) : NULL);
212 bool is_group_replication_applier_channel=
213 channel_map.is_group_replication_channel_name((const_cast<Relay_log_info *>(rli))->get_channel(), true);
214 char buff[MAX_SLAVE_ERRMSG], *slider;
215 const char *buff_end= buff + sizeof(buff);
216 size_t len;
217 Diagnostics_area::Sql_condition_iterator it=
218 thd->get_stmt_da()->sql_conditions();
219 const Sql_condition *err;
220 buff[0]= 0;
221
222 for (err= it++, slider= buff; err && slider < buff_end - 1;
223 slider += len, err= it++)
224 {
225 len= my_snprintf(slider, buff_end - slider,
226 " %s, Error_code: %d;", err->message_text(),
227 err->mysql_errno());
228 }
229 if (is_group_replication_applier_channel)
230 {
231 if (ha_error != 0)
232 {
233 rli->report(level, thd->is_error() ? thd->get_stmt_da()->mysql_errno() :
234 ER_UNKNOWN_ERROR, "Could not execute %s event on table %s.%s;"
235 "%s handler error %s",
236 type, table->s->db.str, table->s->table_name.str,
237 buff, handler_error == NULL ? "<unknown>" : handler_error);
238 }
239 else
240 {
241 rli->report(level, thd->is_error() ? thd->get_stmt_da()->mysql_errno() :
242 ER_UNKNOWN_ERROR, "Could not execute %s event on table %s.%s;"
243 "%s", type, table->s->db.str, table->s->table_name.str,
244 buff);
245 }
246 }
247 else
248 {
249 if (ha_error != 0)
250 {
251 rli->report(level, thd->is_error() ? thd->get_stmt_da()->mysql_errno() :
252 ER_UNKNOWN_ERROR, "Could not execute %s event on table %s.%s;"
253 "%s handler error %s; "
254 "the event's master log %s, end_log_pos %lu",
255 type, table->s->db.str, table->s->table_name.str,
256 buff, handler_error == NULL ? "<unknown>" : handler_error,
257 log_name, pos);
258 }
259 else
260 {
261 rli->report(level, thd->is_error() ? thd->get_stmt_da()->mysql_errno() :
262 ER_UNKNOWN_ERROR, "Could not execute %s event on table %s.%s;"
263 "%s the event's master log %s, end_log_pos %lu",
264 type, table->s->db.str, table->s->table_name.str,
265 buff, log_name, pos);
266 }
267 }
268 }
269
set_thd_db(THD * thd,const char * db,size_t db_len)270 static void set_thd_db(THD *thd, const char *db, size_t db_len)
271 {
272 char lcase_db_buf[NAME_LEN +1];
273 LEX_CSTRING new_db;
274 new_db.length= db_len;
275 if (lower_case_table_names)
276 {
277 my_stpcpy(lcase_db_buf, db);
278 my_casedn_str(system_charset_info, lcase_db_buf);
279 new_db.str= lcase_db_buf;
280 }
281 else
282 new_db.str= (char*) db;
283
284 new_db.str= (char*) rpl_filter->get_rewrite_db(new_db.str,
285 &new_db.length);
286 thd->set_db(new_db);
287 }
288
289 #endif
290
291
292 /*
293 pretty_print_str()
294 */
295
296 #ifdef MYSQL_CLIENT
pretty_print_str(IO_CACHE * cache,const char * str,size_t len)297 static void pretty_print_str(IO_CACHE* cache, const char* str, size_t len)
298 {
299 const char* end = str + len;
300 my_b_printf(cache, "\'");
301 while (str < end)
302 {
303 char c;
304 switch ((c=*str++)) {
305 case '\n': my_b_printf(cache, "\\n"); break;
306 case '\r': my_b_printf(cache, "\\r"); break;
307 case '\\': my_b_printf(cache, "\\\\"); break;
308 case '\b': my_b_printf(cache, "\\b"); break;
309 case '\t': my_b_printf(cache, "\\t"); break;
310 case '\'': my_b_printf(cache, "\\'"); break;
311 case 0 : my_b_printf(cache, "\\0"); break;
312 default:
313 my_b_printf(cache, "%c", c);
314 break;
315 }
316 }
317 my_b_printf(cache, "\'");
318 }
319 #endif /* MYSQL_CLIENT */
320
321 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
322
clear_all_errors(THD * thd,Relay_log_info * rli)323 static void clear_all_errors(THD *thd, Relay_log_info *rli)
324 {
325 thd->is_slave_error = 0;
326 thd->clear_error();
327 rli->clear_error();
328 if (rli->workers_array_initialized)
329 {
330 for(size_t i= 0; i < rli->get_worker_count(); i++)
331 {
332 rli->get_worker(i)->clear_error();
333 }
334 }
335 }
336
idempotent_error_code(int err_code)337 inline int idempotent_error_code(int err_code)
338 {
339 int ret= 0;
340
341 switch (err_code)
342 {
343 case 0:
344 ret= 1;
345 break;
346 /*
347 The following list of "idempotent" errors
348 means that an error from the list might happen
349 because of idempotent (more than once)
350 applying of a binlog file.
351 Notice, that binlog has a ddl operation its
352 second applying may cause
353
354 case HA_ERR_TABLE_DEF_CHANGED:
355 case HA_ERR_CANNOT_ADD_FOREIGN:
356
357 which are not included into to the list.
358
359 Note that HA_ERR_RECORD_DELETED is not in the list since
360 do_exec_row() should not return that error code.
361 */
362 case HA_ERR_RECORD_CHANGED:
363 case HA_ERR_KEY_NOT_FOUND:
364 case HA_ERR_END_OF_FILE:
365 case HA_ERR_FOUND_DUPP_KEY:
366 case HA_ERR_FOUND_DUPP_UNIQUE:
367 case HA_ERR_FOREIGN_DUPLICATE_KEY:
368 case HA_ERR_NO_REFERENCED_ROW:
369 case HA_ERR_ROW_IS_REFERENCED:
370 ret= 1;
371 break;
372 default:
373 ret= 0;
374 break;
375 }
376 return (ret);
377 }
378
379 /**
380 Ignore error code specified on command line.
381 */
382
ignored_error_code(int err_code)383 int ignored_error_code(int err_code)
384 {
385 return ((err_code == ER_SLAVE_IGNORED_TABLE) ||
386 (use_slave_mask && bitmap_is_set(&slave_error_mask, err_code)));
387 }
388
389 /*
390 This function converts an engine's error to a server error.
391
392 If the thread does not have an error already reported, it tries to
393 define it by calling the engine's method print_error. However, if a
394 mapping is not found, it uses the ER_UNKNOWN_ERROR and prints out a
395 warning message.
396 */
convert_handler_error(int error,THD * thd,TABLE * table)397 int convert_handler_error(int error, THD* thd, TABLE *table)
398 {
399 uint actual_error= (thd->is_error() ? thd->get_stmt_da()->mysql_errno() :
400 0);
401
402 if (actual_error == 0)
403 {
404 table->file->print_error(error, MYF(0));
405 actual_error= (thd->is_error() ? thd->get_stmt_da()->mysql_errno() :
406 ER_UNKNOWN_ERROR);
407 if (actual_error == ER_UNKNOWN_ERROR)
408 sql_print_warning("Unknown error detected %d in handler", error);
409 }
410
411 return (actual_error);
412 }
413
concurrency_error_code(int error)414 inline bool concurrency_error_code(int error)
415 {
416 switch (error)
417 {
418 case ER_LOCK_WAIT_TIMEOUT:
419 case ER_LOCK_DEADLOCK:
420 case ER_XA_RBDEADLOCK:
421 return TRUE;
422 default:
423 return (FALSE);
424 }
425 }
426
unexpected_error_code(int unexpected_error)427 inline bool unexpected_error_code(int unexpected_error)
428 {
429 switch (unexpected_error)
430 {
431 case ER_NET_READ_ERROR:
432 case ER_NET_ERROR_ON_WRITE:
433 case ER_QUERY_INTERRUPTED:
434 case ER_SERVER_SHUTDOWN:
435 case ER_NEW_ABORTING_CONNECTION:
436 return(TRUE);
437 default:
438 return(FALSE);
439 }
440 }
441
442 /*
443 pretty_print_str()
444 */
445
pretty_print_str(char * packet,const char * str,size_t len)446 static char *pretty_print_str(char *packet, const char *str, size_t len)
447 {
448 const char *end= str + len;
449 char *pos= packet;
450 *pos++= '\'';
451 while (str < end)
452 {
453 char c;
454 switch ((c=*str++)) {
455 case '\n': *pos++= '\\'; *pos++= 'n'; break;
456 case '\r': *pos++= '\\'; *pos++= 'r'; break;
457 case '\\': *pos++= '\\'; *pos++= '\\'; break;
458 case '\b': *pos++= '\\'; *pos++= 'b'; break;
459 case '\t': *pos++= '\\'; *pos++= 't'; break;
460 case '\'': *pos++= '\\'; *pos++= '\''; break;
461 case 0 : *pos++= '\\'; *pos++= '0'; break;
462 default:
463 *pos++= c;
464 break;
465 }
466 }
467 *pos++= '\'';
468 return pos;
469 }
470 #endif /* !MYSQL_CLIENT */
471
472
473 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
474
475 /**
476 Creates a temporary name for load data infile:.
477
478 @param buf Store new filename here
479 @param file_id File_id (part of file name)
480 @param event_server_id Event_id (part of file name)
481 @param ext Extension for file name
482
483 @return
484 Pointer to start of extension
485 */
486
slave_load_file_stem(char * buf,uint file_id,int event_server_id,const char * ext)487 static char *slave_load_file_stem(char *buf, uint file_id,
488 int event_server_id, const char *ext)
489 {
490 char *res;
491 fn_format(buf,PREFIX_SQL_LOAD,slave_load_tmpdir, "", MY_UNPACK_FILENAME);
492 to_unix_path(buf);
493
494 buf= strend(buf);
495 int appended_length= sprintf(buf, "%s-%d-", server_uuid, event_server_id);
496 buf+= appended_length;
497 res= int10_to_str(file_id, buf, 10);
498 my_stpcpy(res, ext); // Add extension last
499 return res; // Pointer to extension
500 }
501 #endif
502
503
504 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
505
506 /**
507 Delete all temporary files used for SQL_LOAD.
508 */
509
cleanup_load_tmpdir()510 static void cleanup_load_tmpdir()
511 {
512 MY_DIR *dirp;
513 FILEINFO *file;
514 uint i;
515 char fname[FN_REFLEN], prefbuf[TEMP_FILE_MAX_LEN], *p;
516
517 if (!(dirp=my_dir(slave_load_tmpdir,MYF(0))))
518 return;
519
520 /*
521 When we are deleting temporary files, we should only remove
522 the files associated with the server id of our server.
523 We don't use event_server_id here because since we've disabled
524 direct binlogging of Create_file/Append_file/Exec_load events
525 we cannot meet Start_log event in the middle of events from one
526 LOAD DATA.
527 */
528 p= strmake(prefbuf, STRING_WITH_LEN(PREFIX_SQL_LOAD));
529 sprintf(p,"%s-",server_uuid);
530
531 for (i=0 ; i < dirp->number_off_files; i++)
532 {
533 file=dirp->dir_entry+i;
534 if (is_prefix(file->name, prefbuf))
535 {
536 fn_format(fname,file->name,slave_load_tmpdir,"",MY_UNPACK_FILENAME);
537 mysql_file_delete(key_file_misc, fname, MYF(0));
538 }
539 }
540
541 my_dirend(dirp);
542 }
543 #endif
544
545
546 /*
547 Stores string to IO_CACHE file.
548
549 Writes str to file in the following format:
550 1. Stores length using only one byte (255 maximum value);
551 2. Stores complete str.
552 */
553
write_str_at_most_255_bytes(IO_CACHE * file,const char * str,uint length,Event_encrypter * event_encrypter)554 static bool write_str_at_most_255_bytes(IO_CACHE *file, const char *str, uint length,
555 Event_encrypter *event_encrypter)
556 {
557 uchar tmp[1];
558 tmp[0]= (uchar) length;
559 return (event_encrypter->encrypt_and_write(file, tmp, sizeof(tmp)) ||
560 event_encrypter->encrypt_and_write(file, (uchar*) str, length));
561 }
562
563 /**
564 Transforms a string into "" or its expression in 0x... form.
565 */
566
str_to_hex(char * to,const char * from,size_t len)567 char *str_to_hex(char *to, const char *from, size_t len)
568 {
569 if (len)
570 {
571 *to++= '0';
572 *to++= 'x';
573 to= octet2hex(to, from, len);
574 }
575 else
576 to= my_stpcpy(to, "\"\"");
577 return to; // pointer to end 0 of 'to'
578 }
579
580 #ifndef MYSQL_CLIENT
581
582 /**
583 Append a version of the 'from' string suitable for use in a query to
584 the 'to' string. To generate a correct escaping, the character set
585 information in 'csinfo' is used.
586 */
587
588 int
append_query_string(THD * thd,const CHARSET_INFO * csinfo,String const * from,String * to)589 append_query_string(THD *thd, const CHARSET_INFO *csinfo,
590 String const *from, String *to)
591 {
592 char *beg, *ptr;
593 size_t const orig_len= to->length();
594 if (to->reserve(orig_len + from->length()*2+3))
595 return 1;
596
597 beg= to->c_ptr_quick() + to->length();
598 ptr= beg;
599 if (csinfo->escape_with_backslash_is_dangerous)
600 ptr= str_to_hex(ptr, from->ptr(), from->length());
601 else
602 {
603 *ptr++= '\'';
604 if (!(thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES))
605 {
606 ptr+= escape_string_for_mysql(csinfo, ptr, 0,
607 from->ptr(), from->length());
608 }
609 else
610 {
611 const char *frm_str= from->ptr();
612
613 for (; frm_str < (from->ptr() + from->length()); frm_str++)
614 {
615 /* Using '' way to represent "'" */
616 if (*frm_str == '\'')
617 *ptr++= *frm_str;
618
619 *ptr++= *frm_str;
620 }
621 }
622
623 *ptr++= '\'';
624 }
625 to->length(orig_len + ptr - beg);
626 return 0;
627 }
628 #endif
629
630
631 /**
632 Prints a "session_var=value" string. Used by mysqlbinlog to print some SET
633 commands just before it prints a query.
634 */
635
636 #ifdef MYSQL_CLIENT
637
print_set_option(IO_CACHE * file,uint32 bits_changed,uint32 option,uint32 flags,const char * name,bool * need_comma)638 static void print_set_option(IO_CACHE* file, uint32 bits_changed,
639 uint32 option, uint32 flags, const char* name,
640 bool* need_comma)
641 {
642 if (bits_changed & option)
643 {
644 if (*need_comma)
645 my_b_printf(file,", ");
646 my_b_printf(file,"%s=%d", name, MY_TEST(flags & option));
647 *need_comma= 1;
648 }
649 }
650 #endif
651 /**************************************************************************
652 Log_event methods (= the parent class of all events)
653 **************************************************************************/
654
655 /**
656 @return
657 returns the human readable name of the event's type
658 */
659
get_type_str(Log_event_type type)660 const char* Log_event::get_type_str(Log_event_type type)
661 {
662 switch(type) {
663 case binary_log::START_EVENT_V3: return "Start_v3";
664 case binary_log::STOP_EVENT: return "Stop";
665 case binary_log::QUERY_EVENT: return "Query";
666 case binary_log::ROTATE_EVENT: return "Rotate";
667 case binary_log::INTVAR_EVENT: return "Intvar";
668 case binary_log::LOAD_EVENT: return "Load";
669 case binary_log::NEW_LOAD_EVENT: return "New_load";
670 case binary_log::CREATE_FILE_EVENT: return "Create_file";
671 case binary_log::APPEND_BLOCK_EVENT: return "Append_block";
672 case binary_log::DELETE_FILE_EVENT: return "Delete_file";
673 case binary_log::EXEC_LOAD_EVENT: return "Exec_load";
674 case binary_log::RAND_EVENT: return "RAND";
675 case binary_log::XID_EVENT: return "Xid";
676 case binary_log::USER_VAR_EVENT: return "User var";
677 case binary_log::FORMAT_DESCRIPTION_EVENT: return "Format_desc";
678 case binary_log::TABLE_MAP_EVENT: return "Table_map";
679 case binary_log::PRE_GA_WRITE_ROWS_EVENT: return "Write_rows_event_old";
680 case binary_log::PRE_GA_UPDATE_ROWS_EVENT: return "Update_rows_event_old";
681 case binary_log::PRE_GA_DELETE_ROWS_EVENT: return "Delete_rows_event_old";
682 case binary_log::WRITE_ROWS_EVENT_V1: return "Write_rows_v1";
683 case binary_log::UPDATE_ROWS_EVENT_V1: return "Update_rows_v1";
684 case binary_log::DELETE_ROWS_EVENT_V1: return "Delete_rows_v1";
685 case binary_log::BEGIN_LOAD_QUERY_EVENT: return "Begin_load_query";
686 case binary_log::EXECUTE_LOAD_QUERY_EVENT: return "Execute_load_query";
687 case binary_log::INCIDENT_EVENT: return "Incident";
688 case binary_log::IGNORABLE_LOG_EVENT: return "Ignorable";
689 case binary_log::ROWS_QUERY_LOG_EVENT: return "Rows_query";
690 case binary_log::WRITE_ROWS_EVENT: return "Write_rows";
691 case binary_log::UPDATE_ROWS_EVENT: return "Update_rows";
692 case binary_log::DELETE_ROWS_EVENT: return "Delete_rows";
693 case binary_log::GTID_LOG_EVENT: return "Gtid";
694 case binary_log::ANONYMOUS_GTID_LOG_EVENT: return "Anonymous_Gtid";
695 case binary_log::PREVIOUS_GTIDS_LOG_EVENT: return "Previous_gtids";
696 case binary_log::HEARTBEAT_LOG_EVENT: return "Heartbeat";
697 case binary_log::TRANSACTION_CONTEXT_EVENT: return "Transaction_context";
698 case binary_log::VIEW_CHANGE_EVENT: return "View_change";
699 case binary_log::XA_PREPARE_LOG_EVENT: return "XA_prepare";
700 case binary_log::START_ENCRYPTION_EVENT: return "Start_encryption";
701 default: return "Unknown"; /* impossible */
702 }
703 }
704
get_type_str()705 const char* Log_event::get_type_str()
706 {
707 return get_type_str(get_type_code());
708 }
709
710
711 /*
712 Log_event::Log_event()
713 */
714
715 #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,Log_event_header * header,Log_event_footer * footer)716 Log_event::Log_event(THD* thd_arg, uint16 flags_arg,
717 enum_event_cache_type cache_type_arg,
718 enum_event_logging_type logging_type_arg,
719 Log_event_header *header, Log_event_footer *footer)
720 : is_valid_param(false), temp_buf(0), exec_time(0),
721 event_cache_type(cache_type_arg), event_logging_type(logging_type_arg),
722 crc(0), common_header(header), common_footer(footer), thd(thd_arg)
723 {
724 server_id= thd->server_id;
725 common_header->unmasked_server_id= server_id;
726 common_header->when= thd->start_time;
727 common_header->log_pos= 0;
728 common_header->flags= flags_arg;
729 }
730
731 /**
732 This minimal constructor is for when you are not even sure that there
733 is a valid THD. For example in the server when we are shutting down or
734 flushing logs after receiving a SIGHUP (then we must write a Rotate to
735 the binlog but we have no THD, so we need this minimal constructor).
736 */
737
Log_event(Log_event_header * header,Log_event_footer * footer,enum_event_cache_type cache_type_arg,enum_event_logging_type logging_type_arg)738 Log_event::Log_event(Log_event_header* header, Log_event_footer *footer,
739 enum_event_cache_type cache_type_arg,
740 enum_event_logging_type logging_type_arg)
741 : is_valid_param(false), temp_buf(0), exec_time(0), event_cache_type(cache_type_arg),
742 event_logging_type(logging_type_arg), crc(0), common_header(header),
743 common_footer(footer), thd(0)
744 {
745 server_id= ::server_id;
746 common_header->unmasked_server_id= server_id;
747 }
748 #endif /* !MYSQL_CLIENT */
749
750
751 /*
752 Log_event::Log_event()
753 */
754
Log_event(Log_event_header * header,Log_event_footer * footer)755 Log_event::Log_event(Log_event_header *header,
756 Log_event_footer *footer)
757 : is_valid_param(false), temp_buf(0), exec_time(0),
758 event_cache_type(EVENT_INVALID_CACHE),
759 event_logging_type(EVENT_INVALID_LOGGING),
760 crc(0), common_header(header), common_footer(footer)
761 {
762 #ifndef MYSQL_CLIENT
763 thd= 0;
764 #endif
765 /*
766 Mask out any irrelevant parts of the server_id
767 */
768 #ifdef HAVE_REPLICATION
769 server_id = common_header->unmasked_server_id & opt_server_id_mask;
770 #else
771 server_id = common_header->unmasked_server_id;
772 #endif
773 }
774
775 /*
776 This method is not on header file to avoid using key_memory_log_event
777 outside log_event.cc, allowing header file to be included on plugins.
778 */
operator new(size_t size)779 void* Log_event::operator new(size_t size)
780 {
781 return my_malloc(key_memory_log_event, size, MYF(MY_WME|MY_FAE));
782 }
783
784 #ifndef MYSQL_CLIENT
785 #ifdef HAVE_REPLICATION
do_apply_event_worker(Slave_worker * w)786 inline int Log_event::do_apply_event_worker(Slave_worker *w)
787 {
788 DBUG_EXECUTE_IF("crash_in_a_worker",
789 {
790 /* we will crash a worker after waiting for
791 2 seconds to make sure that other transactions are
792 scheduled and completed */
793 if (w->id == 2)
794 {
795 DBUG_SET("-d,crash_in_a_worker");
796 my_sleep(2000000);
797 DBUG_SUICIDE();
798 }
799 });
800 return do_apply_event(w);
801 }
802
do_update_pos(Relay_log_info * rli)803 int Log_event::do_update_pos(Relay_log_info *rli)
804 {
805 int error= 0;
806 assert(!rli->belongs_to_client());
807 /*
808 rli is null when (as far as I (Guilhem) know) the caller is
809 Load_log_event::do_apply_event *and* that one is called from
810 Execute_load_log_event::do_apply_event. In this case, we don't
811 do anything here ; Execute_load_log_event::do_apply_event will
812 call Log_event::do_apply_event again later with the proper rli.
813 Strictly speaking, if we were sure that rli is null only in the
814 case discussed above, 'if (rli)' is useless here. But as we are
815 not 100% sure, keep it for now.
816
817 Matz: I don't think we will need this check with this refactoring.
818 */
819
820 assert(!is_mts_worker(rli->info_thd));
821
822 if (rli)
823 error= rli->stmt_done(common_header->log_pos);
824 return error;
825 }
826
827
828 Log_event::enum_skip_reason
do_shall_skip(Relay_log_info * rli)829 Log_event::do_shall_skip(Relay_log_info *rli)
830 {
831 /*
832 The logic for slave_skip_counter is as follows:
833
834 - Events that are skipped because they have the same server_id as
835 the slave do not decrease slave_skip_counter.
836
837 - Other events (that pass the server_id test) will decrease
838 slave_skip_counter.
839
840 - Except in one case: if slave_skip_counter==1, it will only
841 decrease to 0 if we are at a so-called group boundary. Here, a
842 group is defined as the range of events that represent a single
843 transaction in the relay log: see comment for is_in_group in
844 rpl_rli.h for a definition.
845
846 The difficult part to implement is the logic to avoid decreasing
847 the counter to 0. Given that groups have the form described in
848 is_in_group in rpl_rli.h, we implement the logic as follows:
849
850 - Gtid, Rand, User_var, Int_var will never decrease the counter to
851 0.
852
853 - BEGIN will set thd->variables.option_bits & OPTION_BEGIN and
854 COMMIT/Xid will clear it. This happens regardless of whether
855 the BEGIN/COMMIT/Xid is skipped itself.
856
857 - Other events will decrease the counter unless OPTION_BEGIN is
858 set.
859 */
860 DBUG_PRINT("info", ("ev->server_id=%lu, ::server_id=%lu,"
861 " rli->replicate_same_server_id=%d,"
862 " rli->slave_skip_counter=%d",
863 (ulong) server_id, (ulong) ::server_id,
864 rli->replicate_same_server_id,
865 rli->slave_skip_counter));
866 if ((server_id == ::server_id && !rli->replicate_same_server_id) ||
867 (rli->slave_skip_counter == 1 && rli->is_in_group()))
868 return EVENT_SKIP_IGNORE;
869 else if (rli->slave_skip_counter > 0)
870 return EVENT_SKIP_COUNT;
871 else
872 return EVENT_SKIP_NOT;
873 }
874
875
876 /*
877 Log_event::pack_info()
878 */
879
pack_info(Protocol * protocol)880 int Log_event::pack_info(Protocol *protocol)
881 {
882 protocol->store("", &my_charset_bin);
883 return 0;
884 }
885
886
887 /**
888 Only called by SHOW BINLOG EVENTS
889 */
net_send(Protocol * protocol,const char * log_name,my_off_t pos)890 int Log_event::net_send(Protocol *protocol, const char* log_name, my_off_t pos)
891 {
892 const char *p= strrchr(log_name, FN_LIBCHAR);
893 const char *event_type;
894 if (p)
895 log_name = p + 1;
896
897 protocol->start_row();
898 protocol->store(log_name, &my_charset_bin);
899 protocol->store((ulonglong) pos);
900 event_type = get_type_str();
901 protocol->store(event_type, strlen(event_type), &my_charset_bin);
902 protocol->store((uint32) server_id);
903 protocol->store((ulonglong) common_header->log_pos);
904 if (pack_info(protocol))
905 return 1;
906 return protocol->end_row();
907 }
908 #endif /* HAVE_REPLICATION */
909
910
911 /**
912 init_show_field_list() prepares the column names and types for the
913 output of SHOW BINLOG EVENTS; it is used only by SHOW BINLOG
914 EVENTS.
915 */
916
init_show_field_list(List<Item> * field_list)917 void Log_event::init_show_field_list(List<Item>* field_list)
918 {
919 field_list->push_back(new Item_empty_string("Log_name", 20));
920 field_list->push_back(new Item_return_int("Pos", MY_INT32_NUM_DECIMAL_DIGITS,
921 MYSQL_TYPE_LONGLONG));
922 field_list->push_back(new Item_empty_string("Event_type", 20));
923 field_list->push_back(new Item_return_int("Server_id", 10,
924 MYSQL_TYPE_LONG));
925 field_list->push_back(new Item_return_int("End_log_pos",
926 MY_INT32_NUM_DECIMAL_DIGITS,
927 MYSQL_TYPE_LONGLONG));
928 field_list->push_back(new Item_empty_string("Info", 20));
929 }
930
931 /**
932 A decider of whether to trigger checksum computation or not.
933 To be invoked in Log_event::write() stack.
934 The decision is positive
935
936 S,M) if it's been marked for checksumming with @c checksum_alg
937
938 M) otherwise, if @@global.binlog_checksum is not NONE and the event is
939 directly written to the binlog file.
940 The to-be-cached event decides at @c write_cache() time.
941
942 Otherwise the decision is negative.
943
944 @note A side effect of the method is altering Log_event::checksum_alg
945 it the latter was undefined at calling.
946
947 @return true (positive) or false (negative)
948 */
need_checksum()949 my_bool Log_event::need_checksum()
950 {
951 DBUG_ENTER("Log_event::need_checksum");
952 my_bool ret= FALSE;
953 /*
954 few callers of Log_event::write
955 (incl FD::write, FD constructing code on the slave side, Rotate relay log
956 and Stop event)
957 provides their checksum alg preference through Log_event::checksum_alg.
958 */
959 if (common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_UNDEF)
960 ret= (common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_OFF);
961 else if (binlog_checksum_options != binary_log::BINLOG_CHECKSUM_ALG_OFF &&
962 event_cache_type == Log_event::EVENT_NO_CACHE)
963 ret= (binlog_checksum_options != 0);
964 else
965 ret= FALSE;
966
967 /*
968 FD calls the methods before data_written has been calculated.
969 The following invariant claims if the current is not the first
970 call (and therefore data_written is not zero) then `ret' must be
971 TRUE. It may not be null because FD is always checksummed.
972 */
973
974 assert(get_type_code() != binary_log::FORMAT_DESCRIPTION_EVENT || ret ||
975 common_header->data_written == 0);
976
977 if (common_footer->checksum_alg == binary_log::BINLOG_CHECKSUM_ALG_UNDEF)
978 common_footer->checksum_alg= ret ? // calculated value stored
979 static_cast<enum_binlog_checksum_alg>(binlog_checksum_options) :
980 binary_log::BINLOG_CHECKSUM_ALG_OFF;
981
982 assert(!ret ||
983 ((common_footer->checksum_alg ==
984 static_cast<enum_binlog_checksum_alg>(binlog_checksum_options) ||
985 /*
986 Stop event closes the relay-log and its checksum alg
987 preference is set by the caller can be different
988 from the server's binlog_checksum_options.
989 */
990 get_type_code() == binary_log::STOP_EVENT ||
991 /*
992 Rotate:s can be checksummed regardless of the server's
993 binlog_checksum_options. That applies to both
994 the local RL's Rotate and the master's Rotate
995 which IO thread instantiates via queue_binlog_ver_3_event.
996 */
997 get_type_code() == binary_log::ROTATE_EVENT ||
998 get_type_code() == binary_log::START_ENCRYPTION_EVENT ||
999 /*
1000 The previous event has its checksum option defined
1001 according to the format description event.
1002 */
1003 get_type_code() == binary_log::PREVIOUS_GTIDS_LOG_EVENT ||
1004 /* FD is always checksummed */
1005 get_type_code() == binary_log::FORMAT_DESCRIPTION_EVENT) &&
1006 common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_OFF));
1007
1008 assert(common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_UNDEF);
1009 assert(((get_type_code() != binary_log::ROTATE_EVENT &&
1010 get_type_code() != binary_log::STOP_EVENT) ||
1011 get_type_code() != binary_log::FORMAT_DESCRIPTION_EVENT) ||
1012 event_cache_type == Log_event::EVENT_NO_CACHE);
1013
1014 DBUG_RETURN(ret);
1015 }
1016
wrapper_my_b_safe_write(IO_CACHE * file,const uchar * buf,size_t size)1017 bool Log_event::wrapper_my_b_safe_write(IO_CACHE* file, const uchar* buf, size_t size)
1018 {
1019 DBUG_EXECUTE_IF("simulate_temp_file_write_error",
1020 {
1021 memset(file->write_pos, 0, file->write_end - file->write_pos);
1022 file->write_pos=file->write_end;
1023 DBUG_SET("+d,simulate_file_write_error");
1024 });
1025 if (need_checksum() && size != 0)
1026 crc= checksum_crc32(crc, buf, size);
1027
1028 bool ret = event_encrypter.encrypt_and_write(file, buf, size);
1029 DBUG_EXECUTE_IF("simulate_temp_file_write_error",
1030 {
1031 DBUG_SET("-d,simulate_file_write_error");
1032 });
1033 return ret;
1034 }
1035
write_footer(IO_CACHE * file)1036 bool Log_event::write_footer(IO_CACHE* file)
1037 {
1038 /*
1039 footer contains the checksum-algorithm descriptor
1040 followed by the checksum value
1041 */
1042 if (need_checksum())
1043 {
1044 uchar buf[BINLOG_CHECKSUM_LEN];
1045 int4store(buf, crc);
1046 if (event_encrypter.encrypt_and_write(file, buf, BINLOG_CHECKSUM_LEN))
1047 return true;
1048 }
1049 return event_encrypter.is_encryption_enabled() &&
1050 event_encrypter.finish(file);
1051 }
1052
1053
write_header_to_memory(uchar * buf)1054 uint32 Log_event::write_header_to_memory(uchar *buf)
1055 {
1056 // Query start time
1057 ulong timestamp= (ulong) get_time();
1058
1059 #ifndef NDEBUG
1060 if (DBUG_EVALUATE_IF("inc_event_time_by_1_hour",1,0) &&
1061 DBUG_EVALUATE_IF("dec_event_time_by_1_hour",1,0))
1062 {
1063 /**
1064 This assertion guarantees that these debug flags are not
1065 used at the same time (they would cancel each other).
1066 */
1067 assert(0);
1068 }
1069 else
1070 {
1071 DBUG_EXECUTE_IF("inc_event_time_by_1_hour", timestamp= timestamp + 3600;);
1072 DBUG_EXECUTE_IF("dec_event_time_by_1_hour", timestamp= timestamp - 3600;);
1073 }
1074 #endif
1075
1076 /*
1077 Header will be of size LOG_EVENT_HEADER_LEN for all events, except for
1078 FORMAT_DESCRIPTION_EVENT and ROTATE_EVENT, where it will be
1079 LOG_EVENT_MINIMAL_HEADER_LEN (remember these 2 have a frozen header,
1080 because we read them before knowing the format).
1081 */
1082
1083 int4store(buf, timestamp);
1084 buf[EVENT_TYPE_OFFSET]= get_type_code();
1085 int4store(buf + SERVER_ID_OFFSET, server_id);
1086 int4store(buf + EVENT_LEN_OFFSET,
1087 static_cast<uint32>(common_header->data_written));
1088 int4store(buf + LOG_POS_OFFSET,
1089 static_cast<uint32>(common_header->log_pos));
1090 int2store(buf + FLAGS_OFFSET, common_header->flags);
1091
1092 return LOG_EVENT_HEADER_LEN;
1093 }
1094
1095
write_header(IO_CACHE * file,size_t event_data_length)1096 bool Log_event::write_header(IO_CACHE* file, size_t event_data_length)
1097 {
1098 uchar header[LOG_EVENT_HEADER_LEN];
1099 DBUG_ENTER("Log_event::write_header");
1100
1101 /* Store number of bytes that will be written by this event */
1102 common_header->data_written= event_data_length + sizeof(header);
1103
1104 if (need_checksum())
1105 {
1106 crc= checksum_crc32(0L, NULL, 0);
1107 common_header->data_written += BINLOG_CHECKSUM_LEN;
1108 }
1109
1110 /*
1111 log_pos != 0 if this is relay-log event. In this case we should not
1112 change the position
1113 */
1114
1115 if (is_artificial_event())
1116 {
1117 /*
1118 Artificial events are automatically generated and do not exist
1119 in master's binary log, so log_pos should be set to 0.
1120 */
1121 common_header->log_pos= 0;
1122 }
1123 else if (!common_header->log_pos)
1124 {
1125 /*
1126 Calculate position of end of event
1127
1128 Note that with a SEQ_READ_APPEND cache, my_b_tell() does not
1129 work well. So this will give slightly wrong positions for the
1130 Format_desc/Rotate/Stop events which the slave writes to its
1131 relay log. For example, the initial Format_desc will have
1132 end_log_pos=91 instead of 95. Because after writing the first 4
1133 bytes of the relay log, my_b_tell() still reports 0. Because
1134 my_b_append() does not update the counter which my_b_tell()
1135 later uses (one should probably use my_b_append_tell() to work
1136 around this). To get right positions even when writing to the
1137 relay log, we use the (new) my_b_safe_tell().
1138
1139 Note that this raises a question on the correctness of all these
1140 assert(my_b_tell()=rli->event_relay_log_pos).
1141
1142 If in a transaction, the log_pos which we calculate below is not
1143 very good (because then my_b_safe_tell() returns start position
1144 of the BEGIN, so it's like the statement was at the BEGIN's
1145 place), but it's not a very serious problem (as the slave, when
1146 it is in a transaction, does not take those end_log_pos into
1147 account (as it calls inc_event_relay_log_pos()). To be fixed
1148 later, so that it looks less strange. But not bug.
1149 */
1150
1151 common_header->log_pos= my_b_safe_tell(file) + common_header->data_written;
1152 }
1153
1154 write_header_to_memory(header);
1155
1156 const bool is_format_description_and_need_checksum= need_checksum() &&
1157 ((common_header->flags & LOG_EVENT_BINLOG_IN_USE_F) != 0);
1158
1159 /*
1160 Update the checksum.
1161
1162 In case this is a Format_description_log_event, we need to clear
1163 the LOG_EVENT_BINLOG_IN_USE_F flag before computing the checksum,
1164 since the flag will be cleared when the binlog is closed. On
1165 verification, the flag is dropped before computing the checksum
1166 too. We need to compute the checksum before we encrypt the header,
1167 in case binlog encryption is turned on.
1168 */
1169
1170 if (is_format_description_and_need_checksum)
1171 {
1172 common_header->flags&= ~LOG_EVENT_BINLOG_IN_USE_F;
1173 int2store(header + FLAGS_OFFSET, common_header->flags);
1174 }
1175 crc= my_checksum(crc, header, LOG_EVENT_HEADER_LEN);
1176
1177 // restore IN_USE flag after calculating the checksum
1178 if (is_format_description_and_need_checksum)
1179 {
1180 common_header->flags|= LOG_EVENT_BINLOG_IN_USE_F;
1181 int2store(header + FLAGS_OFFSET, common_header->flags);
1182 }
1183
1184 uchar *pos= header;
1185 size_t len= sizeof(header);
1186
1187 if (event_encrypter.is_encryption_enabled() &&
1188 event_encrypter.init(file, pos, len))
1189 DBUG_RETURN(true);
1190
1191 DBUG_RETURN(event_encrypter.encrypt_and_write(file, pos, len));
1192 }
1193
1194 /**
1195 This needn't be format-tolerant, because we only read
1196 LOG_EVENT_MINIMAL_HEADER_LEN (we just want to read the event's length).
1197
1198 The caller should allocate the packet buffer before calling this function.
1199 */
1200
read_log_event(IO_CACHE * file,String * packet,const Format_description_log_event * fdle,mysql_mutex_t * log_lock,enum_binlog_checksum_alg checksum_alg_arg,const char * log_file_name_arg,bool * is_binlog_active,char * event_header)1201 int Log_event::read_log_event(IO_CACHE* file, String* packet,
1202 const Format_description_log_event *fdle,
1203 mysql_mutex_t* log_lock,
1204 enum_binlog_checksum_alg checksum_alg_arg,
1205 const char *log_file_name_arg,
1206 bool* is_binlog_active,
1207 char *event_header)
1208 {
1209
1210 ulong data_len;
1211 int result=0;
1212 char local_buf[LOG_EVENT_MINIMAL_HEADER_LEN];
1213 char *buf= event_header != NULL ? event_header : local_buf;
1214 size_t ev_offset= packet->length();
1215 DBUG_ENTER("Log_event::read_log_event(IO_CACHE *, String *, mysql_mutex_t, uint8)");
1216
1217 if (log_lock)
1218 mysql_mutex_lock(log_lock);
1219
1220 if (log_file_name_arg)
1221 *is_binlog_active= mysql_bin_log.is_active(log_file_name_arg);
1222
1223 /* If the event header wasn't passed, we need to read it. */
1224 if (buf == local_buf)
1225 {
1226 if (my_b_read(file, (uchar*) buf, LOG_EVENT_MINIMAL_HEADER_LEN))
1227 {
1228 /*
1229 If the read hits eof, we must report it as eof so the caller
1230 will know it can go into cond_wait to be woken up on the next
1231 update to the log.
1232 */
1233 DBUG_PRINT("error",("my_b_read failed. file->error: %d", file->error));
1234 if (!file->error)
1235 result= LOG_READ_EOF;
1236 else
1237 result= (file->error > 0 ? LOG_READ_TRUNC : LOG_READ_IO);
1238 goto end;
1239 }
1240 }
1241 else
1242 DBUG_PRINT("info",("Skipped reading the event header. Using the provided one."));
1243
1244 data_len= uint4korr(buf + EVENT_LEN_OFFSET);
1245 if (data_len < LOG_EVENT_MINIMAL_HEADER_LEN ||
1246 data_len > max(current_thd->variables.max_allowed_packet,
1247 opt_binlog_rows_event_max_size + MAX_LOG_EVENT_HEADER))
1248 {
1249 DBUG_PRINT("error",("data_len is out of bounds. data_len: %lu", data_len));
1250 result= ((data_len < LOG_EVENT_MINIMAL_HEADER_LEN) ? LOG_READ_BOGUS :
1251 LOG_READ_TOO_LARGE);
1252 goto end;
1253 }
1254
1255 /*
1256 If the event header wasn't passed, the caller doesn't know the event size
1257 yet, so the packet size may not have enough space to load the entire
1258 event. We need to adjust the packet size here since the call to my_b_read()
1259 below expects the buffer to be allocated.
1260 */
1261 if (buf == local_buf)
1262 {
1263 ulong new_alloc_len= packet->length() + data_len;
1264 if (new_alloc_len > packet->alloced_length() &&
1265 packet->mem_realloc(new_alloc_len))
1266 {
1267 /* Failed to allocate packet */
1268 result= LOG_READ_MEM;
1269 goto end;
1270 }
1271 }
1272
1273 /* Check packet buffer size and append the log event header to it */
1274 if (packet->alloced_length() - packet->length() < data_len ||
1275 packet->append(buf, LOG_EVENT_MINIMAL_HEADER_LEN))
1276 {
1277 DBUG_PRINT("info", ("first packet->append failed (out of memory)"));
1278 /* Failed to allocate packet */
1279 result= LOG_READ_MEM;
1280 goto end;
1281 }
1282 data_len-= LOG_EVENT_MINIMAL_HEADER_LEN;
1283 if (data_len)
1284 {
1285 /*
1286 Append rest of event, read directly from file into packet.
1287
1288 We are avoiding to call packet->append(IO_CACHE, size_t) at this point
1289 because the String::append logic will call String::mem_realloc() that
1290 might resize the buffer (changing its pointer) in order to reserve a
1291 space for a trailing '\0' that we don't need.
1292 */
1293 char *event_data_buffer= const_cast<char*>(packet->ptr() +
1294 packet->length());
1295 result= my_b_read(file,
1296 reinterpret_cast<uchar*>(event_data_buffer),
1297 data_len);
1298 if (result)
1299 {
1300 /*
1301 Fatal error occured when appending rest of the event
1302 to packet, possible failures:
1303 1. EOF occured when reading from file, it's really an error
1304 as data_len is >=0 there's supposed to be more bytes available.
1305 file->error will have been set to number of bytes left to read
1306 2. Read was interrupted, file->error would normally be set to -1
1307 3. Failed to allocate memory for packet, my_errno
1308 will be ENOMEM(file->error shuold be 0, but since the
1309 memory allocation occurs before the call to read it might
1310 be uninitialized)
1311 */
1312 DBUG_PRINT("info", ("second packet->append failed (out of memory)"));
1313 result= (my_errno() == ENOMEM ? LOG_READ_MEM :
1314 (file->error >= 0 ? LOG_READ_TRUNC: LOG_READ_IO));
1315 goto end;
1316 }
1317 else
1318 {
1319 packet->length(packet->length() + data_len);
1320
1321 if (fdle != NULL && fdle->crypto_data.is_enabled())
1322 {
1323 size_t true_data_len= data_len + LOG_EVENT_MINIMAL_HEADER_LEN;
1324
1325 char *decrypted_packet=
1326 reinterpret_cast<char*>(my_malloc(key_memory_log_event, true_data_len + ev_offset + 1,
1327 MYF(MY_WME)));
1328 if (!decrypted_packet)
1329 DBUG_RETURN(LOG_READ_MEM);
1330 memcpy(decrypted_packet, packet->ptr(), ev_offset);
1331
1332 uchar *src= (uchar*)packet->ptr() + ev_offset;
1333 uchar *dst= (uchar*)decrypted_packet + ev_offset;
1334 memcpy(src + EVENT_LEN_OFFSET, src, 4);
1335
1336 if (decrypt_event(my_b_tell(file) - true_data_len, fdle->crypto_data, src, dst, true_data_len))
1337 {
1338 my_free(decrypted_packet);
1339 DBUG_RETURN(LOG_READ_DECRYPT);
1340 }
1341
1342 packet->length(0); // size of the content
1343 packet->append(decrypted_packet, true_data_len + ev_offset);
1344 my_free(decrypted_packet);
1345 }
1346 /*
1347 Corrupt the event for Dump thread.
1348 We also need to exclude Previous_gtids_log_event and Gtid_log_event
1349 events from injected corruption to allow dump thread to move forward
1350 on binary log until the missing transactions from slave when
1351 MASTER_AUTO_POSITION= 1.
1352 */
1353 DBUG_EXECUTE_IF("corrupt_read_log_event",
1354 uchar *debug_event_buf_c = (uchar*) packet->ptr() + ev_offset;
1355 if (debug_event_buf_c[EVENT_TYPE_OFFSET] != binary_log::FORMAT_DESCRIPTION_EVENT &&
1356 debug_event_buf_c[EVENT_TYPE_OFFSET] != binary_log::PREVIOUS_GTIDS_LOG_EVENT &&
1357 debug_event_buf_c[EVENT_TYPE_OFFSET] != binary_log::GTID_LOG_EVENT &&
1358 debug_event_buf_c[EVENT_TYPE_OFFSET] != binary_log::START_ENCRYPTION_EVENT)
1359 {
1360 int debug_cor_pos = rand() % (data_len + LOG_EVENT_MINIMAL_HEADER_LEN -
1361 BINLOG_CHECKSUM_LEN);
1362 debug_event_buf_c[debug_cor_pos] =~ debug_event_buf_c[debug_cor_pos];
1363 DBUG_PRINT("info", ("Corrupt the event at Log_event::read_log_event: byte on position %d", debug_cor_pos));
1364 }
1365 );
1366 /*
1367 CRC verification of the Dump thread
1368 */
1369 binary_log_debug::debug_checksum_test=
1370 DBUG_EVALUATE_IF("simulate_checksum_test_failure", true, false);
1371
1372 if (opt_master_verify_checksum &&
1373 Log_event_footer::event_checksum_test((uchar*)packet->ptr() + ev_offset,
1374 data_len + LOG_EVENT_MINIMAL_HEADER_LEN,
1375 checksum_alg_arg))
1376 {
1377 DBUG_PRINT("info", ("checksum test failed"));
1378 result= LOG_READ_CHECKSUM_FAILURE;
1379 goto end;
1380 }
1381 }
1382 }
1383
1384 end:
1385 if (log_lock)
1386 mysql_mutex_unlock(log_lock);
1387 DBUG_PRINT("info", ("read_log_event returns %d", result));
1388 DBUG_RETURN(result);
1389 }
1390 #endif /* !MYSQL_CLIENT */
1391
1392 #ifndef MYSQL_CLIENT
1393 #define UNLOCK_MUTEX if (log_lock) mysql_mutex_unlock(log_lock);
1394 #define LOCK_MUTEX if (log_lock) mysql_mutex_lock(log_lock);
1395 #else
1396 #define UNLOCK_MUTEX
1397 #define LOCK_MUTEX
1398 #endif
1399
1400 #ifndef MYSQL_CLIENT
1401 /**
1402 @note
1403 Allocates memory; The caller is responsible for clean-up.
1404 */
read_log_event(IO_CACHE * file,mysql_mutex_t * log_lock,const Format_description_log_event * description_event,my_bool crc_check)1405 Log_event* Log_event::read_log_event(IO_CACHE* file,
1406 mysql_mutex_t* log_lock,
1407 const Format_description_log_event
1408 *description_event,
1409 my_bool crc_check)
1410 #else
1411 Log_event* Log_event::read_log_event(IO_CACHE* file,
1412 const Format_description_log_event
1413 *description_event,
1414 my_bool crc_check,
1415 read_log_event_filter_function f)
1416 #endif
1417 {
1418 DBUG_ENTER("Log_event::read_log_event(IO_CACHE *[, mysql_mutex_t *], Format_description_log_event *, my_bool)");
1419 assert(description_event != 0);
1420 char head[LOG_EVENT_MINIMAL_HEADER_LEN];
1421 /*
1422 First we only want to read at most LOG_EVENT_MINIMAL_HEADER_LEN, just to
1423 check the event for sanity and to know its length; no need to really parse
1424 it. We say "at most" because this could be a 3.23 master, which has header
1425 of 13 bytes, whereas LOG_EVENT_MINIMAL_HEADER_LEN is 19 bytes (it's
1426 "minimal" over the set {MySQL >=4.0}).
1427 */
1428 uint header_size= min<uint>(description_event->common_header_len,
1429 LOG_EVENT_MINIMAL_HEADER_LEN);
1430
1431 LOCK_MUTEX;
1432 DBUG_PRINT("info", ("my_b_tell: %lu", (ulong) my_b_tell(file)));
1433 if (my_b_read(file, (uchar *) head, header_size))
1434 {
1435 DBUG_PRINT("info", ("Log_event::read_log_event(IO_CACHE*,Format_desc*) "
1436 "failed in my_b_read((IO_CACHE*)%p, (uchar*)%p, %u)",
1437 file, head, header_size));
1438 UNLOCK_MUTEX;
1439 /*
1440 No error here; it could be that we are at the file's end. However
1441 if the next my_b_read() fails (below), it will be an error as we
1442 were able to read the first bytes.
1443 */
1444 DBUG_RETURN(0);
1445 }
1446 ulong data_len = uint4korr(head + EVENT_LEN_OFFSET);
1447 char *buf= 0;
1448 const char *error= 0;
1449 Log_event *res= 0;
1450 #if !defined(MYSQL_SERVER) && !defined(EMBEDDED_LIBRARY)
1451 ulong log_max_allowed_packet = 0;
1452 mysql_get_option(NULL, MYSQL_OPT_MAX_ALLOWED_PACKET,
1453 &log_max_allowed_packet);
1454 #else
1455 THD *thd=current_thd;
1456 uint log_max_allowed_packet= thd ? slave_max_allowed_packet : ~0U;
1457 #endif
1458
1459 ulong const max_size=
1460 max<ulong>(log_max_allowed_packet,
1461 opt_binlog_rows_event_max_size + MAX_LOG_EVENT_HEADER);
1462 if (data_len > max_size)
1463 {
1464 error = "Event too big";
1465 goto err;
1466 }
1467
1468 if (data_len < header_size)
1469 {
1470 error = "Event invalid";
1471 goto err;
1472 }
1473
1474 // some events use the extra byte to null-terminate strings
1475 if (!(buf = (char*) my_malloc(key_memory_log_event,
1476 data_len+1, MYF(MY_WME))))
1477 {
1478 error = "Out of memory";
1479 goto err;
1480 }
1481 buf[data_len] = 0;
1482 memcpy(buf, head, header_size);
1483 if (my_b_read(file, (uchar*) buf + header_size, data_len - header_size))
1484 {
1485 error = "read error";
1486 goto err;
1487 }
1488
1489 if (description_event->crypto_data.is_enabled())
1490 {
1491 #if defined(MYSQL_CLIENT)
1492 // Clients do not have access to keyring and thus cannot decrypt
1493 // binlog events
1494 error= "Decryption error as clients do not have access to keyring and thus "
1495 "cannot decrypt binlog events.";
1496 goto err;
1497 #endif
1498 char *dst_buf=
1499 reinterpret_cast<char*>(my_malloc(key_memory_log_event, data_len + 1, MYF(MY_WME)));
1500 dst_buf[data_len]=0;
1501 memcpy(dst_buf, buf, data_len);
1502
1503 if (decrypt_event(my_b_tell(file) - data_len, description_event->crypto_data, (uchar*)buf, (uchar*)dst_buf, data_len))
1504 {
1505 my_free(dst_buf);
1506 error= "decryption error";
1507 goto err;
1508 }
1509
1510 my_free(buf);
1511 buf= dst_buf;
1512 }
1513
1514 #if defined(MYSQL_CLIENT)
1515 if (f && f(&buf, &data_len, description_event))
1516 {
1517 error = "Error applying filter while reading event";
1518 goto err;
1519 }
1520 #endif
1521 if ((res= read_log_event(buf, data_len, &error, description_event, crc_check)))
1522 res->register_temp_buf(buf);
1523
1524 err:
1525 UNLOCK_MUTEX;
1526 if (!res)
1527 {
1528 assert(error != 0);
1529 /* Don't log error if read_log_event invoked from SHOW BINLOG EVENTS */
1530 #ifdef MYSQL_CLIENT
1531 if (force_opt)
1532 DBUG_RETURN(new Unknown_log_event());
1533 #endif
1534 #ifdef MYSQL_SERVER
1535 THD *thd= current_thd;
1536 if (!(thd && thd->lex &&
1537 thd->lex->sql_command == SQLCOM_SHOW_BINLOG_EVENTS)) {
1538 #endif
1539 sql_print_error("Error in Log_event::read_log_event(): "
1540 "'%s', data_len: %lu, event_type: %d",
1541 error,data_len,head[EVENT_TYPE_OFFSET]);
1542 #ifdef MYSQL_SERVER
1543 }
1544 #endif
1545 my_free(buf);
1546 /*
1547 The SQL slave thread will check if file->error<0 to know
1548 if there was an I/O error. Even if there is no "low-level" I/O errors
1549 with 'file', any of the high-level above errors is worrying
1550 enough to stop the SQL thread now ; as we are skipping the current event,
1551 going on with reading and successfully executing other events can
1552 only corrupt the slave's databases. So stop.
1553 The file->error is also checked to record the position of
1554 the last valid event when master server recovers.
1555 */
1556 file->error= -1;
1557 }
1558 DBUG_RETURN(res);
1559 }
1560
1561
1562 /**
1563 Binlog format tolerance is in (buf, event_len, description_event)
1564 constructors.
1565 */
1566
read_log_event(const char * buf,uint event_len,const char ** error,const Format_description_log_event * description_event,my_bool crc_check)1567 Log_event* Log_event::read_log_event(const char* buf, uint event_len,
1568 const char **error,
1569 const Format_description_log_event *description_event,
1570 my_bool crc_check)
1571 {
1572 Log_event* ev= NULL;
1573 enum_binlog_checksum_alg alg;
1574 DBUG_ENTER("Log_event::read_log_event(char *, uint, char **, Format_description_log_event *, my_bool)");
1575 assert(description_event != 0);
1576 DBUG_PRINT("info", ("binlog_version: %d", description_event->binlog_version));
1577 DBUG_DUMP("data", (unsigned char*) buf, event_len);
1578
1579 #ifdef MYSQL_CLIENT
1580 static bool was_start_encryption_event = false;
1581 if (was_start_encryption_event)
1582 {
1583 // We know that binlog is encrypted (as we read Start_encryption event) and we know that
1584 // client applications cannot decrypt encrypted binlogs as they have no access to
1585 // keyring. Thus we return Unknown_event for all encrypted events when force is used
1586 // and close mysqlbinlog when no force.
1587 if (!force_opt)
1588 {
1589 *error= "No point in reading encrypted binlog - quitting. "
1590 "Start mysqlbinlog with --force-read if you want to attempt "
1591 "to read an encrypted binlog without decryption.";
1592 DBUG_RETURN(0);
1593 }
1594 DBUG_RETURN(new Unknown_log_event);
1595 }
1596 #endif
1597
1598 /* Check the integrity */
1599 if (event_len < EVENT_LEN_OFFSET ||
1600 event_len != uint4korr(buf+EVENT_LEN_OFFSET))
1601 {
1602 DBUG_PRINT("error", ("event_len=%u EVENT_LEN_OFFSET=%d "
1603 "buf[EVENT_TYPE_OFFSET]=%d ENUM_END_EVENT=%d "
1604 "uint4korr(buf+EVENT_LEN_OFFSET)=%d",
1605 event_len, EVENT_LEN_OFFSET,
1606 buf[EVENT_TYPE_OFFSET], binary_log::ENUM_END_EVENT,
1607 uint4korr(buf+EVENT_LEN_OFFSET)));
1608 *error="Sanity check failed"; // Needed to free buffer
1609 DBUG_RETURN(NULL); // general sanity check - will fail on a partial read
1610 }
1611
1612 uint event_type= static_cast<uchar>(buf[EVENT_TYPE_OFFSET]);
1613 // all following START events in the current file are without checksum
1614 if (event_type == binary_log::START_EVENT_V3)
1615 (const_cast<Format_description_log_event*>(description_event))->
1616 common_footer->checksum_alg= binary_log::BINLOG_CHECKSUM_ALG_OFF;
1617 // Sanity check for Format description event
1618 if (event_type == binary_log::FORMAT_DESCRIPTION_EVENT)
1619 {
1620 if (event_len < LOG_EVENT_MINIMAL_HEADER_LEN +
1621 ST_COMMON_HEADER_LEN_OFFSET)
1622 {
1623 *error= "Found invalid Format description event in binary log";
1624 DBUG_RETURN(0);
1625 }
1626 uint tmp_header_len= buf[LOG_EVENT_MINIMAL_HEADER_LEN + ST_COMMON_HEADER_LEN_OFFSET];
1627 if (event_len < tmp_header_len + ST_SERVER_VER_OFFSET + ST_SERVER_VER_LEN)
1628 {
1629 *error= "Found invalid Format description event in binary log";
1630 DBUG_RETURN(0);
1631 }
1632 }
1633 /*
1634 CRC verification by SQL and Show-Binlog-Events master side.
1635 The caller has to provide @description_event->checksum_alg to
1636 be the last seen FD's (A) descriptor.
1637 If event is FD the descriptor is in it.
1638 Notice, FD of the binlog can be only in one instance and therefore
1639 Show-Binlog-Events executing master side thread needs just to know
1640 the only FD's (A) value - whereas RL can contain more.
1641 In the RL case, the alg is kept in FD_e (@description_event) which is reset
1642 to the newer read-out event after its execution with possibly new alg descriptor.
1643 Therefore in a typical sequence of RL:
1644 {FD_s^0, FD_m, E_m^1} E_m^1
1645 will be verified with (A) of FD_m.
1646
1647 See legends definition on MYSQL_BIN_LOG::relay_log_checksum_alg docs
1648 lines (log.h).
1649
1650 Notice, a pre-checksum FD version forces alg := BINLOG_CHECKSUM_ALG_UNDEF.
1651 */
1652 alg= (event_type != binary_log::FORMAT_DESCRIPTION_EVENT) ?
1653 description_event->common_footer->checksum_alg :
1654 Log_event_footer::get_checksum_alg(buf, event_len);
1655 // Emulate the corruption during reading an event
1656 DBUG_EXECUTE_IF("corrupt_read_log_event_char",
1657 if (event_type != binary_log::FORMAT_DESCRIPTION_EVENT &&
1658 event_type != binary_log::START_ENCRYPTION_EVENT)
1659 {
1660 char *debug_event_buf_c = (char *)buf;
1661 int debug_cor_pos = rand() % (event_len - BINLOG_CHECKSUM_LEN);
1662 debug_event_buf_c[debug_cor_pos] =~ debug_event_buf_c[debug_cor_pos];
1663 DBUG_PRINT("info", ("Corrupt the event at Log_event::read_log_event(char*,...): byte on position %d", debug_cor_pos));
1664 DBUG_SET("");
1665 }
1666 );
1667
1668 #ifndef NDEBUG
1669 binary_log_debug::debug_checksum_test=
1670 DBUG_EVALUATE_IF("simulate_checksum_test_failure", true, false);
1671 #endif
1672 if (crc_check &&
1673 Log_event_footer::event_checksum_test((uchar *) buf, event_len, alg) &&
1674 /* Skip the crc check when simulating an unknown ignorable log event. */
1675 !DBUG_EVALUATE_IF("simulate_unknown_ignorable_log_event", 1, 0))
1676 {
1677 *error= "Event crc check failed! Most likely there is event corruption.";
1678 #ifdef MYSQL_CLIENT
1679 if (force_opt)
1680 {
1681 ev= new Unknown_log_event(buf, description_event);
1682 DBUG_RETURN(ev);
1683 }
1684 #endif
1685 DBUG_RETURN(NULL);
1686 }
1687
1688 if (event_type > description_event->number_of_event_types &&
1689 event_type != binary_log::FORMAT_DESCRIPTION_EVENT &&
1690 event_type != binary_log::START_ENCRYPTION_EVENT &&
1691 /*
1692 Skip the event type check when simulating an
1693 unknown ignorable log event.
1694 */
1695 !DBUG_EVALUATE_IF("simulate_unknown_ignorable_log_event", 1, 0))
1696 {
1697 /*
1698 It is unsafe to use the description_event if its post_header_len
1699 array does not include the event type.
1700 */
1701 DBUG_PRINT("error", ("event type %d found, but the current "
1702 "Format_description_log_event supports only %d event "
1703 "types", event_type,
1704 description_event->number_of_event_types));
1705 ev= NULL;
1706 }
1707 else
1708 {
1709 /*
1710 In some previuos versions (see comment in
1711 Format_description_log_event::Format_description_log_event(char*,...)),
1712 event types were assigned different id numbers than in the
1713 present version. In order to replicate from such versions to the
1714 present version, we must map those event type id's to our event
1715 type id's. The mapping is done with the event_type_permutation
1716 array, which was set up when the Format_description_log_event
1717 was read.
1718 */
1719 if (description_event->event_type_permutation)
1720 {
1721 uint new_event_type;
1722 if (event_type >= EVENT_TYPE_PERMUTATION_NUM)
1723 /* Safe guard for read out of bounds of event_type_permutation. */
1724 new_event_type= binary_log::UNKNOWN_EVENT;
1725 else
1726 new_event_type= description_event->event_type_permutation[event_type];
1727
1728 DBUG_PRINT("info", ("converting event type %d to %d (%s)",
1729 event_type, new_event_type,
1730 get_type_str((Log_event_type)new_event_type)));
1731 event_type= new_event_type;
1732 }
1733
1734 if (alg != binary_log::BINLOG_CHECKSUM_ALG_UNDEF &&
1735 (event_type == binary_log::FORMAT_DESCRIPTION_EVENT ||
1736 alg != binary_log::BINLOG_CHECKSUM_ALG_OFF))
1737 event_len= event_len - BINLOG_CHECKSUM_LEN;
1738
1739 switch(event_type) {
1740 case binary_log::QUERY_EVENT:
1741 #ifndef NDEBUG
1742 binary_log_debug::debug_query_mts_corrupt_db_names=
1743 DBUG_EVALUATE_IF("query_log_event_mts_corrupt_db_names", true, false);
1744 #endif
1745 ev = new Query_log_event(buf, event_len, description_event,
1746 binary_log::QUERY_EVENT);
1747 break;
1748 case binary_log::LOAD_EVENT:
1749 case binary_log::NEW_LOAD_EVENT:
1750 #ifndef NDEBUG
1751 binary_log_debug::debug_simulate_invalid_address=
1752 DBUG_EVALUATE_IF("simulate_invalid_address", true, false);
1753 #endif
1754 ev = new Load_log_event(buf, event_len, description_event);
1755 break;
1756 case binary_log::ROTATE_EVENT:
1757 ev = new Rotate_log_event(buf, event_len, description_event);
1758 break;
1759 case binary_log::CREATE_FILE_EVENT:
1760 #ifndef NDEBUG
1761 binary_log_debug::debug_simulate_invalid_address=
1762 DBUG_EVALUATE_IF("simulate_invalid_address", true, false);
1763 #endif
1764 ev = new Create_file_log_event(buf, event_len, description_event);
1765 break;
1766 case binary_log::APPEND_BLOCK_EVENT:
1767 ev = new Append_block_log_event(buf, event_len, description_event);
1768 break;
1769 case binary_log::DELETE_FILE_EVENT:
1770 ev = new Delete_file_log_event(buf, event_len, description_event);
1771 break;
1772 case binary_log::EXEC_LOAD_EVENT:
1773 ev = new Execute_load_log_event(buf, event_len, description_event);
1774 break;
1775 case binary_log::START_EVENT_V3: /* this is sent only by MySQL <=4.x */
1776 ev = new Start_log_event_v3(buf, event_len, description_event);
1777 break;
1778 case binary_log::STOP_EVENT:
1779 ev = new Stop_log_event(buf, description_event);
1780 break;
1781 case binary_log::INTVAR_EVENT:
1782 ev = new Intvar_log_event(buf, description_event);
1783 break;
1784 case binary_log::XID_EVENT:
1785 ev = new Xid_log_event(buf, description_event);
1786 break;
1787 case binary_log::RAND_EVENT:
1788 ev = new Rand_log_event(buf, description_event);
1789 break;
1790 case binary_log::USER_VAR_EVENT:
1791 ev = new User_var_log_event(buf, event_len, description_event);
1792 break;
1793 case binary_log::FORMAT_DESCRIPTION_EVENT:
1794 ev = new Format_description_log_event(buf, event_len, description_event);
1795 break;
1796 #if defined(HAVE_REPLICATION)
1797 case binary_log::PRE_GA_WRITE_ROWS_EVENT:
1798 ev = new Write_rows_log_event_old(buf, event_len, description_event);
1799 break;
1800 case binary_log::PRE_GA_UPDATE_ROWS_EVENT:
1801 ev = new Update_rows_log_event_old(buf, event_len, description_event);
1802 break;
1803 case binary_log::PRE_GA_DELETE_ROWS_EVENT:
1804 ev = new Delete_rows_log_event_old(buf, event_len, description_event);
1805 break;
1806 case binary_log::WRITE_ROWS_EVENT_V1:
1807 if (!(description_event->post_header_len.empty()))
1808 ev = new Write_rows_log_event(buf, event_len, description_event);
1809 break;
1810 case binary_log::UPDATE_ROWS_EVENT_V1:
1811 if (!(description_event->post_header_len.empty()))
1812 ev = new Update_rows_log_event(buf, event_len, description_event);
1813 break;
1814 case binary_log::DELETE_ROWS_EVENT_V1:
1815 if (!(description_event->post_header_len.empty()))
1816 ev = new Delete_rows_log_event(buf, event_len, description_event);
1817 break;
1818 case binary_log::TABLE_MAP_EVENT:
1819 if (!(description_event->post_header_len.empty()))
1820 ev = new Table_map_log_event(buf, event_len, description_event);
1821 break;
1822 #endif
1823 case binary_log::BEGIN_LOAD_QUERY_EVENT:
1824 ev = new Begin_load_query_log_event(buf, event_len, description_event);
1825 break;
1826 case binary_log::EXECUTE_LOAD_QUERY_EVENT:
1827 ev= new Execute_load_query_log_event(buf, event_len, description_event);
1828 break;
1829 case binary_log::INCIDENT_EVENT:
1830 ev = new Incident_log_event(buf, event_len, description_event);
1831 break;
1832 case binary_log::START_ENCRYPTION_EVENT:
1833 ev = new Start_encryption_log_event(buf, event_len, description_event);
1834 #ifdef MYSQL_CLIENT
1835 was_start_encryption_event= true;
1836 #endif
1837 break;
1838 case binary_log::ROWS_QUERY_LOG_EVENT:
1839 ev= new Rows_query_log_event(buf, event_len, description_event);
1840 break;
1841 case binary_log::GTID_LOG_EVENT:
1842 case binary_log::ANONYMOUS_GTID_LOG_EVENT:
1843 ev= new Gtid_log_event(buf, event_len, description_event);
1844 break;
1845 case binary_log::PREVIOUS_GTIDS_LOG_EVENT:
1846 ev= new Previous_gtids_log_event(buf, event_len, description_event);
1847 break;
1848 #if defined(HAVE_REPLICATION)
1849 case binary_log::WRITE_ROWS_EVENT:
1850 ev = new Write_rows_log_event(buf, event_len, description_event);
1851 break;
1852 case binary_log::UPDATE_ROWS_EVENT:
1853 ev = new Update_rows_log_event(buf, event_len, description_event);
1854 break;
1855 case binary_log::DELETE_ROWS_EVENT:
1856 ev = new Delete_rows_log_event(buf, event_len, description_event);
1857 break;
1858 case binary_log::TRANSACTION_CONTEXT_EVENT:
1859 ev = new Transaction_context_log_event(buf, event_len, description_event);
1860 break;
1861 case binary_log::VIEW_CHANGE_EVENT:
1862 ev = new View_change_log_event(buf, event_len, description_event);
1863 break;
1864 #endif
1865 case binary_log::XA_PREPARE_LOG_EVENT:
1866 ev= new XA_prepare_log_event(buf, description_event);
1867 break;
1868 default:
1869 /*
1870 Create an object of Ignorable_log_event for unrecognized sub-class.
1871 So that SLAVE SQL THREAD will only update the position and continue.
1872 */
1873 if (uint2korr(buf + FLAGS_OFFSET) & LOG_EVENT_IGNORABLE_F)
1874 {
1875 ev= new Ignorable_log_event(buf, description_event);
1876 }
1877 else
1878 {
1879 DBUG_PRINT("error",("Unknown event code: %d",
1880 (int) buf[EVENT_TYPE_OFFSET]));
1881 ev= NULL;
1882 }
1883 break;
1884 }
1885 }
1886
1887 if (ev)
1888 {
1889 ev->common_footer->checksum_alg= alg;
1890 if (ev->common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_OFF &&
1891 ev->common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_UNDEF)
1892 ev->crc= uint4korr(buf + (event_len));
1893 }
1894
1895 DBUG_PRINT("read_event", ("%s(type_code: %d; event_len: %d)",
1896 ev ? ev->get_type_str() : "<unknown>",
1897 buf[EVENT_TYPE_OFFSET],
1898 event_len));
1899 /*
1900 is_valid is used for small event-specific sanity tests which are
1901 important; for example there are some my_malloc() in constructors
1902 (e.g. Query_log_event::Query_log_event(char*...)); when these
1903 my_malloc() fail we can't return an error out of the constructor
1904 (because constructor is "void") ; so instead we leave the pointer we
1905 wanted to allocate (e.g. 'query') to 0 and we test it and set the
1906 value of is_valid to true or false based on the test.
1907 Same for Format_description_log_event, member 'post_header_len'.
1908
1909 SLAVE_EVENT is never used, so it should not be read ever.
1910 */
1911 if (!ev || !ev->is_valid() || (event_type == binary_log::SLAVE_EVENT))
1912 {
1913 DBUG_PRINT("error",("Found invalid event in binary log"));
1914 delete ev;
1915 #ifdef MYSQL_CLIENT
1916 if (!force_opt) /* then mysqlbinlog dies */
1917 {
1918 *error= "Found invalid event in binary log";
1919 DBUG_RETURN(0);
1920 }
1921 ev= new Unknown_log_event(buf, description_event);
1922 #else
1923 *error= "Found invalid event in binary log";
1924 DBUG_RETURN(0);
1925 #endif
1926 }
1927 DBUG_RETURN(ev);
1928 }
1929
1930 #ifdef MYSQL_CLIENT
1931
1932 /*
1933 Log_event::print_header()
1934 */
1935
print_header(IO_CACHE * file,PRINT_EVENT_INFO * print_event_info,bool is_more MY_ATTRIBUTE ((unused)))1936 void Log_event::print_header(IO_CACHE* file,
1937 PRINT_EVENT_INFO* print_event_info,
1938 bool is_more MY_ATTRIBUTE((unused)))
1939 {
1940 MY_ATTRIBUTE((unused)) int write_res;
1941 char llbuff[22];
1942 my_off_t hexdump_from= print_event_info->hexdump_from;
1943 DBUG_ENTER("Log_event::print_header");
1944
1945 my_b_printf(file, "#");
1946 print_timestamp(file, NULL);
1947 my_b_printf(file, " server id %lu end_log_pos %s ", (ulong) server_id,
1948 llstr(common_header->log_pos,llbuff));
1949
1950 /* print the checksum */
1951
1952 if (common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_OFF &&
1953 common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_UNDEF)
1954 {
1955 char checksum_buf[BINLOG_CHECKSUM_LEN * 2 + 4]; // to fit to "0x%lx "
1956 size_t const bytes_written=
1957 my_snprintf(checksum_buf, sizeof(checksum_buf), "0x%08lx ", (ulong) crc);
1958 my_b_printf(file, "%s ", get_type(&binlog_checksum_typelib,
1959 common_footer->checksum_alg));
1960 my_b_printf(file, checksum_buf, bytes_written);
1961 }
1962
1963 /* mysqlbinlog --hexdump */
1964 if (print_event_info->hexdump_from)
1965 {
1966 my_b_printf(file, "\n");
1967 uchar *ptr= (uchar*)temp_buf;
1968 my_off_t size=
1969 uint4korr(ptr + EVENT_LEN_OFFSET) - LOG_EVENT_MINIMAL_HEADER_LEN;
1970 my_off_t i;
1971
1972 /* Header len * 4 >= header len * (2 chars + space + extra space) */
1973 char *h, hex_string[49]= {0};
1974 char *c, char_string[16+1]= {0};
1975
1976 /* Pretty-print event common header if header is exactly 19 bytes */
1977 if (print_event_info->common_header_len == LOG_EVENT_MINIMAL_HEADER_LEN)
1978 {
1979 char emit_buf[256]; // Enough for storing one line
1980 my_b_printf(file, "# Position Timestamp Type Master ID "
1981 "Size Master Pos Flags \n");
1982 size_t const bytes_written=
1983 my_snprintf(emit_buf, sizeof(emit_buf),
1984 "# %8.8lx %02x %02x %02x %02x %02x "
1985 "%02x %02x %02x %02x %02x %02x %02x %02x "
1986 "%02x %02x %02x %02x %02x %02x\n",
1987 (unsigned long) hexdump_from,
1988 ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6],
1989 ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13],
1990 ptr[14], ptr[15], ptr[16], ptr[17], ptr[18]);
1991 assert(static_cast<size_t>(bytes_written) < sizeof(emit_buf));
1992 write_res= my_b_write(file, (uchar*) emit_buf, bytes_written);
1993 assert(write_res == 0);
1994 ptr += LOG_EVENT_MINIMAL_HEADER_LEN;
1995 hexdump_from += LOG_EVENT_MINIMAL_HEADER_LEN;
1996 }
1997
1998 /* Rest of event (without common header) */
1999 for (i= 0, c= char_string, h=hex_string;
2000 i < size;
2001 i++, ptr++)
2002 {
2003 my_snprintf(h, 4, (i % 16 <= 7) ? "%02x " : " %02x", *ptr);
2004 h += 3;
2005
2006 *c++= my_isalnum(&my_charset_bin, *ptr) ? *ptr : '.';
2007
2008 if (i % 16 == 15)
2009 {
2010 /*
2011 my_b_printf() does not support full printf() formats, so we
2012 have to do it this way.
2013
2014 TODO: Rewrite my_b_printf() to support full printf() syntax.
2015 */
2016 char emit_buf[256];
2017 size_t const bytes_written=
2018 my_snprintf(emit_buf, sizeof(emit_buf),
2019 "# %8.8lx %-48.48s |%16s|\n",
2020 (unsigned long) (hexdump_from + (i & 0xfffffff0)),
2021 hex_string, char_string);
2022 assert(static_cast<size_t>(bytes_written) < sizeof(emit_buf));
2023 write_res= my_b_write(file, (uchar*) emit_buf, bytes_written);
2024 assert(write_res == 0);
2025 hex_string[0]= 0;
2026 char_string[0]= 0;
2027 c= char_string;
2028 h= hex_string;
2029 }
2030 }
2031 *c= '\0';
2032 assert(hex_string[48] == 0);
2033
2034 if (hex_string[0])
2035 {
2036 char emit_buf[256];
2037 // Right-pad hex_string with spaces, up to 48 characters.
2038 memset(h, ' ', (sizeof(hex_string) -1) - (h - hex_string));
2039 size_t const bytes_written=
2040 my_snprintf(emit_buf, sizeof(emit_buf),
2041 "# %8.8lx %-48.48s |%s|\n",
2042 (unsigned long) (hexdump_from + (i & 0xfffffff0)),
2043 hex_string, char_string);
2044 assert(static_cast<size_t>(bytes_written) < sizeof(emit_buf));
2045 write_res= my_b_write(file, (uchar*) emit_buf, bytes_written);
2046 assert(write_res == 0);
2047 }
2048 /*
2049 need a # to prefix the rest of printouts for example those of
2050 Rows_log_event::print_helper().
2051 */
2052 write_res= my_b_write(file, reinterpret_cast<const uchar*>("# "), 2);
2053 assert(write_res == 0);
2054 }
2055 DBUG_VOID_RETURN;
2056 }
2057
2058
2059 /**
2060 Prints a quoted string to io cache.
2061 Control characters are displayed as hex sequence, e.g. \x00
2062
2063 @param[in] file IO cache
2064 @param[in] prt Pointer to string
2065 @param[in] length String length
2066 */
2067
2068 static void
my_b_write_quoted(IO_CACHE * file,const uchar * ptr,uint length)2069 my_b_write_quoted(IO_CACHE *file, const uchar *ptr, uint length)
2070 {
2071 MY_ATTRIBUTE((unused)) int write_res;
2072 const uchar *s;
2073 my_b_printf(file, "'");
2074 for (s= ptr; length > 0 ; s++, length--)
2075 {
2076 if (*s > 0x1F && *s != '\'' && *s != '\\')
2077 {
2078 write_res= my_b_write(file, s, 1);
2079 assert(write_res == 0);
2080 }
2081 else
2082 {
2083 uchar hex[10];
2084 size_t len= my_snprintf((char*) hex, sizeof(hex), "%s%02x", "\\x", *s);
2085 write_res = my_b_write(file, hex, len);
2086 assert(write_res == 0);
2087 }
2088 }
2089 my_b_printf(file, "'");
2090 }
2091
2092 /**
2093 Prints a bit string to io cache in format b'1010'.
2094
2095 @param[in] file IO cache
2096 @param[in] ptr Pointer to string
2097 @param[in] nbits Number of bits
2098 */
2099 static void
my_b_write_bit(IO_CACHE * file,const uchar * ptr,uint nbits)2100 my_b_write_bit(IO_CACHE *file, const uchar *ptr, uint nbits)
2101 {
2102 uint bitnum, nbits8= ((nbits + 7) / 8) * 8, skip_bits= nbits8 - nbits;
2103 my_b_printf(file, "b'");
2104 for (bitnum= skip_bits ; bitnum < nbits8; bitnum++)
2105 {
2106 int is_set= (ptr[(bitnum) / 8] >> (7 - bitnum % 8)) & 0x01;
2107 MY_ATTRIBUTE((unused)) int write_res=
2108 my_b_write(file, (const uchar*) (is_set ? "1" : "0"), 1);
2109 assert(write_res == 0);
2110 }
2111 my_b_printf(file, "'");
2112 }
2113
2114
2115 /**
2116 Prints a packed string to io cache.
2117 The string consists of length packed to 1 or 2 bytes,
2118 followed by string data itself.
2119
2120 @param[in] file IO cache
2121 @param[in] ptr Pointer to string
2122 @param[in] length String size
2123
2124 @retval - number of bytes scanned.
2125 */
2126 static size_t
my_b_write_quoted_with_length(IO_CACHE * file,const uchar * ptr,uint length)2127 my_b_write_quoted_with_length(IO_CACHE *file, const uchar *ptr, uint length)
2128 {
2129 if (length < 256)
2130 {
2131 length= *ptr;
2132 my_b_write_quoted(file, ptr + 1, length);
2133 return length + 1;
2134 }
2135 else
2136 {
2137 length= uint2korr(ptr);
2138 my_b_write_quoted(file, ptr + 2, length);
2139 return length + 2;
2140 }
2141 }
2142
2143
2144 /**
2145 Prints a 32-bit number in both signed and unsigned representation
2146
2147 @param[in] file IO cache
2148 @param[in] sl Signed number
2149 @param[in] ul Unsigned number
2150 */
2151 static void
my_b_write_sint32_and_uint32(IO_CACHE * file,int32 si,uint32 ui)2152 my_b_write_sint32_and_uint32(IO_CACHE *file, int32 si, uint32 ui)
2153 {
2154 my_b_printf(file, "%d", si);
2155 if (si < 0)
2156 my_b_printf(file, " (%u)", ui);
2157 }
2158
2159
2160 /**
2161 Print a packed value of the given SQL type into IO cache
2162
2163 @param[in] file IO cache
2164 @param[in] ptr Pointer to string
2165 @param[in] type Column type
2166 @param[in] meta Column meta information
2167 @param[out] typestr SQL type string buffer (for verbose output)
2168 @param[out] typestr_length Size of typestr
2169
2170 @retval - number of bytes scanned from ptr.
2171 */
2172 static size_t
log_event_print_value(IO_CACHE * file,const uchar * ptr,uint type,uint meta,char * typestr,size_t typestr_length)2173 log_event_print_value(IO_CACHE *file, const uchar *ptr,
2174 uint type, uint meta,
2175 char *typestr, size_t typestr_length)
2176 {
2177 uint32 length= 0;
2178
2179 if (type == MYSQL_TYPE_STRING)
2180 {
2181 if (meta >= 256)
2182 {
2183 uint byte0= meta >> 8;
2184 uint byte1= meta & 0xFF;
2185
2186 if ((byte0 & 0x30) != 0x30)
2187 {
2188 /* a long CHAR() field: see #37426 */
2189 length= byte1 | (((byte0 & 0x30) ^ 0x30) << 4);
2190 type= byte0 | 0x30;
2191 }
2192 else
2193 length = meta & 0xFF;
2194 }
2195 else
2196 length= meta;
2197 }
2198
2199 switch (type) {
2200 case MYSQL_TYPE_LONG:
2201 {
2202 my_snprintf(typestr, typestr_length, "INT");
2203 if(!ptr)
2204 return my_b_printf(file, "NULL");
2205 int32 si= sint4korr(ptr);
2206 uint32 ui= uint4korr(ptr);
2207 my_b_write_sint32_and_uint32(file, si, ui);
2208 return 4;
2209 }
2210
2211 case MYSQL_TYPE_TINY:
2212 {
2213 my_snprintf(typestr, typestr_length, "TINYINT");
2214 if(!ptr)
2215 return my_b_printf(file, "NULL");
2216 my_b_write_sint32_and_uint32(file, (int) (signed char) *ptr,
2217 (uint) (unsigned char) *ptr);
2218 return 1;
2219 }
2220
2221 case MYSQL_TYPE_SHORT:
2222 {
2223 my_snprintf(typestr, typestr_length, "SHORTINT");
2224 if(!ptr)
2225 return my_b_printf(file, "NULL");
2226 int32 si= (int32) sint2korr(ptr);
2227 uint32 ui= (uint32) uint2korr(ptr);
2228 my_b_write_sint32_and_uint32(file, si, ui);
2229 return 2;
2230 }
2231
2232 case MYSQL_TYPE_INT24:
2233 {
2234 my_snprintf(typestr, typestr_length, "MEDIUMINT");
2235 if(!ptr)
2236 return my_b_printf(file, "NULL");
2237 int32 si= sint3korr(ptr);
2238 uint32 ui= uint3korr(ptr);
2239 my_b_write_sint32_and_uint32(file, si, ui);
2240 return 3;
2241 }
2242
2243 case MYSQL_TYPE_LONGLONG:
2244 {
2245 my_snprintf(typestr, typestr_length, "LONGINT");
2246 if(!ptr)
2247 return my_b_printf(file, "NULL");
2248 char tmp[64];
2249 longlong si= sint8korr(ptr);
2250 longlong10_to_str(si, tmp, -10);
2251 my_b_printf(file, "%s", tmp);
2252 if (si < 0)
2253 {
2254 ulonglong ui= uint8korr(ptr);
2255 longlong10_to_str((longlong) ui, tmp, 10);
2256 my_b_printf(file, " (%s)", tmp);
2257 }
2258 return 8;
2259 }
2260
2261 case MYSQL_TYPE_NEWDECIMAL:
2262 {
2263 uint precision= meta >> 8;
2264 uint decimals= meta & 0xFF;
2265 my_snprintf(typestr, typestr_length, "DECIMAL(%d,%d)",
2266 precision, decimals);
2267 if(!ptr)
2268 return my_b_printf(file, "NULL");
2269 uint bin_size= my_decimal_get_binary_size(precision, decimals);
2270 my_decimal dec;
2271 binary2my_decimal(E_DEC_FATAL_ERROR, (uchar*) ptr, &dec,
2272 precision, decimals);
2273 int len= DECIMAL_MAX_STR_LENGTH;
2274 char buff[DECIMAL_MAX_STR_LENGTH + 1];
2275 decimal2string(&dec,buff,&len, 0, 0, 0);
2276 my_b_printf(file, "%s", buff);
2277 return bin_size;
2278 }
2279
2280 case MYSQL_TYPE_FLOAT:
2281 {
2282 my_snprintf(typestr, typestr_length, "FLOAT");
2283 if(!ptr)
2284 return my_b_printf(file, "NULL");
2285 float fl;
2286 float4get(&fl, ptr);
2287 char tmp[320];
2288 sprintf(tmp, "%-20g", (double) fl);
2289 my_b_printf(file, "%s", tmp); /* my_snprintf doesn't support %-20g */
2290 return 4;
2291 }
2292
2293 case MYSQL_TYPE_DOUBLE:
2294 {
2295 strcpy(typestr, "DOUBLE");
2296 if(!ptr)
2297 return my_b_printf(file, "NULL");
2298 double dbl;
2299 float8get(&dbl, ptr);
2300 char tmp[320];
2301 sprintf(tmp, "%-.20g", dbl); /* my_snprintf doesn't support %-20g */
2302 my_b_printf(file, "%s", tmp);
2303 return 8;
2304 }
2305
2306 case MYSQL_TYPE_BIT:
2307 {
2308 /* Meta-data: bit_len, bytes_in_rec, 2 bytes */
2309 uint nbits= ((meta >> 8) * 8) + (meta & 0xFF);
2310 my_snprintf(typestr, typestr_length, "BIT(%d)", nbits);
2311 if(!ptr)
2312 return my_b_printf(file, "NULL");
2313 length= (nbits + 7) / 8;
2314 my_b_write_bit(file, ptr, nbits);
2315 return length;
2316 }
2317
2318 case MYSQL_TYPE_TIMESTAMP:
2319 {
2320 my_snprintf(typestr, typestr_length, "TIMESTAMP");
2321 if(!ptr)
2322 return my_b_printf(file, "NULL");
2323 uint32 i32= uint4korr(ptr);
2324 my_b_printf(file, "%d", i32);
2325 return 4;
2326 }
2327
2328 case MYSQL_TYPE_TIMESTAMP2:
2329 {
2330 my_snprintf(typestr, typestr_length, "TIMESTAMP(%d)", meta);
2331 if(!ptr)
2332 return my_b_printf(file, "NULL");
2333 char buf[MAX_DATE_STRING_REP_LENGTH];
2334 struct timeval tm;
2335 my_timestamp_from_binary(&tm, ptr, meta);
2336 int buflen= my_timeval_to_str(&tm, buf, meta);
2337 if (my_b_write(file, reinterpret_cast<const uchar*>(buf), buflen))
2338 return 0;
2339 return my_timestamp_binary_length(meta);
2340 }
2341
2342 case MYSQL_TYPE_DATETIME:
2343 {
2344 my_snprintf(typestr, typestr_length, "DATETIME");
2345 if(!ptr)
2346 return my_b_printf(file, "NULL");
2347 size_t d, t;
2348 uint64 i64= uint8korr(ptr); /* YYYYMMDDhhmmss */
2349 d= static_cast<size_t>(i64 / 1000000);
2350 t= i64 % 1000000;
2351 my_b_printf(file, "%04d-%02d-%02d %02d:%02d:%02d",
2352 static_cast<int>(d / 10000),
2353 static_cast<int>(d % 10000) / 100,
2354 static_cast<int>(d % 100),
2355 static_cast<int>(t / 10000),
2356 static_cast<int>(t % 10000) / 100,
2357 static_cast<int>(t % 100));
2358 return 8;
2359 }
2360
2361 case MYSQL_TYPE_DATETIME2:
2362 {
2363 my_snprintf(typestr, typestr_length, "DATETIME(%d)", meta);
2364 if(!ptr)
2365 return my_b_printf(file, "NULL");
2366 char buf[MAX_DATE_STRING_REP_LENGTH];
2367 MYSQL_TIME ltime;
2368 longlong packed= my_datetime_packed_from_binary(ptr, meta);
2369 TIME_from_longlong_datetime_packed(<ime, packed);
2370 int buflen= my_datetime_to_str(<ime, buf, meta);
2371 my_b_write_quoted(file, (uchar *) buf, buflen);
2372 return my_datetime_binary_length(meta);
2373 }
2374
2375 case MYSQL_TYPE_TIME:
2376 {
2377 my_snprintf(typestr, typestr_length, "TIME");
2378 if(!ptr)
2379 return my_b_printf(file, "NULL");
2380 uint32 i32= uint3korr(ptr);
2381 my_b_printf(file, "'%02d:%02d:%02d'",
2382 i32 / 10000, (i32 % 10000) / 100, i32 % 100);
2383 return 3;
2384 }
2385
2386 case MYSQL_TYPE_TIME2:
2387 {
2388 my_snprintf(typestr, typestr_length, "TIME(%d)", meta);
2389 if(!ptr)
2390 return my_b_printf(file, "NULL");
2391 char buf[MAX_DATE_STRING_REP_LENGTH];
2392 MYSQL_TIME ltime;
2393 longlong packed= my_time_packed_from_binary(ptr, meta);
2394 TIME_from_longlong_time_packed(<ime, packed);
2395 int buflen= my_time_to_str(<ime, buf, meta);
2396 my_b_write_quoted(file, (uchar *) buf, buflen);
2397 return my_time_binary_length(meta);
2398 }
2399
2400 case MYSQL_TYPE_NEWDATE:
2401 {
2402 my_snprintf(typestr, typestr_length, "DATE");
2403 if(!ptr)
2404 return my_b_printf(file, "NULL");
2405 uint32 tmp= uint3korr(ptr);
2406 int part;
2407 char buf[11];
2408 char *pos= &buf[10]; // start from '\0' to the beginning
2409
2410 /* Copied from field.cc */
2411 *pos--=0; // End NULL
2412 part=(int) (tmp & 31);
2413 *pos--= (char) ('0'+part%10);
2414 *pos--= (char) ('0'+part/10);
2415 *pos--= ':';
2416 part=(int) (tmp >> 5 & 15);
2417 *pos--= (char) ('0'+part%10);
2418 *pos--= (char) ('0'+part/10);
2419 *pos--= ':';
2420 part=(int) (tmp >> 9);
2421 *pos--= (char) ('0'+part%10); part/=10;
2422 *pos--= (char) ('0'+part%10); part/=10;
2423 *pos--= (char) ('0'+part%10); part/=10;
2424 *pos= (char) ('0'+part);
2425 my_b_printf(file , "'%s'", buf);
2426 return 3;
2427 }
2428
2429 case MYSQL_TYPE_YEAR:
2430 {
2431 my_snprintf(typestr, typestr_length, "YEAR");
2432 if(!ptr)
2433 return my_b_printf(file, "NULL");
2434 uint32 i32= *ptr;
2435 my_b_printf(file, "%04d", i32+ 1900);
2436 return 1;
2437 }
2438
2439 case MYSQL_TYPE_ENUM:
2440 switch (meta & 0xFF) {
2441 case 1:
2442 my_snprintf(typestr, typestr_length, "ENUM(1 byte)");
2443 if(!ptr)
2444 return my_b_printf(file, "NULL");
2445 my_b_printf(file, "%d", (int) *ptr);
2446 return 1;
2447 case 2:
2448 {
2449 my_snprintf(typestr, typestr_length, "ENUM(2 bytes)");
2450 if(!ptr)
2451 return my_b_printf(file, "NULL");
2452 int32 i32= uint2korr(ptr);
2453 my_b_printf(file, "%d", i32);
2454 return 2;
2455 }
2456 default:
2457 my_b_printf(file, "!! Unknown ENUM packlen=%d", meta & 0xFF);
2458 return 0;
2459 }
2460 break;
2461
2462 case MYSQL_TYPE_SET:
2463 my_snprintf(typestr, typestr_length, "SET(%d bytes)", meta & 0xFF);
2464 if(!ptr)
2465 return my_b_printf(file, "NULL");
2466 my_b_write_bit(file, ptr , (meta & 0xFF) * 8);
2467 return meta & 0xFF;
2468
2469 case MYSQL_TYPE_BLOB:
2470 switch (meta) {
2471 case 1:
2472 my_snprintf(typestr, typestr_length, "TINYBLOB/TINYTEXT");
2473 if(!ptr)
2474 return my_b_printf(file, "NULL");
2475 length= *ptr;
2476 my_b_write_quoted(file, ptr + 1, length);
2477 return length + 1;
2478 case 2:
2479 my_snprintf(typestr, typestr_length, "BLOB/TEXT");
2480 if(!ptr)
2481 return my_b_printf(file, "NULL");
2482 length= uint2korr(ptr);
2483 my_b_write_quoted(file, ptr + 2, length);
2484 return length + 2;
2485 case 3:
2486 my_snprintf(typestr, typestr_length, "MEDIUMBLOB/MEDIUMTEXT");
2487 if(!ptr)
2488 return my_b_printf(file, "NULL");
2489 length= uint3korr(ptr);
2490 my_b_write_quoted(file, ptr + 3, length);
2491 return length + 3;
2492 case 4:
2493 my_snprintf(typestr, typestr_length, "LONGBLOB/LONGTEXT");
2494 if(!ptr)
2495 return my_b_printf(file, "NULL");
2496 length= uint4korr(ptr);
2497 my_b_write_quoted(file, ptr + 4, length);
2498 return length + 4;
2499 default:
2500 my_b_printf(file, "!! Unknown BLOB packlen=%d", length);
2501 return 0;
2502 }
2503
2504 case MYSQL_TYPE_VARCHAR:
2505 case MYSQL_TYPE_VAR_STRING:
2506 length= meta;
2507 my_snprintf(typestr, typestr_length, "VARSTRING(%d)", length);
2508 if(!ptr)
2509 return my_b_printf(file, "NULL");
2510 return my_b_write_quoted_with_length(file, ptr, length);
2511
2512 case MYSQL_TYPE_STRING:
2513 my_snprintf(typestr, typestr_length, "STRING(%d)", length);
2514 if(!ptr)
2515 return my_b_printf(file, "NULL");
2516 return my_b_write_quoted_with_length(file, ptr, length);
2517
2518 case MYSQL_TYPE_JSON:
2519 my_snprintf(typestr, typestr_length, "JSON");
2520 if (!ptr)
2521 return my_b_printf(file, "NULL");
2522 length= uint2korr(ptr);
2523 my_b_write_quoted(file, ptr + meta, length);
2524 return length + meta;
2525
2526 default:
2527 {
2528 char tmp[5];
2529 my_snprintf(tmp, sizeof(tmp), "%04x", meta);
2530 my_b_printf(file,
2531 "!! Don't know how to handle column type=%d meta=%d (%s)",
2532 type, meta, tmp);
2533 }
2534 break;
2535 }
2536 *typestr= 0;
2537 return 0;
2538 }
2539
2540
2541 /**
2542 Print a packed row into IO cache
2543
2544 @param[in] file IO cache
2545 @param[in] td Table definition
2546 @param[in] print_event_into Print parameters
2547 @param[in] cols_bitmap Column bitmaps.
2548 @param[in] value Pointer to packed row
2549 @param[in] prefix Row's SQL clause ("SET", "WHERE", etc)
2550
2551 @retval - number of bytes scanned.
2552 */
2553
2554
2555 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)2556 Rows_log_event::print_verbose_one_row(IO_CACHE *file, table_def *td,
2557 PRINT_EVENT_INFO *print_event_info,
2558 MY_BITMAP *cols_bitmap,
2559 const uchar *value, const uchar *prefix)
2560 {
2561 const uchar *value0= value;
2562 const uchar *null_bits= value;
2563 uint null_bit_index= 0;
2564 char typestr[64]= "";
2565
2566 /*
2567 Skip metadata bytes which gives the information about nullabity of master
2568 columns. Master writes one bit for each affected column.
2569 */
2570 value+= (bitmap_bits_set(cols_bitmap) + 7) / 8;
2571
2572 my_b_printf(file, "%s", prefix);
2573
2574 for (size_t i= 0; i < td->size(); i ++)
2575 {
2576 int is_null= (null_bits[null_bit_index / 8]
2577 >> (null_bit_index % 8)) & 0x01;
2578
2579 if (bitmap_is_set(cols_bitmap, i) == 0)
2580 continue;
2581
2582 my_b_printf(file, "### @%d=", static_cast<int>(i + 1));
2583 if (!is_null)
2584 {
2585 size_t fsize= td->calc_field_size((uint)i, (uchar*) value);
2586 if (value + fsize > m_rows_end)
2587 {
2588 my_b_printf(file, "***Corrupted replication event was detected."
2589 " Not printing the value***\n");
2590 value+= fsize;
2591 return 0;
2592 }
2593 }
2594 size_t size= log_event_print_value(file,is_null? NULL: value,
2595 td->type(i), td->field_metadata(i),
2596 typestr, sizeof(typestr));
2597 if (!size)
2598 return 0;
2599
2600 if(!is_null)
2601 value+= size;
2602
2603 if (print_event_info->verbose > 1)
2604 {
2605 my_b_printf(file, " /* ");
2606
2607 my_b_printf(file, "%s ", typestr);
2608
2609 my_b_printf(file, "meta=%d nullable=%d is_null=%d ",
2610 td->field_metadata(i),
2611 td->maybe_null(i), is_null);
2612 my_b_printf(file, "*/");
2613 }
2614
2615 my_b_printf(file, "\n");
2616
2617 null_bit_index++;
2618 }
2619 return value - value0;
2620 }
2621
2622
2623 /**
2624 Print a row event into IO cache in human readable form (in SQL format)
2625
2626 @param[in] file IO cache
2627 @param[in] print_event_into Print parameters
2628 */
print_verbose(IO_CACHE * file,PRINT_EVENT_INFO * print_event_info)2629 void Rows_log_event::print_verbose(IO_CACHE *file,
2630 PRINT_EVENT_INFO *print_event_info)
2631 {
2632 // Quoted length of the identifier can be twice the original length
2633 char quoted_db[1 + NAME_LEN * 2 + 2];
2634 char quoted_table[1 + NAME_LEN * 2 + 2];
2635 size_t quoted_db_len, quoted_table_len;
2636 Table_map_log_event *map;
2637 table_def *td;
2638 const char *sql_command, *sql_clause1, *sql_clause2;
2639 Log_event_type general_type_code= get_general_type_code();
2640
2641 if (m_extra_row_data)
2642 {
2643 uint8 extra_data_len= m_extra_row_data[EXTRA_ROW_INFO_LEN_OFFSET];
2644 uint8 extra_payload_len= extra_data_len - EXTRA_ROW_INFO_HDR_BYTES;
2645 assert(extra_data_len >= EXTRA_ROW_INFO_HDR_BYTES);
2646
2647 my_b_printf(file, "### Extra row data format: %u, len: %u :",
2648 m_extra_row_data[EXTRA_ROW_INFO_FORMAT_OFFSET],
2649 extra_payload_len);
2650 if (extra_payload_len)
2651 {
2652 /*
2653 Buffer for hex view of string, including '0x' prefix,
2654 2 hex chars / byte and trailing 0
2655 */
2656 const int buff_len= 2 + (256 * 2) + 1;
2657 char buff[buff_len];
2658 str_to_hex(buff, (const char*) &m_extra_row_data[EXTRA_ROW_INFO_HDR_BYTES],
2659 extra_payload_len);
2660 my_b_printf(file, "%s", buff);
2661 }
2662 my_b_printf(file, "\n");
2663 }
2664
2665 switch (general_type_code) {
2666 case binary_log::WRITE_ROWS_EVENT:
2667 sql_command= "INSERT INTO";
2668 sql_clause1= "### SET\n";
2669 sql_clause2= NULL;
2670 break;
2671 case binary_log::DELETE_ROWS_EVENT:
2672 sql_command= "DELETE FROM";
2673 sql_clause1= "### WHERE\n";
2674 sql_clause2= NULL;
2675 break;
2676 case binary_log::UPDATE_ROWS_EVENT:
2677 sql_command= "UPDATE";
2678 sql_clause1= "### WHERE\n";
2679 sql_clause2= "### SET\n";
2680 break;
2681 default:
2682 sql_command= sql_clause1= sql_clause2= NULL;
2683 assert(0); /* Not possible */
2684 }
2685
2686 if (!(map= print_event_info->m_table_map.get_table(m_table_id)) ||
2687 !(td= map->create_table_def()))
2688 {
2689 char llbuff[22];
2690 my_b_printf(file, "### Row event for unknown table #%s",
2691 llstr(m_table_id, llbuff));
2692 return;
2693 }
2694
2695 /* If the write rows event contained no values for the AI */
2696 if (((general_type_code == binary_log::WRITE_ROWS_EVENT) &&
2697 (m_rows_buf==m_rows_end)))
2698 {
2699 my_b_printf(file, "### INSERT INTO `%s`.`%s` VALUES ()\n",
2700 map->get_db_name(), map->get_table_name());
2701 goto end;
2702 }
2703
2704 for (const uchar *value= m_rows_buf; value < m_rows_end; )
2705 {
2706 size_t length;
2707 #ifdef MYSQL_SERVER
2708 quoted_db_len= my_strmov_quoted_identifier(this->thd, (char *) quoted_db,
2709 map->get_db_name(), 0);
2710 quoted_table_len= my_strmov_quoted_identifier(this->thd,
2711 (char *) quoted_table,
2712 map->get_table_name(), 0);
2713 #else
2714 quoted_db_len= my_strmov_quoted_identifier((char *) quoted_db,
2715 map->get_db_name());
2716 quoted_table_len= my_strmov_quoted_identifier((char *) quoted_table,
2717 map->get_table_name());
2718 #endif
2719 quoted_db[quoted_db_len]= '\0';
2720 quoted_table[quoted_table_len]= '\0';
2721 my_b_printf(file, "### %s %s.%s\n",
2722 sql_command,
2723 quoted_db, quoted_table);
2724 /* Print the first image */
2725 if (!(length= print_verbose_one_row(file, td, print_event_info,
2726 &m_cols, value,
2727 (const uchar*) sql_clause1)))
2728 goto end;
2729 value+= length;
2730
2731 /* Print the second image (for UPDATE only) */
2732 if (sql_clause2)
2733 {
2734 if (!(length= print_verbose_one_row(file, td, print_event_info,
2735 &m_cols_ai, value,
2736 (const uchar*) sql_clause2)))
2737 goto end;
2738 value+= length;
2739 }
2740 }
2741
2742 end:
2743 delete td;
2744 }
2745
2746 #ifdef MYSQL_CLIENT
free_table_map_log_event(Table_map_log_event * event)2747 void free_table_map_log_event(Table_map_log_event *event)
2748 {
2749 delete event;
2750 }
2751 #endif
2752
print_base64(IO_CACHE * file,PRINT_EVENT_INFO * print_event_info,bool more)2753 void Log_event::print_base64(IO_CACHE* file,
2754 PRINT_EVENT_INFO* print_event_info,
2755 bool more)
2756 {
2757 const uchar *ptr= (const uchar *)temp_buf;
2758 uint32 size= uint4korr(ptr + EVENT_LEN_OFFSET);
2759 DBUG_ENTER("Log_event::print_base64");
2760
2761 uint64 const tmp_str_sz= base64_needed_encoded_length((uint64) size);
2762 char *const tmp_str= (char *) my_malloc(key_memory_log_event,
2763 tmp_str_sz, MYF(MY_WME));
2764 if (!tmp_str) {
2765 fprintf(stderr, "\nError: Out of memory. "
2766 "Could not print correct binlog event.\n");
2767 DBUG_VOID_RETURN;
2768 }
2769
2770 if (base64_encode(ptr, (size_t) size, tmp_str))
2771 {
2772 assert(0);
2773 }
2774
2775 if (print_event_info->base64_output_mode != BASE64_OUTPUT_DECODE_ROWS)
2776 {
2777 if (my_b_tell(file) == 0)
2778 my_b_printf(file, "\nBINLOG '\n");
2779
2780 my_b_printf(file, "%s\n", tmp_str);
2781
2782 if (!more)
2783 my_b_printf(file, "'%s\n", print_event_info->delimiter);
2784 }
2785
2786 if (print_event_info->verbose)
2787 {
2788 Rows_log_event *ev= NULL;
2789 Log_event_type et= (Log_event_type) ptr[EVENT_TYPE_OFFSET];
2790
2791 if (common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_UNDEF &&
2792 common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_OFF)
2793 size-= BINLOG_CHECKSUM_LEN; // checksum is displayed through the header
2794
2795 const Format_description_event fd_evt=
2796 Format_description_event(glob_description_event->binlog_version,
2797 server_version);
2798 switch(et)
2799 {
2800 case binary_log::TABLE_MAP_EVENT:
2801 {
2802 Table_map_log_event *map;
2803 map= new Table_map_log_event((const char*) ptr, size,
2804 &fd_evt);
2805 print_event_info->m_table_map.set_table(map->get_table_id(), map);
2806 break;
2807 }
2808 case binary_log::WRITE_ROWS_EVENT:
2809 case binary_log::WRITE_ROWS_EVENT_V1:
2810 {
2811 ev= new Write_rows_log_event((const char*) ptr, size,
2812 &fd_evt);
2813 break;
2814 }
2815 case binary_log::DELETE_ROWS_EVENT:
2816 case binary_log::DELETE_ROWS_EVENT_V1:
2817 {
2818 ev= new Delete_rows_log_event((const char*) ptr, size,
2819 &fd_evt);
2820 break;
2821 }
2822 case binary_log::UPDATE_ROWS_EVENT:
2823 case binary_log::UPDATE_ROWS_EVENT_V1:
2824 {
2825 ev= new Update_rows_log_event((const char*) ptr, size,
2826 &fd_evt);
2827 break;
2828 }
2829 default:
2830 break;
2831 }
2832
2833 if (ev)
2834 {
2835 ev->print_verbose(&print_event_info->footer_cache, print_event_info);
2836 delete ev;
2837 }
2838 }
2839
2840 my_free(tmp_str);
2841 DBUG_VOID_RETURN;
2842 }
2843
2844
2845 /*
2846 Log_event::print_timestamp()
2847 */
2848
print_timestamp(IO_CACHE * file,time_t * ts)2849 void Log_event::print_timestamp(IO_CACHE* file, time_t *ts)
2850 {
2851 struct tm *res;
2852 /*
2853 In some Windows versions timeval.tv_sec is defined as "long",
2854 not as "time_t" and can be of a different size.
2855 Let's use a temporary time_t variable to execute localtime()
2856 with a correct argument type.
2857 */
2858 time_t ts_tmp= ts ? *ts : (ulong)common_header->when.tv_sec;
2859 DBUG_ENTER("Log_event::print_timestamp");
2860 struct tm tm_tmp;
2861 localtime_r(&ts_tmp, (res= &tm_tmp));
2862 my_b_printf(file,"%02d%02d%02d %2d:%02d:%02d",
2863 res->tm_year % 100,
2864 res->tm_mon+1,
2865 res->tm_mday,
2866 res->tm_hour,
2867 res->tm_min,
2868 res->tm_sec);
2869 DBUG_VOID_RETURN;
2870 }
2871
2872 #endif /* MYSQL_CLIENT */
2873
2874
2875 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
2876 inline Log_event::enum_skip_reason
continue_group(Relay_log_info * rli)2877 Log_event::continue_group(Relay_log_info *rli)
2878 {
2879 if (rli->slave_skip_counter == 1)
2880 return Log_event::EVENT_SKIP_IGNORE;
2881 return Log_event::do_shall_skip(rli);
2882 }
2883
2884 /**
2885 @param end_group_sets_max_dbs when true the group terminal event
2886 can carry partition info, see a note below.
2887 @return true in cases the current event
2888 carries partition data,
2889 false otherwise
2890
2891 @note Some events combination may force to adjust partition info.
2892 In particular BEGIN, BEGIN_LOAD_QUERY_EVENT, COMMIT
2893 where none of the events holds partitioning data
2894 causes the sequential applying of the group through
2895 assigning OVER_MAX_DBS_IN_EVENT_MTS to mts_accessed_dbs
2896 of the group terminator (e.g COMMIT query) event.
2897 */
contains_partition_info(bool end_group_sets_max_dbs)2898 bool Log_event::contains_partition_info(bool end_group_sets_max_dbs)
2899 {
2900 bool res;
2901
2902 switch (get_type_code()) {
2903 case binary_log::TABLE_MAP_EVENT:
2904 case binary_log::EXECUTE_LOAD_QUERY_EVENT:
2905 res= true;
2906
2907 break;
2908
2909 case binary_log::QUERY_EVENT:
2910 {
2911 Query_log_event *qev= static_cast<Query_log_event*>(this);
2912 if ((ends_group() && end_group_sets_max_dbs) ||
2913 (qev->is_query_prefix_match(STRING_WITH_LEN("XA COMMIT")) ||
2914 qev->is_query_prefix_match(STRING_WITH_LEN("XA ROLLBACK"))))
2915 {
2916 res= true;
2917 qev->mts_accessed_dbs= OVER_MAX_DBS_IN_EVENT_MTS;
2918 }
2919 else
2920 res= (!ends_group() && !starts_group()) ? true : false;
2921 break;
2922 }
2923 default:
2924 res= false;
2925 }
2926
2927 return res;
2928 }
2929 /*
2930 SYNOPSIS
2931 This function assigns a parent ID to the job group being scheduled in parallel.
2932 It also checks if we can schedule the new event in parallel with the previous ones
2933 being executed.
2934
2935 @param ev log event that has to be scheduled next.
2936 @param rli Pointer to coordinato's relay log info.
2937 @return true if error
2938 false otherwise
2939 */
schedule_next_event(Log_event * ev,Relay_log_info * rli)2940 bool schedule_next_event(Log_event* ev, Relay_log_info* rli)
2941 {
2942 int error;
2943 // Check if we can schedule this event
2944 error= rli->current_mts_submode->schedule_next_event(rli, ev);
2945 switch (error)
2946 {
2947 case ER_MTS_CANT_PARALLEL:
2948 char llbuff[22];
2949 llstr(rli->get_event_relay_log_pos(), llbuff);
2950 my_error(ER_MTS_CANT_PARALLEL, MYF(0),
2951 ev->get_type_str(), rli->get_event_relay_log_name(), llbuff,
2952 "The master event is logically timestamped incorrectly.");
2953 return true;
2954 case ER_MTS_INCONSISTENT_DATA:
2955 /* Don't have to do anything. */
2956 return true;
2957 case -1:
2958 /* Unable to schedule: wait_for_last_committed_trx has failed */
2959 return true;
2960 default:
2961 return false;
2962 }
2963 /* Keep compiler happy */
2964 return false;
2965 }
2966
2967
2968 /**
2969 The method maps the event to a Worker and return a pointer to it.
2970 Sending the event to the Worker is done by the caller.
2971
2972 Irrespective of the type of Group marking (DB partioned or BGC) the
2973 following holds true:
2974
2975 - recognize the beginning of a group to allocate the group descriptor
2976 and queue it;
2977 - associate an event with a Worker (which also handles possible conflicts
2978 detection and waiting for their termination);
2979 - finalize the group assignement when the group closing event is met.
2980
2981 When parallelization mode is BGC-based the partitioning info in the event
2982 is simply ignored. Thereby association with a Worker does not require
2983 Assigned Partition Hash of the partitioned method.
2984 This method is not interested in all the taxonomy of the event group
2985 property, what we care about is the boundaries of the group.
2986
2987 As a part of the group, an event belongs to one of the following types:
2988
2989 B - beginning of a group of events (BEGIN query_log_event)
2990 g - mini-group representative event containing the partition info
2991 (any Table_map, a Query_log_event)
2992 p - a mini-group internal event that *p*receeding its g-parent
2993 (int_, rand_, user_ var:s)
2994 r - a mini-group internal "regular" event that follows its g-parent
2995 (Delete, Update, Write -rows)
2996 T - terminator of the group (XID, COMMIT, ROLLBACK, auto-commit query)
2997
2998 Only the first g-event computes the assigned Worker which once
2999 is determined remains to be for the rest of the group.
3000 That is the g-event solely carries partitioning info.
3001 For B-event the assigned Worker is NULL to indicate Coordinator
3002 has not yet decided. The same applies to p-event.
3003
3004 Notice, these is a special group consisting of optionally multiple p-events
3005 terminating with a g-event.
3006 Such case is caused by old master binlog and a few corner-cases of
3007 the current master version (todo: to fix).
3008
3009 In case of the event accesses more than OVER_MAX_DBS the method
3010 has to ensure sure previously assigned groups to all other workers are
3011 done.
3012
3013
3014 @note The function updates GAQ queue directly, updates APH hash
3015 plus relocates some temporary tables from Coordinator's list into
3016 involved entries of APH through @c map_db_to_worker.
3017 There's few memory allocations commented where to be freed.
3018
3019 @return a pointer to the Worker struct or NULL.
3020 */
3021
get_slave_worker(Relay_log_info * rli)3022 Slave_worker *Log_event::get_slave_worker(Relay_log_info *rli)
3023 {
3024 Slave_job_group group= Slave_job_group(), *ptr_group= NULL;
3025 bool is_s_event;
3026 Slave_worker *ret_worker= NULL;
3027 char llbuff[22];
3028 Slave_committed_queue *gaq= rli->gaq;
3029 DBUG_ENTER("Log_event::get_slave_worker");
3030
3031 /* checking partioning properties and perform corresponding actions */
3032
3033 // Beginning of a group designated explicitly with BEGIN or GTID
3034 if ((is_s_event= starts_group()) || is_gtid_event(this) ||
3035 // or DDL:s or autocommit queries possibly associated with own p-events
3036 (!rli->curr_group_seen_begin && !rli->curr_group_seen_gtid &&
3037 /*
3038 the following is a special case of B-free still multi-event group like
3039 { p_1,p_2,...,p_k, g }.
3040 In that case either GAQ is empty (the very first group is being
3041 assigned) or the last assigned group index points at one of
3042 mapped-to-a-worker.
3043 */
3044 (gaq->empty() ||
3045 gaq->get_job_group(rli->gaq->assigned_group_index)->
3046 worker_id != MTS_WORKER_UNDEF)))
3047 {
3048 if (!rli->curr_group_seen_gtid && !rli->curr_group_seen_begin)
3049 {
3050 rli->mts_groups_assigned++;
3051
3052 rli->curr_group_isolated= FALSE;
3053 group.reset(common_header->log_pos, rli->mts_groups_assigned);
3054 // the last occupied GAQ's array index
3055 gaq->assigned_group_index= gaq->en_queue(&group);
3056 DBUG_PRINT("info",("gaq_idx= %ld gaq->size=%ld",
3057 gaq->assigned_group_index,
3058 gaq->size));
3059 assert(gaq->assigned_group_index != MTS_WORKER_UNDEF);
3060 assert(gaq->assigned_group_index < gaq->size);
3061 assert(gaq->get_job_group(rli->gaq->assigned_group_index)->
3062 group_relay_log_name == NULL);
3063 assert(rli->last_assigned_worker == NULL ||
3064 !is_mts_db_partitioned(rli));
3065
3066 if (is_s_event || is_gtid_event(this))
3067 {
3068 Slave_job_item job_item= {this, rli->get_event_relay_log_number(),
3069 rli->get_event_start_pos()};
3070 // B-event is appended to the Deferred Array associated with GCAP
3071 rli->curr_group_da.push_back(job_item);
3072
3073 assert(rli->curr_group_da.size() == 1);
3074
3075 if (starts_group())
3076 {
3077 // mark the current group as started with explicit B-event
3078 rli->mts_end_group_sets_max_dbs= true;
3079 rli->curr_group_seen_begin= true;
3080 }
3081
3082 if (is_gtid_event(this))
3083 // mark the current group as started with explicit Gtid-event
3084 rli->curr_group_seen_gtid= true;
3085 if (schedule_next_event(this, rli))
3086 {
3087 rli->abort_slave= 1;
3088 DBUG_RETURN(NULL);
3089 }
3090 DBUG_RETURN(ret_worker);
3091 }
3092 }
3093 else
3094 {
3095 /*
3096 The block is a result of not making GTID event as group starter.
3097 TODO: Make GITD event as B-event that is starts_group() to
3098 return true.
3099 */
3100 Slave_job_item job_item= {this, rli->get_event_relay_log_number(),
3101 rli->get_event_relay_log_pos()};
3102
3103 // B-event is appended to the Deferred Array associated with GCAP
3104 rli->curr_group_da.push_back(job_item);
3105 rli->curr_group_seen_begin= true;
3106 rli->mts_end_group_sets_max_dbs= true;
3107 if (!rli->curr_group_seen_gtid && schedule_next_event(this, rli))
3108 {
3109 rli->abort_slave= 1;
3110 DBUG_RETURN(NULL);
3111 }
3112
3113 assert(rli->curr_group_da.size() == 2);
3114 assert(starts_group());
3115 DBUG_RETURN (ret_worker);
3116 }
3117 if (schedule_next_event(this, rli))
3118 {
3119 rli->abort_slave= 1;
3120 DBUG_RETURN(NULL);
3121 }
3122 }
3123
3124 ptr_group= gaq->get_job_group(rli->gaq->assigned_group_index);
3125 if (!is_mts_db_partitioned(rli))
3126 {
3127 /* Get least occupied worker */
3128 ret_worker=
3129 rli->current_mts_submode->get_least_occupied_worker(rli, &rli->workers,
3130 this);
3131 if (ret_worker == NULL)
3132 {
3133 /* get_least_occupied_worker may return NULL if the thread is killed */
3134 Slave_job_item job_item= {this, rli->get_event_relay_log_number(),
3135 rli->get_event_start_pos()};
3136 rli->curr_group_da.push_back(job_item);
3137
3138 assert(thd->killed);
3139 DBUG_RETURN(NULL);
3140 }
3141 ptr_group->worker_id= ret_worker->id;
3142 }
3143 else if (contains_partition_info(rli->mts_end_group_sets_max_dbs))
3144 {
3145 int i= 0;
3146 Mts_db_names mts_dbs;
3147
3148 get_mts_dbs(&mts_dbs);
3149 /*
3150 Bug 12982188 - MTS: SBR ABORTS WITH ERROR 1742 ON LOAD DATA
3151 Logging on master can create a group with no events holding
3152 the partition info.
3153 The following assert proves there's the only reason
3154 for such group.
3155 */
3156 #ifndef NDEBUG
3157 {
3158 bool empty_group_with_gtids= rli->curr_group_seen_begin &&
3159 rli->curr_group_seen_gtid &&
3160 ends_group();
3161
3162 bool begin_load_query_event=
3163 ((rli->curr_group_da.size() == 3 && rli->curr_group_seen_gtid) ||
3164 (rli->curr_group_da.size() == 2 && !rli->curr_group_seen_gtid)) &&
3165 (rli->curr_group_da.back().data->
3166 get_type_code() == binary_log::BEGIN_LOAD_QUERY_EVENT);
3167
3168 bool delete_file_event=
3169 ((rli->curr_group_da.size() == 4 && rli->curr_group_seen_gtid) ||
3170 (rli->curr_group_da.size() == 3 && !rli->curr_group_seen_gtid)) &&
3171 (rli->curr_group_da.back().data->
3172 get_type_code() == binary_log::DELETE_FILE_EVENT);
3173
3174 assert((!ends_group() ||
3175 (get_type_code() == binary_log::QUERY_EVENT &&
3176 static_cast<Query_log_event*>(this)->
3177 is_query_prefix_match(STRING_WITH_LEN("XA ROLLBACK")))) ||
3178 empty_group_with_gtids ||
3179 (rli->mts_end_group_sets_max_dbs &&
3180 (begin_load_query_event || delete_file_event)));
3181 }
3182 #endif
3183
3184 // partioning info is found which drops the flag
3185 rli->mts_end_group_sets_max_dbs= false;
3186 ret_worker= rli->last_assigned_worker;
3187 if (mts_dbs.num == OVER_MAX_DBS_IN_EVENT_MTS)
3188 {
3189 // Worker with id 0 to handle serial execution
3190 if (!ret_worker)
3191 ret_worker= rli->workers.at(0);
3192 // No need to know a possible error out of synchronization call.
3193 (void) rli->current_mts_submode->
3194 wait_for_workers_to_finish(rli, ret_worker);
3195 /*
3196 this marking is transferred further into T-event of the current group.
3197 */
3198 rli->curr_group_isolated= TRUE;
3199 }
3200
3201 /* One run of the loop in the case of over-max-db:s */
3202 for (i= 0; i < ((mts_dbs.num != OVER_MAX_DBS_IN_EVENT_MTS) ? mts_dbs.num : 1);
3203 i++)
3204 {
3205 /*
3206 The over max db:s case handled through passing to map_db_to_worker
3207 such "all" db as encoded as the "" empty string.
3208 Note, the empty string is allocated in a large buffer
3209 to satisfy hashcmp() implementation.
3210 */
3211 const char all_db[NAME_LEN]= {0};
3212 if (!(ret_worker=
3213 map_db_to_worker(mts_dbs.num == OVER_MAX_DBS_IN_EVENT_MTS ?
3214 all_db : mts_dbs.name[i], rli,
3215 &mts_assigned_partitions[i],
3216 /*
3217 todo: optimize it. Although pure
3218 rows- event load in insensetive to the flag value
3219 */
3220 TRUE,
3221 ret_worker)))
3222 {
3223 llstr(rli->get_event_relay_log_pos(), llbuff);
3224 my_error(ER_MTS_CANT_PARALLEL, MYF(0),
3225 get_type_str(), rli->get_event_relay_log_name(), llbuff,
3226 "could not distribute the event to a Worker");
3227 DBUG_RETURN(ret_worker);
3228 }
3229 // all temporary tables are transferred from Coordinator in over-max case
3230 assert(mts_dbs.num != OVER_MAX_DBS_IN_EVENT_MTS || !thd->temporary_tables);
3231 assert(!strcmp(mts_assigned_partitions[i]->db,
3232 mts_dbs.num != OVER_MAX_DBS_IN_EVENT_MTS ?
3233 mts_dbs.name[i] : all_db));
3234 assert(ret_worker == mts_assigned_partitions[i]->worker);
3235 assert(mts_assigned_partitions[i]->usage >= 0);
3236 }
3237
3238 if ((ptr_group= gaq->get_job_group(rli->gaq->assigned_group_index))->
3239 worker_id == MTS_WORKER_UNDEF)
3240 {
3241 ptr_group->worker_id= ret_worker->id;
3242
3243 assert(ptr_group->group_relay_log_name == NULL);
3244 }
3245
3246 assert(i == mts_dbs.num || mts_dbs.num == OVER_MAX_DBS_IN_EVENT_MTS);
3247 }
3248 else
3249 {
3250 // a mini-group internal "regular" event
3251 if (rli->last_assigned_worker)
3252 {
3253 ret_worker= rli->last_assigned_worker;
3254
3255 assert(rli->curr_group_assigned_parts.size() > 0 ||
3256 ret_worker->id == 0);
3257 }
3258 else // int_, rand_, user_ var:s, load-data events
3259 {
3260
3261 if (!(get_type_code() == binary_log::INTVAR_EVENT ||
3262 get_type_code() == binary_log::RAND_EVENT ||
3263 get_type_code() == binary_log::USER_VAR_EVENT ||
3264 get_type_code() == binary_log::BEGIN_LOAD_QUERY_EVENT ||
3265 get_type_code() == binary_log::APPEND_BLOCK_EVENT ||
3266 get_type_code() == binary_log::DELETE_FILE_EVENT ||
3267 is_ignorable_event()))
3268 {
3269 assert(!ret_worker);
3270
3271 llstr(rli->get_event_relay_log_pos(), llbuff);
3272 my_error(ER_MTS_CANT_PARALLEL, MYF(0),
3273 get_type_str(), rli->get_event_relay_log_name(), llbuff,
3274 "the event is a part of a group that is unsupported in "
3275 "the parallel execution mode");
3276
3277 DBUG_RETURN(ret_worker);
3278 }
3279 /*
3280 In the logical clock scheduler any internal gets scheduled directly.
3281 That is Int_var, @User_var and Rand bypass the deferred array.
3282 Their association with relay-log physical coordinates is provided
3283 by the same mechanism that applies to a regular event.
3284 */
3285 Slave_job_item job_item= {this, rli->get_event_relay_log_number(),
3286 rli->get_event_start_pos()};
3287 rli->curr_group_da.push_back(job_item);
3288
3289 assert(!ret_worker);
3290 DBUG_RETURN (ret_worker);
3291 }
3292 }
3293
3294 assert(ret_worker);
3295 // T-event: Commit, Xid, a DDL query or dml query of B-less group.4
3296
3297 /*
3298 Preparing event physical coordinates info for Worker before any
3299 event got scheduled so when Worker error-stopped at the first
3300 event it would be aware of where exactly in the event stream.
3301 */
3302 if (!ret_worker->master_log_change_notified)
3303 {
3304 if (!ptr_group)
3305 ptr_group= gaq->get_job_group(rli->gaq->assigned_group_index);
3306 ptr_group->group_master_log_name=
3307 my_strdup(key_memory_log_event, rli->get_group_master_log_name(), MYF(MY_WME));
3308 ret_worker->master_log_change_notified= true;
3309
3310 assert(!ptr_group->notified);
3311 #ifndef NDEBUG
3312 ptr_group->notified= true;
3313 #endif
3314 }
3315
3316 /* Notify the worker about new FD */
3317 if (!ret_worker->fd_change_notified)
3318 {
3319 if (!ptr_group)
3320 ptr_group= gaq->get_job_group(rli->gaq->assigned_group_index);
3321 /*
3322 Increment the usage counter on behalf of Worker.
3323 This avoids inadvertent FD deletion in a race case where Coordinator
3324 would install a next new FD before Worker has noticed the previous one.
3325 */
3326 rli->get_rli_description_event()->usage_counter.atomic_add(1);
3327 ptr_group->new_fd_event= rli->get_rli_description_event();
3328 ret_worker->fd_change_notified= true;
3329 }
3330
3331 if (ends_group() ||
3332 (!rli->curr_group_seen_begin &&
3333 (get_type_code() == binary_log::QUERY_EVENT ||
3334 /*
3335 When applying an old binary log without Gtid_log_event and
3336 Anonymous_gtid_log_event, the logic of multi-threaded slave
3337 still need to require that an event (for example, Query_log_event,
3338 User_var_log_event, Intvar_log_event, and Rand_log_event) that
3339 appeared outside of BEGIN...COMMIT was treated as a transaction
3340 of its own. This was just a technicality in the code and did not
3341 cause a problem, since the event and the following Query_log_event
3342 would both be assigned to dedicated worker 0.
3343 */
3344 !rli->curr_group_seen_gtid)))
3345 {
3346 rli->mts_group_status= Relay_log_info::MTS_END_GROUP;
3347 if (rli->curr_group_isolated)
3348 set_mts_isolate_group();
3349 if (!ptr_group)
3350 ptr_group= gaq->get_job_group(rli->gaq->assigned_group_index);
3351
3352 assert(ret_worker != NULL);
3353
3354 /*
3355 The following two blocks are executed if the worker has not been
3356 notified about new relay-log or a new checkpoints.
3357 Relay-log string is freed by Coordinator, Worker deallocates
3358 strings in the checkpoint block.
3359 However if the worker exits earlier reclaiming for both happens anyway at
3360 GAQ delete.
3361 */
3362 if (!ret_worker->relay_log_change_notified)
3363 {
3364 /*
3365 Prior this event, C rotated the relay log to drop each
3366 Worker's notified flag. Now group terminating event initiates
3367 the new relay-log (where the current event is from) name
3368 delivery to Worker that will receive it in commit_positions().
3369 */
3370 assert(ptr_group->group_relay_log_name == NULL);
3371
3372 ptr_group->group_relay_log_name= (char *)
3373 my_malloc(key_memory_log_event,
3374 strlen(rli->
3375 get_group_relay_log_name()) + 1, MYF(MY_WME));
3376 strcpy(ptr_group->group_relay_log_name,
3377 rli->get_event_relay_log_name());
3378
3379 assert(ptr_group->group_relay_log_name != NULL);
3380
3381 ret_worker->relay_log_change_notified= TRUE;
3382 }
3383
3384 if (!ret_worker->checkpoint_notified)
3385 {
3386 if (!ptr_group)
3387 ptr_group= gaq->get_job_group(rli->gaq->assigned_group_index);
3388 ptr_group->checkpoint_log_name=
3389 my_strdup(key_memory_log_event, rli->get_group_master_log_name(), MYF(MY_WME));
3390 ptr_group->checkpoint_log_pos= rli->get_group_master_log_pos();
3391 ptr_group->checkpoint_relay_log_name=
3392 my_strdup(key_memory_log_event, rli->get_group_relay_log_name(), MYF(MY_WME));
3393 ptr_group->checkpoint_relay_log_pos= rli->get_group_relay_log_pos();
3394 ptr_group->shifted= ret_worker->bitmap_shifted;
3395 ret_worker->bitmap_shifted= 0;
3396 ret_worker->checkpoint_notified= TRUE;
3397 }
3398 ptr_group->checkpoint_seqno= rli->checkpoint_seqno;
3399 ptr_group->ts= common_header->when.tv_sec + (time_t) exec_time; // Seconds_behind_master related
3400 rli->checkpoint_seqno++;
3401 /*
3402 Coordinator should not use the main memroot however its not
3403 reset elsewhere either, so let's do it safe way.
3404 The main mem root is also reset by the SQL thread in at the end
3405 of applying which Coordinator does not do in this case.
3406 That concludes the memroot reset can't harm anything in SQL thread roles
3407 after Coordinator has finished its current scheduling.
3408 */
3409 free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
3410
3411 #ifndef NDEBUG
3412 w_rr++;
3413 #endif
3414
3415 }
3416
3417 DBUG_RETURN (ret_worker);
3418 }
3419
3420
apply_gtid_event(Relay_log_info * rli)3421 int Log_event::apply_gtid_event(Relay_log_info *rli)
3422 {
3423 DBUG_ENTER("LOG_EVENT:apply_gtid_event");
3424
3425 int error= 0;
3426 if (rli->curr_group_da.size() < 1)
3427 DBUG_RETURN(1);
3428
3429 Log_event* ev= rli->curr_group_da[0].data;
3430 assert(ev->get_type_code() == binary_log::GTID_LOG_EVENT ||
3431 ev->get_type_code() ==
3432 binary_log::ANONYMOUS_GTID_LOG_EVENT);
3433
3434 error= ev->do_apply_event(rli);
3435 /* Clean up */
3436 delete ev;
3437 rli->curr_group_da.clear();
3438 rli->curr_group_seen_gtid= false;
3439 /*
3440 Removes the job from the (G)lobal (A)ssigned (Q)ueue after
3441 applying it.
3442 */
3443 assert(rli->gaq->len > 0);
3444 Slave_job_group g= Slave_job_group();
3445 rli->gaq->de_tail(&g);
3446 /*
3447 The rli->mts_groups_assigned is increased when adding the slave job
3448 generated for the gtid into the (G)lobal (A)ssigned (Q)ueue. So we
3449 decrease it here.
3450 */
3451 rli->mts_groups_assigned--;
3452
3453 DBUG_RETURN(error);
3454 }
3455
3456
3457 /**
3458 Scheduling event to execute in parallel or execute it directly.
3459 In MTS case the event gets associated with either Coordinator or a
3460 Worker. A special case of the association is NULL when the Worker
3461 can't be decided yet. In the single threaded sequential mode the
3462 event maps to SQL thread rli.
3463
3464 @note in case of MTS failure Coordinator destroys all gathered
3465 deferred events.
3466
3467 @return 0 as success, otherwise a failure.
3468 */
apply_event(Relay_log_info * rli)3469 int Log_event::apply_event(Relay_log_info *rli)
3470 {
3471 DBUG_ENTER("LOG_EVENT:apply_event");
3472 DBUG_PRINT("info", ("event_type=%s", get_type_str()));
3473 bool parallel= FALSE;
3474 enum enum_mts_event_exec_mode actual_exec_mode= EVENT_EXEC_PARALLEL;
3475 THD *rli_thd= rli->info_thd;
3476
3477 worker= rli;
3478
3479 if (rli->is_mts_recovery())
3480 {
3481 bool skip=
3482 bitmap_is_set(&rli->recovery_groups, rli->mts_recovery_index) &&
3483 (get_mts_execution_mode(::server_id,
3484 rli->mts_group_status ==
3485 Relay_log_info::MTS_IN_GROUP,
3486 rli->current_mts_submode->get_type() ==
3487 MTS_PARALLEL_TYPE_DB_NAME)
3488 == EVENT_EXEC_PARALLEL);
3489 if (skip)
3490 {
3491 DBUG_RETURN(0);
3492 }
3493 else
3494 {
3495 DBUG_RETURN(do_apply_event(rli));
3496 }
3497 }
3498
3499 if (!(parallel= rli->is_parallel_exec()) ||
3500 ((actual_exec_mode=
3501 get_mts_execution_mode(::server_id,
3502 rli->mts_group_status ==
3503 Relay_log_info::MTS_IN_GROUP,
3504 rli->current_mts_submode->get_type() ==
3505 MTS_PARALLEL_TYPE_DB_NAME))
3506 != EVENT_EXEC_PARALLEL))
3507 {
3508 if (parallel)
3509 {
3510 /*
3511 There are two classes of events that Coordinator executes
3512 itself. One e.g the master Rotate requires all Workers to finish up
3513 their assignments. The other async class, e.g the slave Rotate,
3514 can't have this such synchronization because Worker might be waiting
3515 for terminal events to finish.
3516 */
3517
3518 if (actual_exec_mode != EVENT_EXEC_ASYNC)
3519 {
3520 /*
3521 this event does not split the current group but is indeed
3522 a separator beetwen two master's binlog therefore requiring
3523 Workers to sync.
3524 */
3525 if (rli->curr_group_da.size() > 0 &&
3526 is_mts_db_partitioned(rli) &&
3527 get_type_code() != binary_log::INCIDENT_EVENT)
3528 {
3529 char llbuff[22];
3530 /*
3531 Possible reason is a old version binlog sequential event
3532 wrappped with BEGIN/COMMIT or preceeded by User|Int|Random- var.
3533 MTS has to stop to suggest restart in the permanent sequential mode.
3534 */
3535 llstr(rli->get_event_relay_log_pos(), llbuff);
3536 my_error(ER_MTS_CANT_PARALLEL, MYF(0),
3537 get_type_str(), rli->get_event_relay_log_name(), llbuff,
3538 "possible malformed group of events from an old master");
3539
3540 /* Coordinator cant continue, it marks MTS group status accordingly */
3541 rli->mts_group_status= Relay_log_info::MTS_KILLED_GROUP;
3542
3543 goto err;
3544 }
3545
3546 if (get_type_code() == binary_log::INCIDENT_EVENT &&
3547 rli->curr_group_da.size() > 0 &&
3548 rli->current_mts_submode->get_type() ==
3549 MTS_PARALLEL_TYPE_LOGICAL_CLOCK)
3550 {
3551 #ifndef NDEBUG
3552 assert(rli->curr_group_da.size() == 1);
3553 Log_event* ev= rli->curr_group_da[0].data;
3554 assert(ev->get_type_code() == binary_log::GTID_LOG_EVENT ||
3555 ev->get_type_code() ==
3556 binary_log::ANONYMOUS_GTID_LOG_EVENT);
3557 #endif
3558 /*
3559 With MTS logical clock mode, when coordinator is applying an
3560 incident event, it must withdraw delegated_job increased by
3561 the incident's GTID before waiting for workers to finish.
3562 So that it can exit from mts_checkpoint_routine.
3563 */
3564 ((Mts_submode_logical_clock*)rli->current_mts_submode)->
3565 withdraw_delegated_job();
3566 }
3567 /*
3568 Marking sure the event will be executed in sequential mode.
3569 */
3570 if (rli->current_mts_submode->wait_for_workers_to_finish(rli) == -1)
3571 {
3572 // handle synchronization error
3573 rli->report(WARNING_LEVEL, 0,
3574 "Slave worker thread has failed to apply an event. As a "
3575 "consequence, the coordinator thread is stopping "
3576 "execution.");
3577 DBUG_RETURN(-1);
3578 }
3579 /*
3580 Given not in-group mark the event handler can invoke checkpoint
3581 update routine in the following course.
3582 */
3583 assert(rli->mts_group_status == Relay_log_info::MTS_NOT_IN_GROUP
3584 || !is_mts_db_partitioned(rli));
3585
3586 if (get_type_code() == binary_log::INCIDENT_EVENT &&
3587 rli->curr_group_da.size() > 0)
3588 {
3589 assert(rli->curr_group_da.size() == 1);
3590 /*
3591 When MTS is enabled, the incident event must be applied by the
3592 coordinator. So the coordinator applies its GTID right before
3593 applying the incident event..
3594 */
3595 int error= apply_gtid_event(rli);
3596 if (error)
3597 DBUG_RETURN(-1);
3598 }
3599
3600 #ifndef NDEBUG
3601 /* all Workers are idle as done through wait_for_workers_to_finish */
3602 for (uint k= 0; k < rli->curr_group_da.size(); k++)
3603 {
3604 assert(!(rli->workers[k]->usage_partition));
3605 assert(!(rli->workers[k]->jobs.len));
3606 }
3607 #endif
3608 }
3609 else
3610 {
3611 assert(actual_exec_mode == EVENT_EXEC_ASYNC);
3612 }
3613 }
3614 DBUG_RETURN(do_apply_event(rli));
3615 }
3616
3617 assert(actual_exec_mode == EVENT_EXEC_PARALLEL);
3618 assert(!(rli->curr_group_seen_begin && ends_group()) ||
3619 /*
3620 This is an empty group being processed due to gtids.
3621 */
3622 (rli->curr_group_seen_begin && rli->curr_group_seen_gtid
3623 && ends_group()) || is_mts_db_partitioned(rli) ||
3624 rli->last_assigned_worker ||
3625 /*
3626 Begin_load_query can be logged w/o db info and within
3627 Begin/Commit. That's a pattern forcing sequential
3628 applying of LOAD-DATA.
3629 */
3630 (rli->curr_group_da.back().data->
3631 get_type_code() == binary_log::BEGIN_LOAD_QUERY_EVENT) ||
3632 /*
3633 Delete_file can also be logged w/o db info and within
3634 Begin/Commit. That's a pattern forcing sequential
3635 applying of LOAD-DATA.
3636 */
3637 (rli->curr_group_da.back().data->
3638 get_type_code() == binary_log::DELETE_FILE_EVENT));
3639
3640 worker= NULL;
3641 rli->mts_group_status= Relay_log_info::MTS_IN_GROUP;
3642
3643 worker= (Relay_log_info*)
3644 (rli->last_assigned_worker= get_slave_worker(rli));
3645
3646 #ifndef NDEBUG
3647 if (rli->last_assigned_worker)
3648 DBUG_PRINT("mts", ("Assigning job to worker %lu",
3649 rli->last_assigned_worker->id));
3650 #endif
3651
3652 err:
3653 if (rli_thd->is_error() || (!worker && rli->abort_slave))
3654 {
3655 assert(!worker);
3656
3657 /*
3658 Destroy all deferred buffered events but the current prior to exit.
3659 The current one will be deleted as an event never destined/assigned
3660 to any Worker in Coordinator's regular execution path.
3661 */
3662 for (uint k= 0; k < rli->curr_group_da.size(); k++)
3663 {
3664 Log_event *ev_buf= rli->curr_group_da[k].data;
3665 if (this != ev_buf)
3666 delete ev_buf;
3667 }
3668 rli->curr_group_da.clear();
3669 }
3670 else
3671 {
3672 assert(worker || rli->curr_group_assigned_parts.size() == 0);
3673 }
3674
3675 DBUG_RETURN((!(rli_thd->is_error() || (!worker && rli->abort_slave)) ||
3676 DBUG_EVALUATE_IF("fault_injection_get_slave_worker", 1, 0)) ?
3677 0 : -1);
3678 }
3679
3680 #endif
3681
3682 /**************************************************************************
3683 Query_log_event methods
3684 **************************************************************************/
3685
3686 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
3687
3688 /**
3689 This (which is used only for SHOW BINLOG EVENTS) could be updated to
3690 print SET @@session_var=. But this is not urgent, as SHOW BINLOG EVENTS is
3691 only an information, it does not produce suitable queries to replay (for
3692 example it does not print LOAD DATA INFILE).
3693 @todo
3694 show the catalog ??
3695 */
3696
pack_info(Protocol * protocol)3697 int Query_log_event::pack_info(Protocol *protocol)
3698 {
3699 // TODO: show the catalog ??
3700 String str_buf;
3701 // Add use `DB` to the string if required
3702 if (!(common_header->flags & LOG_EVENT_SUPPRESS_USE_F)
3703 && db && db_len)
3704 {
3705 str_buf.append("use ");
3706 append_identifier(this->thd, &str_buf, db, db_len);
3707 str_buf.append("; ");
3708 }
3709 // Add the query to the string
3710 if (query && q_len)
3711 str_buf.append(query);
3712 // persist the buffer in protocol
3713 protocol->store(str_buf.ptr(), str_buf.length(), &my_charset_bin);
3714 return 0;
3715 }
3716 #endif
3717
3718 #ifndef MYSQL_CLIENT
3719
3720 /**
3721 Utility function for the next method (Query_log_event::write()) .
3722 */
write_str_with_code_and_len(uchar ** dst,const char * src,size_t len,uint code)3723 static void write_str_with_code_and_len(uchar **dst, const char *src,
3724 size_t len, uint code)
3725 {
3726 /*
3727 only 1 byte to store the length of catalog, so it should not
3728 surpass 255
3729 */
3730 assert(len <= 255);
3731 assert(src);
3732 *((*dst)++)= code;
3733 *((*dst)++)= (uchar) len;
3734 memmove(*dst, src, len);
3735 (*dst)+= len;
3736 }
3737
3738
3739 /**
3740 Query_log_event::write().
3741
3742 @note
3743 In this event we have to modify the header to have the correct
3744 EVENT_LEN_OFFSET as we don't yet know how many status variables we
3745 will print!
3746 */
3747
write(IO_CACHE * file)3748 bool Query_log_event::write(IO_CACHE* file)
3749 {
3750 uchar buf[Binary_log_event::QUERY_HEADER_LEN + MAX_SIZE_LOG_EVENT_STATUS];
3751 uchar *start, *start_of_status;
3752 size_t event_length;
3753
3754 if (!query)
3755 return 1; // Something wrong with event
3756
3757 /*
3758 We want to store the thread id:
3759 (- as an information for the user when he reads the binlog)
3760 - if the query uses temporary table: for the slave SQL thread to know to
3761 which master connection the temp table belongs.
3762 Now imagine we (write()) are called by the slave SQL thread (we are
3763 logging a query executed by this thread; the slave runs with
3764 --log-slave-updates). Then this query will be logged with
3765 thread_id=the_thread_id_of_the_SQL_thread. Imagine that 2 temp tables of
3766 the same name were created simultaneously on the master (in the masters
3767 binlog you have
3768 CREATE TEMPORARY TABLE t; (thread 1)
3769 CREATE TEMPORARY TABLE t; (thread 2)
3770 ...)
3771 then in the slave's binlog there will be
3772 CREATE TEMPORARY TABLE t; (thread_id_of_the_slave_SQL_thread)
3773 CREATE TEMPORARY TABLE t; (thread_id_of_the_slave_SQL_thread)
3774 which is bad (same thread id!).
3775
3776 To avoid this, we log the thread's thread id EXCEPT for the SQL
3777 slave thread for which we log the original (master's) thread id.
3778 Now this moves the bug: what happens if the thread id on the
3779 master was 10 and when the slave replicates the query, a
3780 connection number 10 is opened by a normal client on the slave,
3781 and updates a temp table of the same name? We get a problem
3782 again. To avoid this, in the handling of temp tables (sql_base.cc)
3783 we use thread_id AND server_id. TODO when this is merged into
3784 4.1: in 4.1, slave_proxy_id has been renamed to pseudo_thread_id
3785 and is a session variable: that's to make mysqlbinlog work with
3786 temp tables. We probably need to introduce
3787
3788 SET PSEUDO_SERVER_ID
3789 for mysqlbinlog in 4.1. mysqlbinlog would print:
3790 SET PSEUDO_SERVER_ID=
3791 SET PSEUDO_THREAD_ID=
3792 for each query using temp tables.
3793 */
3794 int4store(buf + Q_THREAD_ID_OFFSET, slave_proxy_id);
3795 int4store(buf + Q_EXEC_TIME_OFFSET, exec_time);
3796 buf[Q_DB_LEN_OFFSET] = (char) db_len;
3797 int2store(buf + Q_ERR_CODE_OFFSET, error_code);
3798
3799 /*
3800 You MUST always write status vars in increasing order of code. This
3801 guarantees that a slightly older slave will be able to parse those he
3802 knows.
3803 */
3804 start_of_status= start= buf+Binary_log_event::QUERY_HEADER_LEN;
3805 if (flags2_inited)
3806 {
3807 *start++= Q_FLAGS2_CODE;
3808 int4store(start, flags2);
3809 start+= 4;
3810 }
3811 if (sql_mode_inited)
3812 {
3813 *start++= Q_SQL_MODE_CODE;
3814 int8store(start, sql_mode);
3815 start+= 8;
3816 }
3817 if (catalog_len) // i.e. this var is inited (false for 4.0 events)
3818 {
3819 write_str_with_code_and_len(&start,
3820 catalog, catalog_len, Q_CATALOG_NZ_CODE);
3821 /*
3822 In 5.0.x where x<4 masters we used to store the end zero here. This was
3823 a waste of one byte so we don't do it in x>=4 masters. We change code to
3824 Q_CATALOG_NZ_CODE, because re-using the old code would make x<4 slaves
3825 of this x>=4 master segfault (expecting a zero when there is
3826 none). Remaining compatibility problems are: the older slave will not
3827 find the catalog; but it is will not crash, and it's not an issue
3828 that it does not find the catalog as catalogs were not used in these
3829 older MySQL versions (we store it in binlog and read it from relay log
3830 but do nothing useful with it). What is an issue is that the older slave
3831 will stop processing the Q_* blocks (and jumps to the db/query) as soon
3832 as it sees unknown Q_CATALOG_NZ_CODE; so it will not be able to read
3833 Q_AUTO_INCREMENT*, Q_CHARSET and so replication will fail silently in
3834 various ways. Documented that you should not mix alpha/beta versions if
3835 they are not exactly the same version, with example of 5.0.3->5.0.2 and
3836 5.0.4->5.0.3. If replication is from older to new, the new will
3837 recognize Q_CATALOG_CODE and have no problem.
3838 */
3839 }
3840 if (auto_increment_increment != 1 || auto_increment_offset != 1)
3841 {
3842 *start++= Q_AUTO_INCREMENT;
3843 int2store(start, static_cast<uint16>(auto_increment_increment));
3844 int2store(start+2, static_cast<uint16>(auto_increment_offset));
3845 start+= 4;
3846 }
3847 if (charset_inited)
3848 {
3849 *start++= Q_CHARSET_CODE;
3850 memcpy(start, charset, 6);
3851 start+= 6;
3852 }
3853 if (time_zone_len)
3854 {
3855 /* In the TZ sys table, column Name is of length 64 so this should be ok */
3856 assert(time_zone_len <= MAX_TIME_ZONE_NAME_LENGTH);
3857 write_str_with_code_and_len(&start,
3858 time_zone_str, time_zone_len, Q_TIME_ZONE_CODE);
3859 }
3860 if (lc_time_names_number)
3861 {
3862 assert(lc_time_names_number <= 0xFF);
3863 *start++= Q_LC_TIME_NAMES_CODE;
3864 int2store(start, lc_time_names_number);
3865 start+= 2;
3866 }
3867 if (charset_database_number)
3868 {
3869 assert(charset_database_number <= 0xFF);
3870 *start++= Q_CHARSET_DATABASE_CODE;
3871 int2store(start, charset_database_number);
3872 start+= 2;
3873 }
3874 if (table_map_for_update)
3875 {
3876 *start++= Q_TABLE_MAP_FOR_UPDATE_CODE;
3877 int8store(start, table_map_for_update);
3878 start+= 8;
3879 }
3880 if (master_data_written != 0)
3881 {
3882 /*
3883 Q_MASTER_DATA_WRITTEN_CODE only exists in relay logs where the master
3884 has binlog_version<4 and the slave has binlog_version=4. See comment
3885 for master_data_written in log_event.h for details.
3886 */
3887 *start++= Q_MASTER_DATA_WRITTEN_CODE;
3888 int4store(start, static_cast<uint32>(master_data_written));
3889 start+= 4;
3890 }
3891
3892 if (thd && thd->need_binlog_invoker())
3893 {
3894 LEX_CSTRING invoker_user;
3895 LEX_CSTRING invoker_host;
3896 memset(&invoker_user, 0, sizeof(invoker_user));
3897 memset(&invoker_host, 0, sizeof(invoker_host));
3898
3899 if (thd->slave_thread && thd->has_invoker())
3900 {
3901 /* user will be null, if master is older than this patch */
3902 invoker_user= thd->get_invoker_user();
3903 invoker_host= thd->get_invoker_host();
3904 }
3905 else
3906 {
3907 Security_context *ctx= thd->security_context();
3908 LEX_CSTRING priv_user= ctx->priv_user();
3909 LEX_CSTRING priv_host= ctx->priv_host();
3910
3911 invoker_user.length= priv_user.length;
3912 invoker_user.str= (char *) priv_user.str;
3913 if (priv_host.str[0] != '\0')
3914 {
3915 invoker_host.str= (char *) priv_host.str;
3916 invoker_host.length= priv_host.length;
3917 }
3918 }
3919
3920 *start++= Q_INVOKER;
3921
3922 /*
3923 Store user length and user. The max length of use is 16, so 1 byte is
3924 enough to store the user's length.
3925 */
3926 *start++= (uchar)invoker_user.length;
3927 memcpy(start, invoker_user.str, invoker_user.length);
3928 start+= invoker_user.length;
3929
3930 /*
3931 Store host length and host. The max length of host is 60, so 1 byte is
3932 enough to store the host's length.
3933 */
3934 *start++= (uchar)invoker_host.length;
3935 memcpy(start, invoker_host.str, invoker_host.length);
3936 start+= invoker_host.length;
3937 }
3938
3939 if (thd && thd->get_binlog_accessed_db_names() != NULL)
3940 {
3941 uchar dbs;
3942 *start++= Q_UPDATED_DB_NAMES;
3943
3944 compile_time_assert(MAX_DBS_IN_EVENT_MTS <= OVER_MAX_DBS_IN_EVENT_MTS);
3945
3946 /*
3947 In case of the number of db:s exceeds MAX_DBS_IN_EVENT_MTS
3948 no db:s is written and event will require the sequential applying on slave.
3949 */
3950 dbs=
3951 (thd->get_binlog_accessed_db_names()->elements <= MAX_DBS_IN_EVENT_MTS) ?
3952 thd->get_binlog_accessed_db_names()->elements : OVER_MAX_DBS_IN_EVENT_MTS;
3953
3954 assert(dbs != 0);
3955
3956 if (dbs <= MAX_DBS_IN_EVENT_MTS)
3957 {
3958 List_iterator_fast<char> it(*thd->get_binlog_accessed_db_names());
3959 char *db_name= it++;
3960 /*
3961 the single "" db in the acccessed db list corresponds to the same as
3962 exceeds MAX_DBS_IN_EVENT_MTS case, so dbs is set to the over-max.
3963 */
3964 if (dbs == 1 && !strcmp(db_name, ""))
3965 dbs= OVER_MAX_DBS_IN_EVENT_MTS;
3966 *start++= dbs;
3967 if (dbs != OVER_MAX_DBS_IN_EVENT_MTS)
3968 do
3969 {
3970 strcpy((char*) start, db_name);
3971 start += strlen(db_name) + 1;
3972 } while ((db_name= it++));
3973 }
3974 else
3975 {
3976 *start++= dbs;
3977 }
3978 }
3979
3980 if (thd && thd->query_start_usec_used)
3981 {
3982 *start++= Q_MICROSECONDS;
3983 get_time();
3984 int3store(start, common_header->when.tv_usec);
3985 start+= 3;
3986 }
3987
3988 if (thd && thd->binlog_need_explicit_defaults_ts == true)
3989 {
3990 *start++= Q_EXPLICIT_DEFAULTS_FOR_TIMESTAMP;
3991 *start++= thd->variables.explicit_defaults_for_timestamp;
3992 }
3993 /*
3994 NOTE: When adding new status vars, please don't forget to update
3995 the MAX_SIZE_LOG_EVENT_STATUS in log_event.h
3996
3997 Here there could be code like
3998 if (command-line-option-which-says-"log_this_variable" && inited)
3999 {
4000 *start++= Q_THIS_VARIABLE_CODE;
4001 int4store(start, this_variable);
4002 start+= 4;
4003 }
4004 */
4005
4006 /* Store length of status variables */
4007 status_vars_len= (uint) (start-start_of_status);
4008 assert(status_vars_len <= MAX_SIZE_LOG_EVENT_STATUS);
4009 int2store(buf + Q_STATUS_VARS_LEN_OFFSET, status_vars_len);
4010
4011 /*
4012 Calculate length of whole event
4013 The "1" below is the \0 in the db's length
4014 */
4015 event_length= (uint) (start-buf) + get_post_header_size_for_derived() + db_len + 1 + q_len;
4016
4017 return (write_header(file, event_length) ||
4018 wrapper_my_b_safe_write(file, (uchar*) buf, Binary_log_event::QUERY_HEADER_LEN) ||
4019 write_post_header_for_derived(file) ||
4020 wrapper_my_b_safe_write(file, start_of_status,
4021 (uint) (start-start_of_status)) ||
4022 wrapper_my_b_safe_write(file, db ? (uchar*) db : (uchar*)"", db_len + 1) ||
4023 wrapper_my_b_safe_write(file, (uchar*) query, q_len) ||
4024 write_footer(file)) ? 1 : 0;
4025 }
4026
4027
4028 /**
4029 The simplest constructor that could possibly work. This is used for
4030 creating static objects that have a special meaning and are invisible
4031 to the log.
4032 */
Query_log_event()4033 Query_log_event::Query_log_event()
4034 : binary_log::Query_event(),
4035 Log_event(header(), footer()),
4036 data_buf(NULL)
4037 {}
4038
4039 /**
4040 Creates a Query Log Event.
4041
4042 @param thd_arg Thread handle
4043 @param query_arg Array of char representing the query
4044 @param query_length Size of the 'query_arg' array
4045 @param using_trans Indicates that there are transactional changes.
4046 @param immediate After being written to the binary log, the event
4047 must be flushed immediately. This indirectly implies
4048 the stmt-cache.
4049 @param suppress_use Suppress the generation of 'USE' statements
4050 @param errcode The error code of the query
4051 @param ignore Ignore user's statement, i.e. lex information, while
4052 deciding which cache must be used.
4053 */
Query_log_event(THD * thd_arg,const char * query_arg,size_t query_length,bool using_trans,bool immediate,bool suppress_use,int errcode,bool ignore_cmd_internals)4054 Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
4055 size_t query_length, bool using_trans,
4056 bool immediate, bool suppress_use,
4057 int errcode, bool ignore_cmd_internals)
4058
4059 : binary_log::Query_event(query_arg,
4060 thd_arg->catalog().str,
4061 thd_arg->db().str,
4062 query_length,
4063 thd_arg->thread_id(),
4064 thd_arg->variables.sql_mode,
4065 thd_arg->variables.auto_increment_increment,
4066 thd_arg->variables.auto_increment_offset,
4067 thd_arg->variables.lc_time_names->number,
4068 (ulonglong)thd_arg->table_map_for_update,
4069 errcode,
4070 thd_arg->db().str ? strlen(thd_arg->db().str) : 0,
4071 thd_arg->catalog().str ? strlen(thd_arg->catalog().str) : 0),
4072 Log_event(thd_arg,
4073 (thd_arg->thread_specific_used ? LOG_EVENT_THREAD_SPECIFIC_F :
4074 0) |
4075 (suppress_use ? LOG_EVENT_SUPPRESS_USE_F : 0),
4076 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
4077 Log_event::EVENT_STMT_CACHE,
4078 Log_event::EVENT_NORMAL_LOGGING,
4079 header(), footer()),
4080 data_buf(0)
4081 {
4082 DBUG_EXECUTE_IF("debug_lock_before_query_log_event",
4083 DBUG_SYNC_POINT("debug_lock.before_query_log_event", 10););
4084
4085 /* save the original thread id; we already know the server id */
4086 slave_proxy_id= thd_arg->variables.pseudo_thread_id;
4087 if (query != 0)
4088 is_valid_param= true;
4089 /*
4090 exec_time calculation has changed to use the same method that is used
4091 to fill out "thd_arg->start_time"
4092 */
4093
4094 struct timeval end_time;
4095 ulonglong micro_end_time= my_micro_time();
4096 my_micro_time_to_timeval(micro_end_time, &end_time);
4097
4098 exec_time= end_time.tv_sec - thd_arg->start_time.tv_sec;
4099
4100 /**
4101 @todo this means that if we have no catalog, then it is replicated
4102 as an existing catalog of length zero. is that safe? /sven
4103 */
4104 catalog_len = (catalog) ? strlen(catalog) : 0;
4105 /* status_vars_len is set just before writing the event */
4106 db_len = (db) ? strlen(db) : 0;
4107 if (thd_arg->variables.collation_database != thd_arg->db_charset)
4108 charset_database_number= thd_arg->variables.collation_database->number;
4109
4110 /*
4111 We only replicate over the bits of flags2 that we need: the rest
4112 are masked out by "& OPTIONS_WRITTEN_TO_BINLOG".
4113
4114 We also force AUTOCOMMIT=1. Rationale (cf. BUG#29288): After
4115 fixing BUG#26395, we always write BEGIN and COMMIT around all
4116 transactions (even single statements in autocommit mode). This is
4117 so that replication from non-transactional to transactional table
4118 and error recovery from XA to non-XA table should work as
4119 expected. The BEGIN/COMMIT are added in log.cc. However, there is
4120 one exception: MyISAM bypasses log.cc and writes directly to the
4121 binlog. So if autocommit is off, master has MyISAM, and slave has
4122 a transactional engine, then the slave will just see one long
4123 never-ending transaction. The only way to bypass explicit
4124 BEGIN/COMMIT in the binlog is by using a non-transactional table.
4125 So setting AUTOCOMMIT=1 will make this work as expected.
4126
4127 Note: explicitly replicate AUTOCOMMIT=1 from master. We do not
4128 assume AUTOCOMMIT=1 on slave; the slave still reads the state of
4129 the autocommit flag as written by the master to the binlog. This
4130 behavior may change after WL#4162 has been implemented.
4131 */
4132 flags2= (uint32) (thd_arg->variables.option_bits &
4133 (OPTIONS_WRITTEN_TO_BIN_LOG & ~OPTION_NOT_AUTOCOMMIT));
4134 assert(thd_arg->variables.character_set_client->number < 256*256);
4135 assert(thd_arg->variables.collation_connection->number < 256*256);
4136 assert(thd_arg->variables.collation_server->number < 256*256);
4137 assert(thd_arg->variables.character_set_client->mbminlen == 1);
4138 int2store(charset, thd_arg->variables.character_set_client->number);
4139 int2store(charset+2, thd_arg->variables.collation_connection->number);
4140 int2store(charset+4, thd_arg->variables.collation_server->number);
4141 if (thd_arg->time_zone_used)
4142 {
4143 /*
4144 Note that our event becomes dependent on the Time_zone object
4145 representing the time zone. Fortunately such objects are never deleted
4146 or changed during mysqld's lifetime.
4147 */
4148 time_zone_len= thd_arg->variables.time_zone->get_name()->length();
4149 time_zone_str= thd_arg->variables.time_zone->get_name()->ptr();
4150 }
4151 else
4152 time_zone_len= 0;
4153
4154 /*
4155 In what follows, we define in which cache, trx-cache or stmt-cache,
4156 this Query Log Event will be written to.
4157
4158 If ignore_cmd_internals is defined, we rely on the is_trans flag to
4159 choose the cache and this is done in the base class Log_event. False
4160 means that the stmt-cache will be used and upon statement commit/rollback
4161 the cache will be flushed to disk. True means that the trx-cache will
4162 be used and upon transaction commit/rollback the cache will be flushed
4163 to disk.
4164
4165 If set immediate cache is defined, for convenience, we automatically
4166 use the stmt-cache. This mean that the statement will be written
4167 to the stmt-cache and immediately flushed to disk without waiting
4168 for a commit/rollback notification.
4169
4170 For example, the cluster/ndb captures a request to execute a DDL
4171 statement and synchronously propagate it to all available MySQL
4172 servers. Unfortunately, the current protocol assumes that the
4173 generated events are immediately written to diks and does not check
4174 for commit/rollback.
4175
4176 Upon dropping a connection, DDLs (i.e. DROP TEMPORARY TABLE) are
4177 generated and in this case the statements have the immediate flag
4178 set because there is no commit/rollback.
4179
4180 If the immediate flag is not set, the decision on the cache is based
4181 on the current statement and the flag is_trans, which indicates if
4182 a transactional engine was updated.
4183
4184 Statements are classifed as row producers (i.e. can_generate_row_events())
4185 or non-row producers. Non-row producers, DDL in general, are treated
4186 as the immediate flag was set and for convenience are written to the
4187 stmt-cache and immediately flushed to disk.
4188
4189 Row producers are handled in general according to the is_trans flag.
4190 False means that the stmt-cache will be used and upon statement
4191 commit/rollback the cache will be flushed to disk. True means that the
4192 trx-cache will be used and upon transaction commit/rollback the cache
4193 will be flushed to disk.
4194
4195 Unfortunately, there are exceptions to this non-row and row producer
4196 rules:
4197
4198 . The SAVEPOINT, ROLLBACK TO SAVEPOINT, RELEASE SAVEPOINT does not
4199 have the flag is_trans set because there is no updated engine but
4200 must be written to the trx-cache.
4201
4202 . SET If auto-commit is on, it must not go through a cache.
4203
4204 . CREATE TABLE is classfied as non-row producer but CREATE TEMPORARY
4205 must be handled as row producer.
4206
4207 . DROP TABLE is classfied as non-row producer but DROP TEMPORARY
4208 must be handled as row producer.
4209
4210 Finally, some statements that does not have the flag is_trans set may
4211 be written to the trx-cache based on the following criteria:
4212
4213 . updated both a transactional and a non-transactional engine (i.e.
4214 stmt_has_updated_trans_table()).
4215
4216 . accessed both a transactional and a non-transactional engine and
4217 is classified as unsafe (i.e. is_mixed_stmt_unsafe()).
4218
4219 . is executed within a transaction and previously a transactional
4220 engine was updated and the flag binlog_direct_non_trans_update
4221 is set.
4222 */
4223 if (ignore_cmd_internals)
4224 return;
4225
4226 /*
4227 TRUE defines that the trx-cache must be used.
4228 */
4229 bool cmd_can_generate_row_events= FALSE;
4230 /*
4231 TRUE defines that the trx-cache must be used.
4232 */
4233 bool cmd_must_go_to_trx_cache= FALSE;
4234
4235 LEX *lex= thd->lex;
4236 if (!immediate)
4237 {
4238 switch (lex->sql_command)
4239 {
4240 case SQLCOM_DROP_TABLE:
4241 cmd_can_generate_row_events= lex->drop_temporary &&
4242 thd->in_multi_stmt_transaction_mode();
4243 break;
4244 case SQLCOM_CREATE_TABLE:
4245 cmd_must_go_to_trx_cache= lex->select_lex->item_list.elements &&
4246 thd->is_current_stmt_binlog_format_row();
4247 cmd_can_generate_row_events=
4248 ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
4249 thd->in_multi_stmt_transaction_mode()) || cmd_must_go_to_trx_cache;
4250 break;
4251 case SQLCOM_SET_OPTION:
4252 if (lex->autocommit)
4253 cmd_can_generate_row_events= cmd_must_go_to_trx_cache= FALSE;
4254 else
4255 cmd_can_generate_row_events= TRUE;
4256 break;
4257 case SQLCOM_RELEASE_SAVEPOINT:
4258 case SQLCOM_ROLLBACK_TO_SAVEPOINT:
4259 case SQLCOM_SAVEPOINT:
4260 case SQLCOM_XA_PREPARE:
4261 cmd_can_generate_row_events= cmd_must_go_to_trx_cache= TRUE;
4262 break;
4263 default:
4264 cmd_can_generate_row_events=
4265 sqlcom_can_generate_row_events(thd->lex->sql_command);
4266 break;
4267 }
4268 }
4269
4270 if (cmd_can_generate_row_events)
4271 {
4272 cmd_must_go_to_trx_cache= cmd_must_go_to_trx_cache || using_trans;
4273 if (cmd_must_go_to_trx_cache ||
4274 stmt_has_updated_trans_table(thd->get_transaction()->ha_trx_info(Transaction_ctx::STMT)) ||
4275 thd->lex->is_mixed_stmt_unsafe(thd->in_multi_stmt_transaction_mode(),
4276 thd->variables.binlog_direct_non_trans_update,
4277 trans_has_updated_trans_table(thd),
4278 thd->tx_isolation) ||
4279 (!thd->variables.binlog_direct_non_trans_update && trans_has_updated_trans_table(thd)))
4280 {
4281 event_logging_type= Log_event::EVENT_NORMAL_LOGGING;
4282 event_cache_type= Log_event::EVENT_TRANSACTIONAL_CACHE;
4283 }
4284 else
4285 {
4286 event_logging_type= Log_event::EVENT_NORMAL_LOGGING;
4287 event_cache_type= Log_event::EVENT_STMT_CACHE;
4288 }
4289 }
4290 else
4291 {
4292 event_logging_type= Log_event::EVENT_IMMEDIATE_LOGGING;
4293 event_cache_type= Log_event::EVENT_STMT_CACHE;
4294 }
4295
4296 assert(event_cache_type != Log_event::EVENT_INVALID_CACHE);
4297 assert(event_logging_type != Log_event::EVENT_INVALID_LOGGING);
4298 DBUG_PRINT("info",("Query_log_event has flags2: %lu sql_mode: %llu",
4299 (ulong) flags2, (ulonglong) sql_mode));
4300 }
4301 #endif /* MYSQL_CLIENT */
4302
4303
4304 /**
4305 This is used by the SQL slave thread to prepare the event before execution.
4306 */
Query_log_event(const char * buf,uint event_len,const Format_description_event * description_event,Log_event_type event_type)4307 Query_log_event::Query_log_event(const char* buf, uint event_len,
4308 const Format_description_event
4309 *description_event,
4310 Log_event_type event_type)
4311 :binary_log::Query_event(buf, event_len, description_event, event_type),
4312 Log_event(header(), footer())
4313 {
4314 DBUG_ENTER("Query_log_event::Query_log_event(char*,...)");
4315 slave_proxy_id= thread_id;
4316 exec_time= query_exec_time;
4317
4318 ulong buf_len= catalog_len + 1 +
4319 time_zone_len + 1 +
4320 user_len + 1 +
4321 host_len + 1 +
4322 data_len + 1;
4323 #if !defined(MYSQL_CLIENT)
4324 buf_len+= sizeof(size_t)/*for db_len */ + db_len + 1 + QUERY_CACHE_FLAGS_SIZE;
4325 #endif
4326
4327 if (!(data_buf = (Log_event_header::Byte*) my_malloc(key_memory_log_event,
4328 buf_len, MYF(MY_WME))))
4329 DBUG_VOID_RETURN;
4330 /*
4331 The data buffer is used by the slave SQL thread while applying
4332 the event. The catalog, time_zone)str, user, host, db, query
4333 are pointers to this data_buf. The function call below, points these
4334 const pointers to the data buffer.
4335 */
4336 if (!(fill_data_buf(data_buf, buf_len)))
4337 DBUG_VOID_RETURN;
4338
4339 if (query != 0 && q_len > 0)
4340 is_valid_param= true;
4341
4342 /**
4343 The buffer contains the following:
4344 +--------+-----------+------+------+---------+----+-------+
4345 | catlog | time_zone | user | host | db name | \0 | Query |
4346 +--------+-----------+------+------+---------+----+-------+
4347
4348 To support the query cache we append the following buffer to the above
4349 +-------+----------------------------------------+-------+
4350 |db len | uninitiatlized space of size of db len | FLAGS |
4351 +-------+----------------------------------------+-------+
4352
4353 The area of buffer starting from Query field all the way to the end belongs
4354 to the Query buffer and its structure is described in alloc_query() in
4355 sql_parse.cc
4356
4357 We append the db length at the end of the buffer. This will be used by
4358 Query_cache::send_result_to_client() in case the query cache is On.
4359 */
4360 #if !defined(MYSQL_CLIENT)
4361 size_t db_length= db_len;
4362 memcpy(data_buf + query_data_written, &db_length, sizeof(size_t));
4363 #endif
4364 DBUG_VOID_RETURN;
4365 }
4366
4367
4368 #ifdef MYSQL_CLIENT
4369 /**
4370 Query_log_event::print().
4371
4372 @todo
4373 print the catalog ??
4374 */
print_query_header(IO_CACHE * file,PRINT_EVENT_INFO * print_event_info)4375 void Query_log_event::print_query_header(IO_CACHE* file,
4376 PRINT_EVENT_INFO* print_event_info)
4377 {
4378 // TODO: print the catalog ??
4379 char buff[48], *end; // Enough for "SET TIMESTAMP=1305535348.123456"
4380 char quoted_id[1+ 2*FN_REFLEN+ 2];
4381 size_t quoted_len= 0;
4382 bool different_db= true;
4383 uint32 tmp;
4384
4385 if (!print_event_info->short_form)
4386 {
4387 print_header(file, print_event_info, FALSE);
4388 my_b_printf(file, "\t%s\tthread_id=%lu\texec_time=%lu\terror_code=%d\n",
4389 get_type_str(), (ulong) thread_id, (ulong) exec_time,
4390 error_code);
4391 }
4392
4393 if ((common_header->flags & LOG_EVENT_SUPPRESS_USE_F))
4394 {
4395 if (!is_trans_keyword())
4396 print_event_info->db[0]= '\0';
4397 }
4398 else if (db)
4399 {
4400 #ifdef MYSQL_SERVER
4401 quoted_len= my_strmov_quoted_identifier(this->thd, (char*)quoted_id, db, 0);
4402 #else
4403 quoted_len= my_strmov_quoted_identifier((char*)quoted_id, db);
4404 #endif
4405 quoted_id[quoted_len]= '\0';
4406 different_db= memcmp(print_event_info->db, db, db_len + 1);
4407 if (different_db)
4408 memcpy(print_event_info->db, db, db_len + 1);
4409 if (db[0] && different_db)
4410 my_b_printf(file, "use %s%s\n", quoted_id, print_event_info->delimiter);
4411 }
4412
4413 end= int10_to_str((long)common_header->when.tv_sec,
4414 my_stpcpy(buff,"SET TIMESTAMP="),10);
4415 if (common_header->when.tv_usec)
4416 end+= sprintf(end, ".%06d", (int) common_header->when.tv_usec);
4417 end= my_stpcpy(end, print_event_info->delimiter);
4418 *end++='\n';
4419 assert(end < buff + sizeof(buff));
4420 MY_ATTRIBUTE((unused)) int write_res=
4421 my_b_write(file, (uchar*) buff, (uint) (end-buff));
4422 assert(write_res == 0);
4423 if ((!print_event_info->thread_id_printed ||
4424 ((common_header->flags & LOG_EVENT_THREAD_SPECIFIC_F) &&
4425 thread_id != print_event_info->thread_id)))
4426 {
4427 // If --short-form, print deterministic value instead of pseudo_thread_id.
4428 my_b_printf(file,"SET @@session.pseudo_thread_id=%lu%s\n",
4429 short_form ? 999999999 : (ulong)thread_id,
4430 print_event_info->delimiter);
4431 print_event_info->thread_id= thread_id;
4432 print_event_info->thread_id_printed= 1;
4433 }
4434
4435 /*
4436 If flags2_inited==0, this is an event from 3.23 or 4.0; nothing to
4437 print (remember we don't produce mixed relay logs so there cannot be
4438 5.0 events before that one so there is nothing to reset).
4439 */
4440 if (likely(flags2_inited)) /* likely as this will mainly read 5.0 logs */
4441 {
4442 /* tmp is a bitmask of bits which have changed. */
4443 if (likely(print_event_info->flags2_inited))
4444 /* All bits which have changed */
4445 tmp= (print_event_info->flags2) ^ flags2;
4446 else /* that's the first Query event we read */
4447 {
4448 print_event_info->flags2_inited= 1;
4449 tmp= ~((uint32)0); /* all bits have changed */
4450 }
4451
4452 if (unlikely(tmp)) /* some bits have changed */
4453 {
4454 bool need_comma= 0;
4455 my_b_printf(file, "SET ");
4456 print_set_option(file, tmp, OPTION_NO_FOREIGN_KEY_CHECKS, ~flags2,
4457 "@@session.foreign_key_checks", &need_comma);
4458 print_set_option(file, tmp, OPTION_AUTO_IS_NULL, flags2,
4459 "@@session.sql_auto_is_null", &need_comma);
4460 print_set_option(file, tmp, OPTION_RELAXED_UNIQUE_CHECKS, ~flags2,
4461 "@@session.unique_checks", &need_comma);
4462 print_set_option(file, tmp, OPTION_NOT_AUTOCOMMIT, ~flags2,
4463 "@@session.autocommit", &need_comma);
4464 my_b_printf(file,"%s\n", print_event_info->delimiter);
4465 print_event_info->flags2= flags2;
4466 }
4467 }
4468
4469 /*
4470 Now the session variables;
4471 it's more efficient to pass SQL_MODE as a number instead of a
4472 comma-separated list.
4473 FOREIGN_KEY_CHECKS, SQL_AUTO_IS_NULL, UNIQUE_CHECKS are session-only
4474 variables (they have no global version; they're not listed in
4475 sql_class.h), The tests below work for pure binlogs or pure relay
4476 logs. Won't work for mixed relay logs but we don't create mixed
4477 relay logs (that is, there is no relay log with a format change
4478 except within the 3 first events, which mysqlbinlog handles
4479 gracefully). So this code should always be good.
4480 */
4481
4482 if (likely(sql_mode_inited) &&
4483 (unlikely(print_event_info->sql_mode != sql_mode ||
4484 !print_event_info->sql_mode_inited)))
4485 {
4486 my_b_printf(file,"SET @@session.sql_mode=%lu%s\n",
4487 (ulong)sql_mode, print_event_info->delimiter);
4488 print_event_info->sql_mode= sql_mode;
4489 print_event_info->sql_mode_inited= 1;
4490 }
4491 if (print_event_info->auto_increment_increment != auto_increment_increment ||
4492 print_event_info->auto_increment_offset != auto_increment_offset)
4493 {
4494 my_b_printf(file,"SET @@session.auto_increment_increment=%u, @@session.auto_increment_offset=%u%s\n",
4495 auto_increment_increment,auto_increment_offset,
4496 print_event_info->delimiter);
4497 print_event_info->auto_increment_increment= auto_increment_increment;
4498 print_event_info->auto_increment_offset= auto_increment_offset;
4499 }
4500
4501 /* TODO: print the catalog when we feature SET CATALOG */
4502
4503 if (likely(charset_inited) &&
4504 (unlikely(!print_event_info->charset_inited ||
4505 memcmp(print_event_info->charset, charset, 6))))
4506 {
4507 char *charset_p= charset; // Avoid type-punning warning.
4508 CHARSET_INFO *cs_info= get_charset(uint2korr(charset_p), MYF(MY_WME));
4509 if (cs_info)
4510 {
4511 /* for mysql client */
4512 my_b_printf(file, "/*!\\C %s */%s\n",
4513 cs_info->csname, print_event_info->delimiter);
4514 }
4515 my_b_printf(file,"SET "
4516 "@@session.character_set_client=%d,"
4517 "@@session.collation_connection=%d,"
4518 "@@session.collation_server=%d"
4519 "%s\n",
4520 uint2korr(charset_p),
4521 uint2korr(charset+2),
4522 uint2korr(charset+4),
4523 print_event_info->delimiter);
4524 memcpy(print_event_info->charset, charset, 6);
4525 print_event_info->charset_inited= 1;
4526 }
4527 if (time_zone_len)
4528 {
4529 if (memcmp(print_event_info->time_zone_str,
4530 time_zone_str, time_zone_len+1))
4531 {
4532 my_b_printf(file,"SET @@session.time_zone='%s'%s\n",
4533 time_zone_str, print_event_info->delimiter);
4534 memcpy(print_event_info->time_zone_str, time_zone_str, time_zone_len+1);
4535 }
4536 }
4537 if (lc_time_names_number != print_event_info->lc_time_names_number)
4538 {
4539 my_b_printf(file, "SET @@session.lc_time_names=%d%s\n",
4540 lc_time_names_number, print_event_info->delimiter);
4541 print_event_info->lc_time_names_number= lc_time_names_number;
4542 }
4543 if (charset_database_number != print_event_info->charset_database_number)
4544 {
4545 if (charset_database_number)
4546 my_b_printf(file, "SET @@session.collation_database=%d%s\n",
4547 charset_database_number, print_event_info->delimiter);
4548 else
4549 my_b_printf(file, "SET @@session.collation_database=DEFAULT%s\n",
4550 print_event_info->delimiter);
4551 print_event_info->charset_database_number= charset_database_number;
4552 }
4553 if (explicit_defaults_ts != TERNARY_UNSET)
4554 my_b_printf(file, "SET @@session.explicit_defaults_for_timestamp=%d%s\n",
4555 explicit_defaults_ts == TERNARY_OFF? 0 : 1,
4556 print_event_info->delimiter);
4557 }
4558
4559
print(FILE * file,PRINT_EVENT_INFO * print_event_info)4560 void Query_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
4561 {
4562 IO_CACHE *const head= &print_event_info->head_cache;
4563
4564 /**
4565 reduce the size of io cache so that the write function is called
4566 for every call to my_b_write().
4567 */
4568 DBUG_EXECUTE_IF ("simulate_file_write_error",
4569 {head->write_pos= head->write_end- 500;});
4570 print_query_header(head, print_event_info);
4571 MY_ATTRIBUTE((unused)) int write_res=
4572 my_b_write(head, (uchar*)query, q_len);
4573 assert(write_res == 0);
4574 my_b_printf(head, "\n%s\n", print_event_info->delimiter);
4575 }
4576 #endif /* MYSQL_CLIENT */
4577
4578 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
4579
4580 /**
4581 Associating slave Worker thread to a subset of temporary tables.
4582
4583 @param thd_arg THD instance pointer
4584 @param rli Relay_log_info of the worker
4585 */
attach_temp_tables_worker(THD * thd_arg,const Relay_log_info * rli)4586 void Query_log_event::attach_temp_tables_worker(THD *thd_arg,
4587 const Relay_log_info* rli)
4588 {
4589 rli->current_mts_submode->attach_temp_tables(thd_arg, rli, this);
4590 }
4591
4592 /**
4593 Dissociating slave Worker thread from its thd->temporary_tables
4594 to possibly update the involved entries of db-to-worker hash
4595 with new values of temporary_tables.
4596
4597 @param thd_arg THD instance pointer
4598 @param rli relay log info of the worker thread
4599 */
detach_temp_tables_worker(THD * thd_arg,const Relay_log_info * rli)4600 void Query_log_event::detach_temp_tables_worker(THD *thd_arg,
4601 const Relay_log_info *rli)
4602 {
4603 rli->current_mts_submode->detach_temp_tables(thd_arg, rli, this);
4604 }
4605
4606 /*
4607 Query_log_event::do_apply_event()
4608 */
do_apply_event(Relay_log_info const * rli)4609 int Query_log_event::do_apply_event(Relay_log_info const *rli)
4610 {
4611 return do_apply_event(rli, query, q_len);
4612 }
4613
4614 /*
4615 is_silent_error
4616
4617 Return true if the thread has an error which should be
4618 handled silently
4619 */
4620
is_silent_error(THD * thd)4621 static bool is_silent_error(THD* thd)
4622 {
4623 DBUG_ENTER("is_silent_error");
4624 Diagnostics_area::Sql_condition_iterator it=
4625 thd->get_stmt_da()->sql_conditions();
4626 const Sql_condition *err;
4627 while ((err= it++))
4628 {
4629 DBUG_PRINT("info", ("has condition %d %s", err->mysql_errno(),
4630 err->message_text()));
4631 switch (err->mysql_errno())
4632 {
4633 case ER_SLAVE_SILENT_RETRY_TRANSACTION:
4634 {
4635 DBUG_RETURN(true);
4636 }
4637 default:
4638 break;
4639 }
4640 }
4641 DBUG_RETURN(false);
4642 }
4643
4644 /**
4645 @todo
4646 Compare the values of "affected rows" around here. Something
4647 like:
4648 @code
4649 if ((uint32) affected_in_event != (uint32) affected_on_slave)
4650 {
4651 sql_print_error("Slave: did not get the expected number of affected \
4652 rows running query from master - expected %d, got %d (this numbers \
4653 should have matched modulo 4294967296).", 0, ...);
4654 thd->query_error = 1;
4655 }
4656 @endcode
4657 We may also want an option to tell the slave to ignore "affected"
4658 mismatch. This mismatch could be implemented with a new ER_ code, and
4659 to ignore it you would use --slave-skip-errors...
4660 */
do_apply_event(Relay_log_info const * rli,const char * query_arg,size_t q_len_arg)4661 int Query_log_event::do_apply_event(Relay_log_info const *rli,
4662 const char *query_arg, size_t q_len_arg)
4663 {
4664 DBUG_ENTER("Query_log_event::do_apply_event");
4665 int expected_error,actual_error= 0;
4666 HA_CREATE_INFO db_options;
4667
4668 DBUG_PRINT("info", ("query=%s, q_len_arg=%lu",
4669 query, static_cast<unsigned long>(q_len_arg)));
4670
4671 /*
4672 Colleagues: please never free(thd->catalog) in MySQL. This would
4673 lead to bugs as here thd->catalog is a part of an alloced block,
4674 not an entire alloced block (see
4675 Query_log_event::do_apply_event()). Same for thd->db().str. Thank
4676 you.
4677 */
4678
4679 if (catalog_len)
4680 {
4681 LEX_CSTRING catalog_lex_cstr= { catalog, catalog_len};
4682 thd->set_catalog(catalog_lex_cstr);
4683 }
4684 else
4685 thd->set_catalog(EMPTY_CSTR);
4686
4687 size_t valid_len;
4688 bool len_error;
4689 bool is_invalid_db_name= validate_string(system_charset_info, db, db_len,
4690 &valid_len, &len_error);
4691
4692 DBUG_PRINT("debug",("is_invalid_db_name= %s, valid_len=%zu, len_error=%s",
4693 is_invalid_db_name ? "true" : "false",
4694 valid_len,
4695 len_error ? "true" : "false"));
4696
4697 if (is_invalid_db_name || len_error)
4698 {
4699 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
4700 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
4701 "Invalid database name in Query event.");
4702 thd->is_slave_error= true;
4703 goto end;
4704 }
4705
4706 set_thd_db(thd, db, db_len);
4707
4708 /*
4709 Setting the character set and collation of the current database thd->db.
4710 */
4711 load_db_opt_by_name(thd, thd->db().str, &db_options);
4712 if (db_options.default_table_charset)
4713 thd->db_charset= db_options.default_table_charset;
4714 thd->variables.auto_increment_increment= auto_increment_increment;
4715 thd->variables.auto_increment_offset= auto_increment_offset;
4716 if (explicit_defaults_ts != TERNARY_UNSET)
4717 thd->variables.explicit_defaults_for_timestamp=
4718 explicit_defaults_ts == TERNARY_OFF? 0 : 1;
4719
4720 /*
4721 todo: such cleanup should not be specific to Query event and therefore
4722 is preferable at a common with other event pre-execution point
4723 */
4724 clear_all_errors(thd, const_cast<Relay_log_info*>(rli));
4725 if (strcmp("COMMIT", query) == 0 && rli->tables_to_lock != NULL)
4726 {
4727 /*
4728 Cleaning-up the last statement context:
4729 the terminal event of the current statement flagged with
4730 STMT_END_F got filtered out in ndb circular replication.
4731 */
4732 int error;
4733 char llbuff[22];
4734 if ((error= rows_event_stmt_cleanup(const_cast<Relay_log_info*>(rli), thd)))
4735 {
4736 const_cast<Relay_log_info*>(rli)->report(ERROR_LEVEL, error,
4737 "Error in cleaning up after an event preceding the commit; "
4738 "the group log file/position: %s %s",
4739 const_cast<Relay_log_info*>(rli)->get_group_master_log_name(),
4740 llstr(const_cast<Relay_log_info*>(rli)->get_group_master_log_pos(),
4741 llbuff));
4742 }
4743 /*
4744 Executing a part of rli->stmt_done() logics that does not deal
4745 with group position change. The part is redundant now but is
4746 future-change-proof addon, e.g if COMMIT handling will start checking
4747 invariants like IN_STMT flag must be off at committing the transaction.
4748 */
4749 const_cast<Relay_log_info*>(rli)->inc_event_relay_log_pos();
4750 const_cast<Relay_log_info*>(rli)->clear_flag(Relay_log_info::IN_STMT);
4751 }
4752 else
4753 {
4754 const_cast<Relay_log_info*>(rli)->slave_close_thread_tables(thd);
4755 }
4756
4757 {
4758 thd->set_time(&(common_header->when));
4759 thd->set_query(query_arg, q_len_arg);
4760 thd->set_query_for_display(query_arg, q_len_arg);
4761 thd->set_query_id(next_query_id());
4762 thd->variables.pseudo_thread_id= thread_id; // for temp tables
4763 attach_temp_tables_worker(thd, rli);
4764 DBUG_PRINT("query",("%s", thd->query().str));
4765
4766 if (ignored_error_code((expected_error= error_code)) ||
4767 !unexpected_error_code(expected_error))
4768 {
4769 if (flags2_inited)
4770 /*
4771 all bits of thd->variables.option_bits which are 1 in OPTIONS_WRITTEN_TO_BIN_LOG
4772 must take their value from flags2.
4773 */
4774 thd->variables.option_bits= flags2|(thd->variables.option_bits & ~OPTIONS_WRITTEN_TO_BIN_LOG);
4775 /*
4776 else, we are in a 3.23/4.0 binlog; we previously received a
4777 Rotate_log_event which reset thd->variables.option_bits and sql_mode etc, so
4778 nothing to do.
4779 */
4780 /*
4781 We do not replicate MODE_NO_DIR_IN_CREATE. That is, if the master is a
4782 slave which runs with SQL_MODE=MODE_NO_DIR_IN_CREATE, this should not
4783 force us to ignore the dir too. Imagine you are a ring of machines, and
4784 one has a disk problem so that you temporarily need
4785 MODE_NO_DIR_IN_CREATE on this machine; you don't want it to propagate
4786 elsewhere (you don't want all slaves to start ignoring the dirs).
4787 */
4788 if (sql_mode_inited)
4789 thd->variables.sql_mode=
4790 (sql_mode_t) ((thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE) |
4791 (sql_mode & ~(ulonglong) MODE_NO_DIR_IN_CREATE));
4792 if (charset_inited)
4793 {
4794 if (rli->cached_charset_compare(charset))
4795 {
4796 char *charset_p= charset; // Avoid type-punning warning.
4797 /* Verify that we support the charsets found in the event. */
4798 if (!(thd->variables.character_set_client=
4799 get_charset(uint2korr(charset_p), MYF(MY_WME))) ||
4800 !(thd->variables.collation_connection=
4801 get_charset(uint2korr(charset+2), MYF(MY_WME))) ||
4802 !(thd->variables.collation_server=
4803 get_charset(uint2korr(charset+4), MYF(MY_WME))))
4804 {
4805 /*
4806 We updated the thd->variables with nonsensical values (0). Let's
4807 set them to something safe (i.e. which avoids crash), and we'll
4808 stop with EE_UNKNOWN_CHARSET in compare_errors (unless set to
4809 ignore this error).
4810 */
4811 set_slave_thread_default_charset(thd, rli);
4812 goto compare_errors;
4813 }
4814 thd->update_charset(); // for the charset change to take effect
4815 /*
4816 We cannot ask for parsing a statement using a character set
4817 without state_maps (parser internal data).
4818 */
4819 if (!thd->variables.character_set_client->state_maps)
4820 {
4821 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
4822 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
4823 "character_set cannot be parsed");
4824 thd->is_slave_error= true;
4825 goto end;
4826 }
4827 /*
4828 Reset thd->query_string.cs to the newly set value.
4829 Note, there is a small flaw here. For a very short time frame
4830 if the new charset is different from the old charset and
4831 if another thread executes "SHOW PROCESSLIST" after
4832 the above thd->set_query() and before this thd->set_query(),
4833 and if the current query has some non-ASCII characters,
4834 the another thread may see some '?' marks in the PROCESSLIST
4835 result. This should be acceptable now. This is a reminder
4836 to fix this if any refactoring happens here sometime.
4837 */
4838 thd->set_query(query_arg, q_len_arg);
4839 thd->reset_query_for_display();
4840 }
4841 }
4842 if (time_zone_len)
4843 {
4844 String tmp(time_zone_str, time_zone_len, &my_charset_bin);
4845 if (!(thd->variables.time_zone= my_tz_find(thd, &tmp)))
4846 {
4847 my_error(ER_UNKNOWN_TIME_ZONE, MYF(0), tmp.c_ptr());
4848 thd->variables.time_zone= global_system_variables.time_zone;
4849 goto compare_errors;
4850 }
4851 }
4852 if (lc_time_names_number)
4853 {
4854 if (!(thd->variables.lc_time_names=
4855 my_locale_by_number(lc_time_names_number)))
4856 {
4857 my_printf_error(ER_UNKNOWN_ERROR,
4858 "Unknown locale: '%d'", MYF(0), lc_time_names_number);
4859 thd->variables.lc_time_names= &my_locale_en_US;
4860 goto compare_errors;
4861 }
4862 }
4863 else
4864 thd->variables.lc_time_names= &my_locale_en_US;
4865 if (charset_database_number)
4866 {
4867 CHARSET_INFO *cs;
4868 if (!(cs= get_charset(charset_database_number, MYF(0))))
4869 {
4870 char buf[20];
4871 int10_to_str((int) charset_database_number, buf, -10);
4872 my_error(ER_UNKNOWN_COLLATION, MYF(0), buf);
4873 goto compare_errors;
4874 }
4875 thd->variables.collation_database= cs;
4876 }
4877 else
4878 thd->variables.collation_database= thd->db_charset;
4879
4880 thd->table_map_for_update= (table_map)table_map_for_update;
4881
4882 LEX_STRING user_lex= LEX_STRING();
4883 LEX_STRING host_lex= LEX_STRING();
4884 if (user)
4885 {
4886 user_lex.str= const_cast<char*>(user);
4887 user_lex.length= strlen(user);
4888 }
4889 if (host)
4890 {
4891 host_lex.str= const_cast<char*>(host);
4892 host_lex.length= strlen(host);
4893 }
4894 thd->set_invoker(&user_lex, &host_lex);
4895 /*
4896 Flag if we need to rollback the statement transaction on
4897 slave if it by chance succeeds.
4898 If we expected a non-zero error code and get nothing and,
4899 it is a concurrency issue or ignorable issue, effects
4900 of the statement should be rolled back.
4901 */
4902 if (expected_error &&
4903 (ignored_error_code(expected_error) ||
4904 concurrency_error_code(expected_error)))
4905 {
4906 thd->variables.option_bits|= OPTION_MASTER_SQL_ERROR;
4907 }
4908 /* Execute the query (note that we bypass dispatch_command()) */
4909 Parser_state parser_state;
4910 if (!parser_state.init(thd, thd->query().str, thd->query().length))
4911 {
4912 parser_state.m_input.m_has_digest = true;
4913 assert(thd->m_digest == NULL);
4914 thd->m_digest= & thd->m_digest_state;
4915 assert(thd->m_statement_psi == NULL);
4916 thd->m_statement_psi= MYSQL_START_STATEMENT(&thd->m_statement_state,
4917 stmt_info_rpl.m_key,
4918 thd->db().str,
4919 thd->db().length,
4920 thd->charset(), NULL);
4921 THD_STAGE_INFO(thd, stage_starting);
4922
4923 if (thd->m_digest != NULL)
4924 thd->m_digest->reset(thd->m_token_array, max_digest_length);
4925
4926 mysql_parse(thd, &parser_state, true);
4927
4928 /*
4929 Transaction isolation level of pure row based replicated transactions
4930 can be optimized to ISO_READ_COMMITTED by the applier when applying
4931 the Gtid_log_event.
4932
4933 If we are applying a statement other than transaction control ones
4934 after having optimized the transactions isolation level, we must warn
4935 about the non-standard situation we have found.
4936 */
4937 if (is_sbr_logging_format() &&
4938 thd->variables.tx_isolation > ISO_READ_COMMITTED &&
4939 thd->tx_isolation == ISO_READ_COMMITTED)
4940 {
4941 String message;
4942 message.append("The isolation level for the current transaction "
4943 "was changed to READ_COMMITTED based on the "
4944 "assumption that it had only row events and was "
4945 "not mixed with statements. "
4946 "However, an unexpected statement was found in "
4947 "the middle of the transaction."
4948 "Query: '");
4949 message.append(thd->query().str);
4950 message.append("'");
4951 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
4952 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
4953 message.c_ptr());
4954 thd->is_slave_error= true;
4955 goto end;
4956 }
4957
4958 if (sqlcom_can_generate_row_events(thd->lex->sql_command) &&
4959 thd->get_row_count_func() > 0) {
4960 for (TABLE_LIST* tbl= thd->lex->query_tables; tbl;
4961 tbl= tbl->next_global) {
4962 if (!tbl->is_placeholder() && tbl->table->file) {
4963 if (!tbl->table->file->rpl_can_handle_stm_event()) {
4964 String message;
4965 message.append("Masters binlog format is not ROW and storage "
4966 "engine can not handle non-ROW events at this "
4967 "time. Table: '");
4968 message.append(tbl->get_db_name());
4969 message.append(".");
4970 message.append(tbl->get_table_name());
4971 message.append("' Query: '");
4972 message.append(thd->query().str);
4973 message.append("'");
4974 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
4975 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
4976 message.c_ptr());
4977 thd->is_slave_error= true;
4978 goto end;
4979 }
4980 }
4981 }
4982 }
4983
4984 /* Finalize server status flags after executing a statement. */
4985 thd->update_server_status();
4986 log_slow_statement(thd);
4987 }
4988
4989 thd->variables.option_bits&= ~OPTION_MASTER_SQL_ERROR;
4990
4991 /*
4992 Resetting the enable_slow_log thd variable.
4993
4994 We need to reset it back to the opt_log_slow_slave_statements
4995 value after the statement execution (and slow logging
4996 is done). It might have changed if the statement was an
4997 admin statement (in which case, down in mysql_parse execution
4998 thd->enable_slow_log is set to the value of
4999 opt_log_slow_admin_statements).
5000 */
5001 thd->enable_slow_log= opt_log_slow_slave_statements;
5002 }
5003 else
5004 {
5005 /*
5006 The query got a really bad error on the master (thread killed etc),
5007 which could be inconsistent. Parse it to test the table names: if the
5008 replicate-*-do|ignore-table rules say "this query must be ignored" then
5009 we exit gracefully; otherwise we warn about the bad error and tell DBA
5010 to check/fix it.
5011 */
5012 if (mysql_test_parse_for_slave(thd))
5013 clear_all_errors(thd, const_cast<Relay_log_info*>(rli)); /* Can ignore query */
5014 else
5015 {
5016 rli->report(ERROR_LEVEL, ER_ERROR_ON_MASTER, ER(ER_ERROR_ON_MASTER),
5017 expected_error, thd->query().str);
5018 thd->is_slave_error= 1;
5019 }
5020 goto end;
5021 }
5022
5023 /* If the query was not ignored, it is printed to the general log */
5024 if (!thd->is_error() ||
5025 thd->get_stmt_da()->mysql_errno() != ER_SLAVE_IGNORED_TABLE)
5026 {
5027 /*
5028 Log the rewritten query if the query was rewritten
5029 and the option to log raw was not set.
5030
5031 There is an assumption here. We assume that query log
5032 events can never have multi-statement queries, thus the
5033 parsed statement is the same as the raw one.
5034 */
5035 if (opt_general_log_raw || thd->rewritten_query().length() == 0)
5036 query_logger.general_log_write(thd, COM_QUERY, thd->query().str,
5037 thd->query().length);
5038 else
5039 query_logger.general_log_write(thd, COM_QUERY,
5040 thd->rewritten_query().ptr(),
5041 thd->rewritten_query().length());
5042 }
5043
5044 compare_errors:
5045 /* Parser errors shall be ignored when (GTID) skipping statements */
5046 if (thd->is_error() &&
5047 thd->get_stmt_da()->mysql_errno() == ER_PARSE_ERROR &&
5048 gtid_pre_statement_checks(thd) == GTID_STATEMENT_SKIP)
5049 {
5050 thd->get_stmt_da()->reset_diagnostics_area();
5051 }
5052 /*
5053 In the slave thread, we may sometimes execute some DROP / * 40005
5054 TEMPORARY * / TABLE that come from parts of binlogs (likely if we
5055 use RESET SLAVE or CHANGE MASTER TO), while the temporary table
5056 has already been dropped. To ignore such irrelevant "table does
5057 not exist errors", we silently clear the error if TEMPORARY was used.
5058 */
5059 if (thd->lex->sql_command == SQLCOM_DROP_TABLE &&
5060 thd->lex->drop_temporary &&
5061 thd->is_error() &&
5062 thd->get_stmt_da()->mysql_errno() == ER_BAD_TABLE_ERROR &&
5063 !expected_error)
5064 thd->get_stmt_da()->reset_diagnostics_area();
5065 /*
5066 If we expected a non-zero error code, and we don't get the same error
5067 code, and it should be ignored or is related to a concurrency issue.
5068 */
5069 actual_error= thd->is_error() ? thd->get_stmt_da()->mysql_errno() : 0;
5070 DBUG_PRINT("info",("expected_error: %d sql_errno: %d",
5071 expected_error, actual_error));
5072
5073 /*
5074 If a statement with expected error is received on slave and if the
5075 statement is not filtered on the slave, only then compare the expected
5076 error with the actual error that happened on slave.
5077 */
5078 if ((expected_error && rpl_filter->db_ok(thd->db().str) &&
5079 expected_error != actual_error &&
5080 !concurrency_error_code(expected_error)) &&
5081 !ignored_error_code(actual_error) &&
5082 !ignored_error_code(expected_error))
5083 {
5084 if (!ignored_error_code(ER_INCONSISTENT_ERROR))
5085 {
5086 rli->report(ERROR_LEVEL, ER_INCONSISTENT_ERROR,
5087 ER(ER_INCONSISTENT_ERROR),
5088 ER_THD(thd, expected_error), expected_error,
5089 (actual_error ?
5090 thd->get_stmt_da()->message_text() :
5091 "no error"),
5092 actual_error, print_slave_db_safe(db), query_arg);
5093 thd->is_slave_error= 1;
5094 }
5095 else
5096 {
5097 rli->report(INFORMATION_LEVEL, actual_error,
5098 "The actual error and expected error on slave are"
5099 " different that will result in ER_INCONSISTENT_ERROR but"
5100 " that is passed as an argument to slave_skip_errors so no"
5101 " error is thrown. "
5102 "The expected error was %s with, Error_code: %d. "
5103 "The actual error is %s with ",
5104 ER(expected_error), expected_error,
5105 thd->get_stmt_da()->message_text());
5106 clear_all_errors(thd, const_cast<Relay_log_info*>(rli));
5107 }
5108 }
5109 /*
5110 If we get the same error code as expected and it is not a concurrency
5111 issue, or should be ignored.
5112 */
5113 else if ((expected_error == actual_error &&
5114 !concurrency_error_code(expected_error)) ||
5115 ignored_error_code(actual_error))
5116 {
5117 DBUG_PRINT("info",("error ignored"));
5118 if (actual_error && ignored_error_code(actual_error))
5119 {
5120 if (actual_error == ER_SLAVE_IGNORED_TABLE)
5121 {
5122 if (!slave_ignored_err_throttle.log())
5123 rli->report(INFORMATION_LEVEL, actual_error,
5124 "Could not execute %s event. Detailed error: %s;"
5125 " Error log throttle is enabled. This error will not be"
5126 " displayed for next %lu secs. It will be suppressed",
5127 get_type_str(), thd->get_stmt_da()->message_text(),
5128 (window_size / 1000000));
5129 }
5130 else
5131 rli->report(INFORMATION_LEVEL, actual_error,
5132 "Could not execute %s event. Detailed error: %s;",
5133 get_type_str(), thd->get_stmt_da()->message_text());
5134 }
5135 clear_all_errors(thd, const_cast<Relay_log_info*>(rli));
5136 thd->killed= THD::NOT_KILLED;
5137 }
5138 /*
5139 Other cases: mostly we expected no error and get one.
5140 */
5141 else if (thd->is_slave_error || thd->is_fatal_error)
5142 {
5143 if (!is_silent_error(thd))
5144 {
5145 rli->report(ERROR_LEVEL, actual_error,
5146 "Error '%s' on query. Default database: '%s'. Query: '%s'",
5147 (actual_error ?
5148 thd->get_stmt_da()->message_text() :
5149 "unexpected success or fatal error"),
5150 print_slave_db_safe(thd->db().str), query_arg);
5151 }
5152 thd->is_slave_error= 1;
5153 }
5154
5155 /*
5156 TODO: compare the values of "affected rows" around here. Something
5157 like:
5158 if ((uint32) affected_in_event != (uint32) affected_on_slave)
5159 {
5160 sql_print_error("Slave: did not get the expected number of affected \
5161 rows running query from master - expected %d, got %d (this numbers \
5162 should have matched modulo 4294967296).", 0, ...);
5163 thd->is_slave_error = 1;
5164 }
5165 We may also want an option to tell the slave to ignore "affected"
5166 mismatch. This mismatch could be implemented with a new ER_ code, and
5167 to ignore it you would use --slave-skip-errors...
5168
5169 To do the comparison we need to know the value of "affected" which the
5170 above mysql_parse() computed. And we need to know the value of
5171 "affected" in the master's binlog. Both will be implemented later. The
5172 important thing is that we now have the format ready to log the values
5173 of "affected" in the binlog. So we can release 5.0.0 before effectively
5174 logging "affected" and effectively comparing it.
5175 */
5176 } /* End of if (db_ok(... */
5177
5178 {
5179 /**
5180 The following failure injecion works in cooperation with tests
5181 setting @@global.debug= 'd,stop_slave_middle_group'.
5182 The sql thread receives the killed status and will proceed
5183 to shutdown trying to finish incomplete events group.
5184 */
5185
5186 // TODO: address the middle-group killing in MTS case
5187
5188 DBUG_EXECUTE_IF("stop_slave_middle_group",
5189 if (strcmp("COMMIT", query) != 0 &&
5190 strcmp("BEGIN", query) != 0)
5191 {
5192 if (thd->get_transaction()->cannot_safely_rollback(
5193 Transaction_ctx::SESSION))
5194 const_cast<Relay_log_info*>(rli)->abort_slave= 1;
5195 };);
5196 }
5197
5198 end:
5199
5200 if (thd->temporary_tables)
5201 detach_temp_tables_worker(thd, rli);
5202 /*
5203 Probably we have set thd->query, thd->db, thd->catalog to point to places
5204 in the data_buf of this event. Now the event is going to be deleted
5205 probably, so data_buf will be freed, so the thd->... listed above will be
5206 pointers to freed memory.
5207 So we must set them to 0, so that those bad pointers values are not later
5208 used. Note that "cleanup" queries like automatic DROP TEMPORARY TABLE
5209 don't suffer from these assignments to 0 as DROP TEMPORARY
5210 TABLE uses the db.table syntax.
5211 */
5212 thd->set_catalog(NULL_CSTR);
5213 thd->set_db(NULL_CSTR); /* will free the current database */
5214 thd->reset_query();
5215 thd->lex->sql_command= SQLCOM_END;
5216 DBUG_PRINT("info", ("end: query= 0"));
5217
5218 /* Mark the statement completed. */
5219 MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da());
5220 thd->reset_rewritten_query();
5221 thd->m_statement_psi= NULL;
5222 thd->m_digest= NULL;
5223
5224 /*
5225 Prevent rewritten query from getting "stuck" in SHOW PROCESSLIST,
5226 and performance_schema.threads.
5227 */
5228 thd->reset_rewritten_query();
5229 thd->reset_query_for_display();
5230
5231 /*
5232 As a disk space optimization, future masters will not log an event for
5233 LAST_INSERT_ID() if that function returned 0 (and thus they will be able
5234 to replace the THD::stmt_depends_on_first_successful_insert_id_in_prev_stmt
5235 variable by (THD->first_successful_insert_id_in_prev_stmt > 0) ; with the
5236 resetting below we are ready to support that.
5237 */
5238 thd->first_successful_insert_id_in_prev_stmt_for_binlog= 0;
5239 thd->first_successful_insert_id_in_prev_stmt= 0;
5240 thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
5241 free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
5242 DBUG_RETURN(thd->is_slave_error);
5243 }
5244
do_update_pos(Relay_log_info * rli)5245 int Query_log_event::do_update_pos(Relay_log_info *rli)
5246 {
5247 int ret= Log_event::do_update_pos(rli);
5248
5249 DBUG_EXECUTE_IF("crash_after_commit_and_update_pos",
5250 if (!strcmp("COMMIT", query))
5251 {
5252 sql_print_information("Crashing crash_after_commit_and_update_pos.");
5253 rli->flush_info(true);
5254 ha_flush_logs(0);
5255 DBUG_SUICIDE();
5256 }
5257 );
5258
5259 return ret;
5260 }
5261
5262
5263 Log_event::enum_skip_reason
do_shall_skip(Relay_log_info * rli)5264 Query_log_event::do_shall_skip(Relay_log_info *rli)
5265 {
5266 DBUG_ENTER("Query_log_event::do_shall_skip");
5267 DBUG_PRINT("debug", ("query: %s; q_len: %d", query, static_cast<int>(q_len)));
5268 assert(query && q_len > 0);
5269
5270 if (rli->slave_skip_counter > 0)
5271 {
5272 if (strcmp("BEGIN", query) == 0)
5273 {
5274 thd->variables.option_bits|= OPTION_BEGIN;
5275 DBUG_RETURN(Log_event::continue_group(rli));
5276 }
5277
5278 if (strcmp("COMMIT", query) == 0 || strcmp("ROLLBACK", query) == 0)
5279 {
5280 thd->variables.option_bits&= ~OPTION_BEGIN;
5281 DBUG_RETURN(Log_event::EVENT_SKIP_COUNT);
5282 }
5283 }
5284 Log_event::enum_skip_reason ret= Log_event::do_shall_skip(rli);
5285 DBUG_RETURN(ret);
5286 }
5287
5288 #endif
5289
5290 /**
5291 Return the query string pointer (and its size) from a Query log event
5292 using only the event buffer (we don't instantiate a Query_log_event
5293 object for this).
5294
5295 @param buf Pointer to the event buffer.
5296 @param length The size of the event buffer.
5297 @param description_event The description event of the master which logged
5298 the event.
5299 @param[out] query The pointer to receive the query pointer.
5300
5301 @return The size of the query.
5302 */
get_query(const char * buf,size_t length,const Format_description_log_event * fd_event,char ** query)5303 size_t Query_log_event::get_query(const char *buf, size_t length,
5304 const Format_description_log_event *fd_event,
5305 char** query)
5306 {
5307 assert((Log_event_type)buf[EVENT_TYPE_OFFSET] ==
5308 binary_log::QUERY_EVENT);
5309
5310 char db_len; /* size of db name */
5311 uint status_vars_len= 0; /* size of status_vars */
5312 size_t qlen; /* size of the query */
5313 int checksum_size= 0; /* size of trailing checksum */
5314 const char *end_of_query;
5315
5316 uint common_header_len= fd_event->common_header_len;
5317 uint query_header_len= fd_event->post_header_len[binary_log::QUERY_EVENT-1];
5318
5319 /* Error if the event content is too small */
5320 if (length < (common_header_len + query_header_len))
5321 goto err;
5322
5323 /* Skip the header */
5324 buf+= common_header_len;
5325
5326 /* Check if there are status variables in the event */
5327 if ((query_header_len - QUERY_HEADER_MINIMAL_LEN) > 0)
5328 {
5329 status_vars_len= uint2korr(buf + Q_STATUS_VARS_LEN_OFFSET);
5330 }
5331
5332 /* Check if the event has trailing checksum */
5333 if (fd_event->common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_OFF)
5334 checksum_size= 4;
5335
5336 db_len= (uchar)buf[Q_DB_LEN_OFFSET];
5337
5338 /* Error if the event content is too small */
5339 if (length < (common_header_len + query_header_len +
5340 db_len + 1 + status_vars_len + checksum_size))
5341 goto err;
5342
5343 *query= (char *)buf + query_header_len + db_len + 1 + status_vars_len;
5344
5345 /* Calculate the query length */
5346 end_of_query= buf + (length - common_header_len) - /* we skipped the header */
5347 checksum_size;
5348 qlen= end_of_query - *query;
5349 return qlen;
5350
5351 err:
5352 *query= NULL;
5353 return 0;
5354 }
5355
5356
5357 /**************************************************************************
5358 Start_log_event_v3 methods
5359 **************************************************************************/
5360 #ifndef MYSQL_CLIENT
Start_log_event_v3()5361 Start_log_event_v3::Start_log_event_v3()
5362 : binary_log::Start_event_v3(),
5363 Log_event(header(), footer(), Log_event::EVENT_INVALID_CACHE,
5364 Log_event::EVENT_INVALID_LOGGING)
5365 {
5366 is_valid_param= true;
5367 }
5368 #endif
5369
5370 /*
5371 Start_log_event_v3::pack_info()
5372 */
5373
5374 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
pack_info(Protocol * protocol)5375 int Start_log_event_v3::pack_info(Protocol *protocol)
5376 {
5377 char buf[12 + ST_SERVER_VER_LEN + 14 + 22], *pos;
5378 pos= my_stpcpy(buf, "Server ver: ");
5379 pos= my_stpcpy(pos, server_version);
5380 pos= my_stpcpy(pos, ", Binlog ver: ");
5381 pos= int10_to_str(binlog_version, pos, 10);
5382 protocol->store(buf, (uint) (pos-buf), &my_charset_bin);
5383 return 0;
5384 }
5385 #endif
5386
5387
5388 /*
5389 Start_log_event_v3::print()
5390 */
5391
5392 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)5393 void Start_log_event_v3::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
5394 {
5395 DBUG_ENTER("Start_log_event_v3::print");
5396
5397 IO_CACHE *const head= &print_event_info->head_cache;
5398
5399 if (!print_event_info->short_form)
5400 {
5401 print_header(head, print_event_info, FALSE);
5402 my_b_printf(head, "\tStart: binlog v %d, server v %s created ",
5403 binlog_version, server_version);
5404 print_timestamp(head, NULL);
5405 if (created)
5406 my_b_printf(head," at startup");
5407 my_b_printf(head, "\n");
5408 if (common_header->flags & LOG_EVENT_BINLOG_IN_USE_F)
5409 my_b_printf(head, "# Warning: this binlog is either in use or was not "
5410 "closed properly.\n");
5411 }
5412
5413 if (is_relay_log_event())
5414 {
5415 my_b_printf(head, "# This Format_description_event appears in a relay log "
5416 "and was generated by the slave thread.\n");
5417 DBUG_VOID_RETURN;
5418 }
5419
5420 if (!is_artificial_event() && created)
5421 {
5422 #ifdef WHEN_WE_HAVE_THE_RESET_CONNECTION_SQL_COMMAND
5423 /*
5424 This is for mysqlbinlog: like in replication, we want to delete the stale
5425 tmp files left by an unclean shutdown of mysqld (temporary tables)
5426 and rollback unfinished transaction.
5427 Probably this can be done with RESET CONNECTION (syntax to be defined).
5428 */
5429 my_b_printf(head,"RESET CONNECTION%s\n", print_event_info->delimiter);
5430 #else
5431 my_b_printf(head,"ROLLBACK%s\n", print_event_info->delimiter);
5432 #endif
5433 }
5434 if (temp_buf &&
5435 print_event_info->base64_output_mode != BASE64_OUTPUT_NEVER &&
5436 !print_event_info->short_form)
5437 {
5438 if (print_event_info->base64_output_mode != BASE64_OUTPUT_DECODE_ROWS)
5439 my_b_printf(head, "BINLOG '\n");
5440 print_base64(head, print_event_info, FALSE);
5441 print_event_info->printed_fd_event= TRUE;
5442
5443 /*
5444 If --skip-gtids is given, the server when it replays the output
5445 should generate a new GTID if gtid_mode=ON. However, when the
5446 server reads the base64-encoded Format_description_log_event, it
5447 will cleverly detect that this is a binlog to be replayed, and
5448 act a little bit like the replication thread, in the following
5449 sense: if the thread does not see any 'SET GTID_NEXT' statement,
5450 it will assume the binlog was created by an old server and try
5451 to preserve transactions as anonymous. This is the opposite of
5452 what we want when passing the --skip-gtids flag, so therefore we
5453 output the following statement.
5454
5455 The behavior where the client preserves transactions following a
5456 Format_description_log_event as anonymous was introduced in
5457 5.6.16.
5458 */
5459 if (print_event_info->skip_gtids)
5460 my_b_printf(head, "/*!50616 SET @@SESSION.GTID_NEXT='AUTOMATIC'*/%s\n",
5461 print_event_info->delimiter);
5462 }
5463 DBUG_VOID_RETURN;
5464 }
5465 #endif /* MYSQL_CLIENT */
5466
5467 /*
5468 Start_log_event_v3::Start_log_event_v3()
5469 */
5470
Start_log_event_v3(const char * buf,uint event_len,const Format_description_event * description_event)5471 Start_log_event_v3::Start_log_event_v3(const char* buf, uint event_len,
5472 const Format_description_event
5473 *description_event)
5474 : binary_log::Start_event_v3(buf, event_len, description_event),
5475 Log_event(header(), footer())
5476 {
5477 is_valid_param= server_version[0] != 0;
5478 if (event_len < (uint)description_event->common_header_len +
5479 ST_COMMON_HEADER_LEN_OFFSET)
5480 {
5481 server_version[0]= 0;
5482 return;
5483 }
5484 buf+= description_event->common_header_len;
5485 binlog_version= uint2korr(buf+ST_BINLOG_VER_OFFSET);
5486 memcpy(server_version, buf+ST_SERVER_VER_OFFSET,
5487 ST_SERVER_VER_LEN);
5488 // prevent overrun if log is corrupted on disk
5489 server_version[ST_SERVER_VER_LEN-1]= 0;
5490 created= uint4korr(buf+ST_CREATED_OFFSET);
5491 dont_set_created= 1;
5492 }
5493
5494
5495 /*
5496 Start_log_event_v3::write()
5497 */
5498
5499 #ifndef MYSQL_CLIENT
write(IO_CACHE * file)5500 bool Start_log_event_v3::write(IO_CACHE* file)
5501 {
5502 char buff[Binary_log_event::START_V3_HEADER_LEN];
5503 int2store(buff + ST_BINLOG_VER_OFFSET,binlog_version);
5504 memcpy(buff + ST_SERVER_VER_OFFSET,server_version,ST_SERVER_VER_LEN);
5505 if (!dont_set_created)
5506 created= get_time();
5507 int4store(buff + ST_CREATED_OFFSET, static_cast<uint32>(created));
5508 return (write_header(file, sizeof(buff)) ||
5509 wrapper_my_b_safe_write(file, (uchar*) buff, sizeof(buff)) ||
5510 write_footer(file));
5511 }
5512 #endif
5513
5514
5515 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
5516
5517 /**
5518 Start_log_event_v3::do_apply_event() .
5519 The master started
5520
5521 IMPLEMENTATION
5522 - To handle the case where the master died without having time to write
5523 DROP TEMPORARY TABLE, DO RELEASE_LOCK (prepared statements' deletion is
5524 TODO), we clean up all temporary tables that we got, if we are sure we
5525 can (see below).
5526
5527 @todo
5528 - Remove all active user locks.
5529 Guilhem 2003-06: this is true but not urgent: the worst it can cause is
5530 the use of a bit of memory for a user lock which will not be used
5531 anymore. If the user lock is later used, the old one will be released. In
5532 other words, no deadlock problem.
5533 */
5534
do_apply_event(Relay_log_info const * rli)5535 int Start_log_event_v3::do_apply_event(Relay_log_info const *rli)
5536 {
5537 DBUG_ENTER("Start_log_event_v3::do_apply_event");
5538 int error= 0;
5539 switch (binlog_version)
5540 {
5541 case 3:
5542 case 4:
5543 /*
5544 This can either be 4.x (then a Start_log_event_v3 is only at master
5545 startup so we are sure the master has restarted and cleared his temp
5546 tables; the event always has 'created'>0) or 5.0 (then we have to test
5547 'created').
5548 */
5549 if (created)
5550 {
5551 error= close_temporary_tables(thd);
5552 cleanup_load_tmpdir();
5553 }
5554 else
5555 {
5556 /*
5557 Set all temporary tables thread references to the current thread
5558 as they may point to the "old" SQL slave thread in case of its
5559 restart.
5560 */
5561 TABLE *table;
5562 for (table= thd->temporary_tables; table; table= table->next)
5563 table->in_use= thd;
5564 }
5565 break;
5566
5567 /*
5568 Now the older formats; in that case load_tmpdir is cleaned up by the I/O
5569 thread.
5570 */
5571 case 1:
5572 if (strncmp(rli->get_rli_description_event()->server_version,
5573 "3.23.57",7) >= 0 && created)
5574 {
5575 /*
5576 Can distinguish, based on the value of 'created': this event was
5577 generated at master startup.
5578 */
5579 error= close_temporary_tables(thd);
5580 }
5581 /*
5582 Otherwise, can't distinguish a Start_log_event generated at
5583 master startup and one generated by master FLUSH LOGS, so cannot
5584 be sure temp tables have to be dropped. So do nothing.
5585 */
5586 break;
5587 default:
5588 /*
5589 This case is not expected. It can be either an event corruption or an
5590 unsupported binary log version.
5591 */
5592 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
5593 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
5594 "Binlog version not supported");
5595 DBUG_RETURN(1);
5596 }
5597 DBUG_RETURN(error);
5598 }
5599 #endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
5600
Start_encryption_log_event(const char * buf,uint event_len,const Format_description_log_event * description_event)5601 Start_encryption_log_event::Start_encryption_log_event(
5602 const char* buf, uint event_len,
5603 const Format_description_log_event* description_event)
5604 : Binary_log_event(&buf, description_event->binlog_version,
5605 description_event->server_version),
5606 Log_event(header(), footer())
5607 {
5608 if ((int)event_len ==
5609 (int)LOG_EVENT_MINIMAL_HEADER_LEN + (int)Start_encryption_log_event::get_data_size())
5610 {
5611 crypto_scheme = *(uchar*)buf;
5612 key_version = uint4korr(buf + Binlog_crypt_data::BINLOG_CRYPTO_SCHEME_LENGTH);
5613 memcpy(nonce,
5614 buf + Binlog_crypt_data::BINLOG_CRYPTO_SCHEME_LENGTH + Binlog_crypt_data::BINLOG_KEY_VERSION_LENGTH,
5615 Binlog_crypt_data::BINLOG_NONCE_LENGTH);
5616 }
5617 else
5618 crypto_scheme= ~0; // invalid
5619
5620 is_valid_param= crypto_scheme == 1;
5621 }
5622
5623 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
do_apply_event(Relay_log_info const * rli)5624 int Start_encryption_log_event::do_apply_event(Relay_log_info const *rli)
5625 {
5626 return rli->get_rli_description_event()->start_decryption(this);
5627 }
5628
do_update_pos(Relay_log_info * rli)5629 int Start_encryption_log_event::do_update_pos(Relay_log_info *rli)
5630 {
5631 /*
5632 Master never sends Start_encryption_log_event, any SELE that a slave
5633 might see was created locally in MYSQL_BIN_LOG::open() on the slave
5634 */
5635 rli->inc_event_relay_log_pos();
5636 return 0;
5637 }
5638
5639 #endif
5640
5641 #ifndef MYSQL_SERVER
print(FILE * file,PRINT_EVENT_INFO * print_event_info)5642 void Start_encryption_log_event::print(FILE* file,
5643 PRINT_EVENT_INFO* print_event_info)
5644 {
5645 // Need 2 characters per one hex + 2 for 0x + 1 for \0
5646 char nonce_buf[Binlog_crypt_data::BINLOG_NONCE_LENGTH * 2 + 2 + 1];
5647 str_to_hex(nonce_buf, reinterpret_cast<char*>(nonce),
5648 Binlog_crypt_data::BINLOG_NONCE_LENGTH);
5649
5650 IO_CACHE *const head= &print_event_info->head_cache;
5651 print_header(head, print_event_info, FALSE);
5652 my_b_printf(head,"Encryption scheme: %d", crypto_scheme);
5653 my_b_printf(head,", key_version: %d", key_version);
5654 my_b_printf(head,", nonce: %s ", nonce_buf);
5655 my_b_printf(head,"\n# The rest of the binlog is encrypted!\n");
5656 }
5657 #endif
5658
5659
5660
5661 /***************************************************************************
5662 Format_description_log_event methods
5663 ****************************************************************************/
5664
5665 /**
5666 Format_description_log_event 1st ctor.
5667
5668 Ctor. Can be used to create the event to write to the binary log (when the
5669 server starts or when FLUSH LOGS), or to create artificial events to parse
5670 binlogs from MySQL 3.23 or 4.x.
5671 When in a client, only the 2nd use is possible.
5672
5673 @param binlog_version the binlog version for which we want to build
5674 an event. Can be 1 (=MySQL 3.23), 3 (=4.0.x
5675 x>=2 and 4.1) or 4 (MySQL 5.0). Note that the
5676 old 4.0 (binlog version 2) is not supported;
5677 it should not be used for replication with
5678 5.0.
5679 @param server_ver a string containing the server version.
5680 */
5681
5682 Format_description_log_event::
Format_description_log_event(uint8_t binlog_ver,const char * server_ver)5683 Format_description_log_event(uint8_t binlog_ver, const char* server_ver)
5684 : binary_log::Start_event_v3(binary_log::FORMAT_DESCRIPTION_EVENT),
5685 Format_description_event(binlog_ver, (binlog_ver <= 3 || server_ver != 0) ?
5686 server_ver : ::server_version)
5687 {
5688 is_valid_param= header_is_valid() && version_is_valid();
5689 common_header->type_code= binary_log::FORMAT_DESCRIPTION_EVENT;
5690 /*
5691 We here have the possibility to simulate a master before we changed
5692 the table map id to be stored in 6 bytes: when it was stored in 4
5693 bytes (=> post_header_len was 6). This is used to test backward
5694 compatibility.
5695 This code can be removed after a few months (today is Dec 21st 2005),
5696 when we know that the 4-byte masters are not deployed anymore (check
5697 with Tomas Ulin first!), and the accompanying test (rpl_row_4_bytes)
5698 too.
5699 */
5700 DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master",
5701 post_header_len[binary_log::TABLE_MAP_EVENT-1]=
5702 post_header_len[binary_log::WRITE_ROWS_EVENT_V1-1]=
5703 post_header_len[binary_log::UPDATE_ROWS_EVENT_V1-1]=
5704 post_header_len[binary_log::DELETE_ROWS_EVENT_V1-1]= 6;);
5705 reset_crypto();
5706 }
5707
5708
5709 /**
5710 The problem with this constructor is that the fixed header may have a
5711 length different from this version, but we don't know this length as we
5712 have not read the Format_description_log_event which says it, yet. This
5713 length is in the post-header of the event, but we don't know where the
5714 post-header starts.
5715
5716 So this type of event HAS to:
5717 - either have the header's length at the beginning (in the header, at a
5718 fixed position which will never be changed), not in the post-header. That
5719 would make the header be "shifted" compared to other events.
5720 - or have a header of size LOG_EVENT_MINIMAL_HEADER_LEN (19), in all future
5721 versions, so that we know for sure.
5722
5723 I (Guilhem) chose the 2nd solution. Rotate has the same constraint (because
5724 it is sent before Format_description_log_event).
5725 */
5726
5727 Format_description_log_event::
Format_description_log_event(const char * buf,uint event_len,const Format_description_event * description_event)5728 Format_description_log_event(const char* buf, uint event_len,
5729 const Format_description_event
5730 *description_event)
5731 : binary_log::Start_event_v3(buf, event_len, description_event),
5732 Format_description_event(buf, event_len, description_event),
5733 Start_log_event_v3(buf, event_len, description_event)
5734 {
5735 is_valid_param= header_is_valid() && version_is_valid();
5736 common_header->type_code= binary_log::FORMAT_DESCRIPTION_EVENT;
5737
5738 /*
5739 We here have the possibility to simulate a master of before we changed
5740 the table map id to be stored in 6 bytes: when it was stored in 4
5741 bytes (=> post_header_len was 6). This is used to test backward
5742 compatibility.
5743 */
5744 DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master",
5745 post_header_len[binary_log::TABLE_MAP_EVENT-1]=
5746 post_header_len[binary_log::WRITE_ROWS_EVENT_V1-1]=
5747 post_header_len[binary_log::UPDATE_ROWS_EVENT_V1-1]=
5748 post_header_len[binary_log::DELETE_ROWS_EVENT_V1-1]= 6;);
5749 reset_crypto();
5750 }
5751
start_decryption(Start_encryption_log_event * sele)5752 bool Format_description_log_event::start_decryption(Start_encryption_log_event* sele)
5753 {
5754 assert(!crypto_data.is_enabled());
5755
5756 if (!sele->is_valid())
5757 return true;
5758 if (crypto_data.init(sele->crypto_scheme, sele->key_version, sele->nonce))
5759 {
5760 sql_print_error("Failed to fetch percona_binlog key (version %u) from keyring and thus "
5761 "failed to initialize binlog encryption.", sele->key_version);
5762 return true;
5763 }
5764 return false;
5765 }
5766
5767 #ifndef MYSQL_CLIENT
write(IO_CACHE * file)5768 bool Format_description_log_event::write(IO_CACHE* file)
5769 {
5770 bool ret;
5771 bool no_checksum;
5772 /*
5773 We don't call Start_log_event_v3::write() because this would make 2
5774 my_b_safe_write().
5775 */
5776 uchar buff[Binary_log_event::FORMAT_DESCRIPTION_HEADER_LEN +
5777 BINLOG_CHECKSUM_ALG_DESC_LEN];
5778 size_t rec_size= sizeof(buff);
5779 int2store(buff + ST_BINLOG_VER_OFFSET,binlog_version);
5780 memcpy((char*) buff + ST_SERVER_VER_OFFSET,server_version,ST_SERVER_VER_LEN);
5781 if (!dont_set_created)
5782 created= get_time();
5783 int4store(buff + ST_CREATED_OFFSET, static_cast<uint32>(created));
5784 buff[ST_COMMON_HEADER_LEN_OFFSET]= LOG_EVENT_HEADER_LEN;
5785
5786 size_t number_of_events;
5787 int post_header_len_size = static_cast<int>(post_header_len.size());
5788
5789 if (post_header_len_size == Binary_log_event::LOG_EVENT_TYPES)
5790 // Replicating between master and slave with same version.
5791 // number_of_events will be same as Binary_log_event::LOG_EVENT_TYPES
5792 number_of_events = Binary_log_event::LOG_EVENT_TYPES;
5793 else if (post_header_len_size > Binary_log_event::LOG_EVENT_TYPES)
5794 /*
5795 Replicating between new master and old slave.
5796 In that case there won't be any memory issues, as there won't be
5797 any out of memory read.
5798 */
5799 number_of_events = Binary_log_event::LOG_EVENT_TYPES;
5800 else
5801 /*
5802 Replicating between old master and new slave.
5803 In that case it might lead to different number_of_events on master and
5804 slave. When the relay log is rotated, the FDE from master is used to
5805 create the FDE event on slave, which is being written here. In that case
5806 we might end up reading more bytes as
5807 post_header_len.size() < Binary_log_event::LOG_EVENT_TYPES;
5808 casuing memory issues.
5809 */
5810 number_of_events = post_header_len_size;
5811
5812 memcpy((char*) buff + ST_COMMON_HEADER_LEN_OFFSET + 1, &post_header_len.front(),
5813 number_of_events);
5814 /*
5815 if checksum is requested
5816 record the checksum-algorithm descriptor next to
5817 post_header_len vector which will be followed by the checksum value.
5818 Master is supposed to trigger checksum computing by binlog_checksum_options,
5819 slave does it via marking the event according to
5820 FD_queue checksum_alg value.
5821 */
5822 compile_time_assert(sizeof(BINLOG_CHECKSUM_ALG_DESC_LEN == 1));
5823 #ifndef NDEBUG
5824 common_header->data_written= 0; // to prepare for need_checksum assert
5825 #endif
5826 buff[Binary_log_event::FORMAT_DESCRIPTION_HEADER_LEN]= need_checksum() ?
5827 (uint8) common_footer->checksum_alg :
5828 (uint8) binary_log::BINLOG_CHECKSUM_ALG_OFF;
5829 /*
5830 FD of checksum-aware server is always checksum-equipped, (V) is in,
5831 regardless of @@global.binlog_checksum policy.
5832 Thereby a combination of (A) == 0, (V) != 0 means
5833 it's the checksum-aware server's FD event that heads checksum-free binlog
5834 file.
5835 Here 0 stands for checksumming OFF to evaluate (V) as 0 is that case.
5836 A combination of (A) != 0, (V) != 0 denotes FD of the checksum-aware server
5837 heading the checksummed binlog.
5838 (A), (V) presence in FD of the checksum-aware server makes the event
5839 1 + 4 bytes bigger comparing to the former FD.
5840 */
5841
5842 if ((no_checksum= (common_footer->checksum_alg ==
5843 binary_log::BINLOG_CHECKSUM_ALG_OFF)))
5844 {
5845 // Forcing (V) room to fill anyway
5846 common_footer->checksum_alg= binary_log::BINLOG_CHECKSUM_ALG_CRC32;
5847 }
5848 ret= (write_header(file, rec_size) ||
5849 wrapper_my_b_safe_write(file, buff, rec_size) ||
5850 write_footer(file));
5851 if (no_checksum)
5852 common_footer->checksum_alg= binary_log::BINLOG_CHECKSUM_ALG_OFF;
5853 return ret;
5854 }
5855 #endif
5856
5857 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
do_apply_event(Relay_log_info const * rli)5858 int Format_description_log_event::do_apply_event(Relay_log_info const *rli)
5859 {
5860 int ret= 0;
5861 DBUG_ENTER("Format_description_log_event::do_apply_event");
5862
5863 /*
5864 As a transaction NEVER spans on 2 or more binlogs:
5865 if we have an active transaction at this point, the master died
5866 while writing the transaction to the binary log, i.e. while
5867 flushing the binlog cache to the binlog. XA guarantees that master has
5868 rolled back. So we roll back.
5869 Note: this event could be sent by the master to inform us of the
5870 format of its binlog; in other words maybe it is not at its
5871 original place when it comes to us; we'll know this by checking
5872 log_pos ("artificial" events have log_pos == 0).
5873 */
5874 if (!thd->rli_fake && !is_artificial_event() && created &&
5875 thd->get_transaction()->is_active(Transaction_ctx::SESSION))
5876 {
5877 /* This is not an error (XA is safe), just an information */
5878 rli->report(INFORMATION_LEVEL, 0,
5879 "Rolling back unfinished transaction (no COMMIT "
5880 "or ROLLBACK in relay log). A probable cause is that "
5881 "the master died while writing the transaction to "
5882 "its binary log, thus rolled back too.");
5883 const_cast<Relay_log_info*>(rli)->cleanup_context(thd, 1);
5884 }
5885
5886 /*
5887 If this event comes from ourselves, there is no cleaning task to
5888 perform, we don't call Start_log_event_v3::do_apply_event()
5889 (this was just to update the log's description event).
5890 */
5891 if (server_id != (uint32) ::server_id)
5892 {
5893 /*
5894 If the event was not requested by the slave i.e. the master sent
5895 it while the slave asked for a position >4, the event will make
5896 rli->group_master_log_pos advance. Say that the slave asked for
5897 position 1000, and the Format_desc event's end is 96. Then in
5898 the beginning of replication rli->group_master_log_pos will be
5899 0, then 96, then jump to first really asked event (which is
5900 >96). So this is ok.
5901 */
5902 ret= Start_log_event_v3::do_apply_event(rli);
5903 }
5904
5905 if (!ret)
5906 {
5907 /* Save the information describing this binlog */
5908 copy_crypto_data(*rli->get_rli_description_event());
5909 const_cast<Relay_log_info *>(rli)->set_rli_description_event(this);
5910 }
5911
5912 DBUG_RETURN(ret);
5913 }
5914
do_update_pos(Relay_log_info * rli)5915 int Format_description_log_event::do_update_pos(Relay_log_info *rli)
5916 {
5917 if (server_id == (uint32) ::server_id)
5918 {
5919 /*
5920 We only increase the relay log position if we are skipping
5921 events and do not touch any group_* variables, nor flush the
5922 relay log info. If there is a crash, we will have to re-skip
5923 the events again, but that is a minor issue.
5924
5925 If we do not skip stepping the group log position (and the
5926 server id was changed when restarting the server), it might well
5927 be that we start executing at a position that is invalid, e.g.,
5928 at a Rows_log_event or a Query_log_event preceeded by a
5929 Intvar_log_event instead of starting at a Table_map_log_event or
5930 the Intvar_log_event respectively.
5931 */
5932 rli->inc_event_relay_log_pos();
5933 return 0;
5934 }
5935 else
5936 {
5937 return Log_event::do_update_pos(rli);
5938 }
5939 }
5940
5941 Log_event::enum_skip_reason
do_shall_skip(Relay_log_info * rli)5942 Format_description_log_event::do_shall_skip(Relay_log_info *rli)
5943 {
5944 return Log_event::EVENT_SKIP_NOT;
5945 }
5946
5947 #endif
5948
5949
5950
5951 /**************************************************************************
5952 Load_log_event methods
5953 General note about Load_log_event: the binlogging of LOAD DATA INFILE is
5954 going to be changed in 5.0 (or maybe in 5.1; not decided yet).
5955 However, the 5.0 slave could still have to read such events (from a 4.x
5956 master), convert them (which just means maybe expand the header, when 5.0
5957 servers have a UID in events) (remember that whatever is after the header
5958 will be like in 4.x, as this event's format is not modified in 5.0 as we
5959 will use new types of events to log the new LOAD DATA INFILE features).
5960 To be able to read/convert, we just need to not assume that the common
5961 header is of length LOG_EVENT_HEADER_LEN (we must use the description
5962 event).
5963 Note that I (Guilhem) manually tested replication of a big LOAD DATA INFILE
5964 between 3.23 and 5.0, and between 4.0 and 5.0, and it works fine (and the
5965 positions displayed in SHOW SLAVE STATUS then are fine too).
5966 **************************************************************************/
5967
5968 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
get_query_buffer_length()5969 uint Load_log_event::get_query_buffer_length()
5970 {
5971 return
5972 //the DB name may double if we escape the quote character
5973 5 + 2*db_len + 3 +
5974 18 + fname_len*4 + 2 + // "LOAD DATA INFILE 'file''"
5975 11 + // "CONCURRENT "
5976 7 + // LOCAL
5977 9 + // " REPLACE or IGNORE "
5978 13 + table_name_len*2 + // "INTO TABLE `table`"
5979 21 + sql_ex.data_info.field_term_len*4 + 2 +
5980 // " FIELDS TERMINATED BY 'str'"
5981 23 + sql_ex.data_info.enclosed_len*4 + 2 +
5982 // " OPTIONALLY ENCLOSED BY 'str'"
5983 12 + sql_ex.data_info.escaped_len*4 + 2 + // " ESCAPED BY 'str'"
5984 21 + sql_ex.data_info.line_term_len*4 + 2 +
5985 // " LINES TERMINATED BY 'str'"
5986 19 + sql_ex.data_info.line_start_len*4 + 2 +
5987 // " LINES STARTING BY 'str'"
5988 15 + 22 + // " IGNORE xxx LINES"
5989 3 + (num_fields-1)*2 + field_block_len; // " (field1, field2, ...)"
5990 }
5991
5992
print_query(bool need_db,const char * cs,char * buf,char ** end,char ** fn_start,char ** fn_end)5993 void Load_log_event::print_query(bool need_db, const char *cs, char *buf,
5994 char **end, char **fn_start, char **fn_end)
5995 {
5996 char quoted_id[1 + NAME_LEN * 2 + 2];//quoted length
5997 size_t quoted_id_len= 0;
5998 char *pos= buf;
5999
6000 if (need_db && db && db_len)
6001 {
6002 pos= my_stpcpy(pos, "use ");
6003 #ifdef MYSQL_SERVER
6004 quoted_id_len= my_strmov_quoted_identifier(this->thd, (char *) quoted_id,
6005 db, 0);
6006 #else
6007 quoted_id_len= my_strmov_quoted_identifier((char *) quoted_id, db);
6008 #endif
6009 quoted_id[quoted_id_len]= '\0';
6010 pos= my_stpcpy(pos, quoted_id);
6011 pos= my_stpcpy(pos, "; ");
6012 }
6013
6014 pos= my_stpcpy(pos, "LOAD DATA ");
6015
6016 if (is_concurrent)
6017 pos= my_stpcpy(pos, "CONCURRENT ");
6018
6019 if (fn_start)
6020 *fn_start= pos;
6021
6022 if (check_fname_outside_temp_buf())
6023 pos= my_stpcpy(pos, "LOCAL ");
6024 pos= my_stpcpy(pos, "INFILE ");
6025 pos= pretty_print_str(pos, fname, fname_len);
6026 pos= my_stpcpy(pos, " ");
6027
6028 if (sql_ex.data_info.opt_flags & REPLACE_FLAG)
6029 pos= my_stpcpy(pos, "REPLACE ");
6030 else if (sql_ex.data_info.opt_flags & IGNORE_FLAG)
6031 pos= my_stpcpy(pos, "IGNORE ");
6032
6033 pos= my_stpcpy(pos ,"INTO");
6034
6035 if (fn_end)
6036 *fn_end= pos;
6037
6038 pos= my_stpcpy(pos ," TABLE ");
6039 memcpy(pos, table_name, table_name_len);
6040 pos+= table_name_len;
6041
6042 if (cs != NULL)
6043 {
6044 pos= my_stpcpy(pos ," CHARACTER SET ");
6045 pos= my_stpcpy(pos , cs);
6046 }
6047
6048 /* We have to create all optional fields as the default is not empty */
6049 pos= my_stpcpy(pos, " FIELDS TERMINATED BY ");
6050 pos= pretty_print_str(pos, sql_ex.data_info.field_term,
6051 sql_ex.data_info.field_term_len);
6052 if (sql_ex.data_info.opt_flags & OPT_ENCLOSED_FLAG)
6053 pos= my_stpcpy(pos, " OPTIONALLY ");
6054 pos= my_stpcpy(pos, " ENCLOSED BY ");
6055 pos= pretty_print_str(pos, sql_ex.data_info.enclosed,
6056 sql_ex.data_info.enclosed_len);
6057
6058 pos= my_stpcpy(pos, " ESCAPED BY ");
6059 pos= pretty_print_str(pos, sql_ex.data_info.escaped,
6060 sql_ex.data_info.escaped_len);
6061
6062 pos= my_stpcpy(pos, " LINES TERMINATED BY ");
6063 pos= pretty_print_str(pos, sql_ex.data_info.line_term,
6064 sql_ex.data_info.line_term_len);
6065 if (sql_ex.data_info.line_start_len)
6066 {
6067 pos= my_stpcpy(pos, " STARTING BY ");
6068 pos= pretty_print_str(pos, sql_ex.data_info.line_start,
6069 sql_ex.data_info.line_start_len);
6070 }
6071
6072 if ((long) skip_lines > 0)
6073 {
6074 pos= my_stpcpy(pos, " IGNORE ");
6075 pos= longlong10_to_str((longlong) skip_lines, pos, 10);
6076 pos= my_stpcpy(pos," LINES ");
6077 }
6078
6079 if (num_fields)
6080 {
6081 uint i;
6082 const char *field= fields;
6083 pos= my_stpcpy(pos, " (");
6084 for (i = 0; i < num_fields; i++)
6085 {
6086 if (i)
6087 {
6088 *pos++= ' ';
6089 *pos++= ',';
6090 }
6091 quoted_id_len= my_strmov_quoted_identifier(this->thd, quoted_id, field,
6092 0);
6093 memcpy(pos, quoted_id, quoted_id_len-1);
6094 }
6095 *pos++= ')';
6096 }
6097
6098 *end= pos;
6099 }
6100
6101
pack_info(Protocol * protocol)6102 int Load_log_event::pack_info(Protocol *protocol)
6103 {
6104 char *buf, *end;
6105
6106 if (!(buf= (char*) my_malloc(key_memory_log_event,
6107 get_query_buffer_length(), MYF(MY_WME))))
6108 return 1;
6109 print_query(TRUE, NULL, buf, &end, 0, 0);
6110 protocol->store(buf, end-buf, &my_charset_bin);
6111 my_free(buf);
6112 return 0;
6113 }
6114 #endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
6115
6116
6117 #ifndef MYSQL_CLIENT
6118
6119 /*
6120 Load_log_event::write_data_header()
6121 */
6122
write_data_header(IO_CACHE * file)6123 bool Load_log_event::write_data_header(IO_CACHE* file)
6124 {
6125 char buf[Binary_log_event::LOAD_HEADER_LEN];
6126 int4store(buf + L_THREAD_ID_OFFSET, slave_proxy_id);
6127 int4store(buf + L_EXEC_TIME_OFFSET, exec_time);
6128 int4store(buf + L_SKIP_LINES_OFFSET, skip_lines);
6129 buf[L_TBL_LEN_OFFSET] = (char)table_name_len;
6130 buf[L_DB_LEN_OFFSET] = (char)db_len;
6131 int4store(buf + L_NUM_FIELDS_OFFSET, num_fields);
6132 return event_encrypter.encrypt_and_write(file, (uchar*)buf, Binary_log_event::LOAD_HEADER_LEN) != 0;
6133 }
6134
6135
6136 /*
6137 Load_log_event::write_data_body()
6138 */
6139
write_data_body(IO_CACHE * file)6140 bool Load_log_event::write_data_body(IO_CACHE* file)
6141 {
6142 sql_ex.event_encrypter= &event_encrypter;
6143 if (sql_ex.write_data(file))
6144 return 1;
6145 if (num_fields && fields && field_lens)
6146 {
6147 if (event_encrypter.encrypt_and_write(file, (uchar*)field_lens, num_fields) ||
6148 event_encrypter.encrypt_and_write(file, (uchar*)fields, field_block_len))
6149 return 1;
6150 }
6151 return (event_encrypter.encrypt_and_write(file, (uchar*)table_name, table_name_len + 1) ||
6152 event_encrypter.encrypt_and_write(file, (uchar*)db, db_len + 1) ||
6153 event_encrypter.encrypt_and_write(file, (uchar*)fname, fname_len));
6154 }
6155
6156
6157 /*
6158 Load_log_event::Load_log_event()
6159 */
6160
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)6161 Load_log_event::Load_log_event(THD *thd_arg, sql_exchange *ex,
6162 const char *db_arg, const char *table_name_arg,
6163 List<Item> &fields_arg,
6164 bool is_concurrent_arg,
6165 enum enum_duplicates handle_dup,
6166 bool ignore, bool using_trans)
6167 : binary_log::Load_event(),
6168 Log_event(thd_arg,
6169 thd_arg->thread_specific_used ? LOG_EVENT_THREAD_SPECIFIC_F : 0,
6170 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
6171 Log_event::EVENT_STMT_CACHE,
6172 Log_event::EVENT_NORMAL_LOGGING,
6173 header(), footer())
6174 {
6175 thread_id= thd_arg->thread_id();
6176 slave_proxy_id= thd_arg->variables.pseudo_thread_id;
6177 table_name= table_name_arg ? table_name_arg : "";
6178 db= db_arg;
6179 fname= ex->file_name;
6180 local_fname= FALSE;
6181 is_concurrent= is_concurrent_arg;
6182
6183 /*
6184 exec_time calculation has changed to use the same method that is used
6185 to fill out "thd_arg->start_time"
6186 */
6187
6188 struct timeval end_time;
6189 ulonglong micro_end_time= my_micro_time();
6190 my_micro_time_to_timeval(micro_end_time, &end_time);
6191
6192 exec_time= end_time.tv_sec - thd_arg->start_time.tv_sec;
6193
6194 /* db can never be a zero pointer in 4.0 */
6195 db_len = strlen(db);
6196 table_name_len = strlen(table_name);
6197 fname_len = (fname) ? strlen(fname) : 0;
6198 sql_ex.data_info.field_term = ex->field.field_term->ptr();
6199 sql_ex.data_info.field_term_len = (uint8) ex->field.field_term->length();
6200 sql_ex.data_info.enclosed = ex->field.enclosed->ptr();
6201 sql_ex.data_info.enclosed_len = (uint8) ex->field.enclosed->length();
6202 sql_ex.data_info.line_term = ex->line.line_term->ptr();
6203 sql_ex.data_info.line_term_len = (uint8) ex->line.line_term->length();
6204 sql_ex.data_info.line_start = ex->line.line_start->ptr();
6205 sql_ex.data_info.line_start_len = (uint8) ex->line.line_start->length();
6206 sql_ex.data_info.escaped = (char*) ex->field.escaped->ptr();
6207 sql_ex.data_info.escaped_len = (uint8) ex->field.escaped->length();
6208 sql_ex.data_info.opt_flags = 0;
6209 sql_ex.data_info.cached_new_format = -1;
6210
6211 if (ex->dumpfile)
6212 sql_ex.data_info.opt_flags|= DUMPFILE_FLAG;
6213 if (ex->field.opt_enclosed)
6214 sql_ex.data_info.opt_flags|= OPT_ENCLOSED_FLAG;
6215
6216 sql_ex.data_info.empty_flags= 0;
6217
6218 switch (handle_dup) {
6219 case DUP_REPLACE:
6220 sql_ex.data_info.opt_flags|= REPLACE_FLAG;
6221 break;
6222 case DUP_UPDATE: // Impossible here
6223 case DUP_ERROR:
6224 break;
6225 }
6226 if (ignore)
6227 sql_ex.data_info.opt_flags|= IGNORE_FLAG;
6228
6229 if (!ex->field.field_term->length())
6230 sql_ex.data_info.empty_flags |= FIELD_TERM_EMPTY;
6231 if (!ex->field.enclosed->length())
6232 sql_ex.data_info.empty_flags |= ENCLOSED_EMPTY;
6233 if (!ex->line.line_term->length())
6234 sql_ex.data_info.empty_flags |= LINE_TERM_EMPTY;
6235 if (!ex->line.line_start->length())
6236 sql_ex.data_info.empty_flags |= LINE_START_EMPTY;
6237 if (!ex->field.escaped->length())
6238 sql_ex.data_info.empty_flags |= ESCAPED_EMPTY;
6239
6240 skip_lines = ex->skip_lines;
6241
6242 List_iterator<Item> li(fields_arg);
6243 field_lens_buf.length(0);
6244 fields_buf.length(0);
6245 Item* item;
6246 while ((item = li++))
6247 {
6248 num_fields++;
6249 uchar len= (uchar) item->item_name.length();
6250 field_block_len += len + 1;
6251 fields_buf.append(item->item_name.ptr(), len + 1);
6252 field_lens_buf.append((char*)&len, 1);
6253 }
6254
6255 field_lens = (const uchar*)field_lens_buf.ptr();
6256 fields = fields_buf.ptr();
6257 if (table_name != 0)
6258 is_valid_param= true;
6259
6260 if (sql_ex.data_info.new_format())
6261 common_header->type_code= binary_log::NEW_LOAD_EVENT;
6262 else
6263 common_header->type_code= binary_log::LOAD_EVENT;
6264 }
6265 #endif /* !MYSQL_CLIENT */
6266
6267
6268 /**
6269 @note
6270 The caller must do buf[event_len] = 0 before he starts using the
6271 constructed event.
6272 */
Load_log_event(const char * buf,uint event_len,const Format_description_event * description_event)6273 Load_log_event::Load_log_event(const char *buf, uint event_len,
6274 const Format_description_event *description_event)
6275 : binary_log::Load_event(buf, event_len, description_event),
6276 Log_event(header(), footer())
6277 {
6278 DBUG_ENTER("Load_log_event");
6279 if (table_name != 0)
6280 is_valid_param= true;
6281 thread_id= slave_proxy_id;
6282 if (event_len)
6283 {
6284 /**
6285 We need to set exec_time here, which is ued to calcutate seconds behind
6286 master on the slave.
6287 */
6288 exec_time= load_exec_time;
6289 /*
6290 I (Guilhem) manually tested replication of LOAD DATA INFILE for 3.23->5.0,
6291 4.0->5.0 and 5.0->5.0 and it works.
6292 */
6293 sql_ex.data_info= sql_ex_data;
6294 }
6295 if (sql_ex.data_info.new_format())
6296 common_header->type_code= binary_log::NEW_LOAD_EVENT;
6297 else
6298 common_header->type_code= binary_log::LOAD_EVENT;
6299 DBUG_VOID_RETURN;
6300 }
6301
6302
6303 /*
6304 Load_log_event::print()
6305 */
6306
6307 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)6308 void Load_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
6309 {
6310 print(file, print_event_info, 0);
6311 }
6312
6313
print(FILE * file_arg,PRINT_EVENT_INFO * print_event_info,bool commented)6314 void Load_log_event::print(FILE* file_arg, PRINT_EVENT_INFO* print_event_info,
6315 bool commented)
6316 {
6317 IO_CACHE *const head= &print_event_info->head_cache;
6318 size_t id_len= 0;
6319 char str_buf[1 + 2*FN_REFLEN + 2];
6320
6321 DBUG_ENTER("Load_log_event::print");
6322 if (!print_event_info->short_form)
6323 {
6324 print_header(head, print_event_info, FALSE);
6325 my_b_printf(head, "\tQuery\tthread_id=%u\texec_time=%ld\n",
6326 thread_id, exec_time);
6327 }
6328
6329 bool different_db= 1;
6330 if (db)
6331 {
6332 /*
6333 If the database is different from the one of the previous statement, we
6334 need to print the "use" command, and we update the last_db.
6335 But if commented, the "use" is going to be commented so we should not
6336 update the last_db.
6337 */
6338 if ((different_db= memcmp(print_event_info->db, db, db_len + 1)) &&
6339 !commented)
6340 memcpy(print_event_info->db, db, db_len + 1);
6341 }
6342
6343 if (db && db[0] && different_db)
6344 {
6345 #ifdef MYSQL_SERVER
6346 id_len= my_strmov_quoted_identifier(this->thd, str_buf, db, 0);
6347 #else
6348 id_len= my_strmov_quoted_identifier(str_buf, db);
6349 #endif
6350 str_buf[id_len]= '\0';
6351 my_b_printf(head, "%suse %s%s\n",
6352 commented ? "# " : "", str_buf, print_event_info->delimiter);
6353 }
6354 if (common_header->flags & LOG_EVENT_THREAD_SPECIFIC_F)
6355 my_b_printf(head,"%sSET @@session.pseudo_thread_id=%lu%s\n",
6356 commented ? "# " : "", (ulong)thread_id,
6357 print_event_info->delimiter);
6358 my_b_printf(head, "%sLOAD DATA ",
6359 commented ? "# " : "");
6360 if (check_fname_outside_temp_buf())
6361 my_b_printf(head, "LOCAL ");
6362 my_b_printf(head, "INFILE '%-*s' ", static_cast<int>(fname_len), fname);
6363
6364 if (sql_ex.data_info.opt_flags & REPLACE_FLAG)
6365 my_b_printf(head,"REPLACE ");
6366 else if (sql_ex.data_info.opt_flags & IGNORE_FLAG)
6367 my_b_printf(head,"IGNORE ");
6368
6369 #ifdef MYSQL_SERVER
6370 id_len= my_strmov_quoted_identifier(this->thd, str_buf, table_name, 0);
6371 #else
6372 id_len= my_strmov_quoted_identifier(str_buf, table_name);
6373 #endif
6374 str_buf[id_len]= '\0';
6375 my_b_printf(head, "INTO TABLE %s", str_buf);
6376
6377 my_b_printf(head, " FIELDS TERMINATED BY ");
6378 pretty_print_str(head, sql_ex.data_info.field_term,
6379 sql_ex.data_info.field_term_len);
6380
6381 if (sql_ex.data_info.opt_flags & OPT_ENCLOSED_FLAG)
6382 my_b_printf(head," OPTIONALLY ");
6383 my_b_printf(head, " ENCLOSED BY ");
6384 pretty_print_str(head, sql_ex.data_info.enclosed,
6385 sql_ex.data_info.enclosed_len);
6386
6387 my_b_printf(head, " ESCAPED BY ");
6388 pretty_print_str(head, sql_ex.data_info.escaped,
6389 sql_ex.data_info.escaped_len);
6390
6391 my_b_printf(head," LINES TERMINATED BY ");
6392 pretty_print_str(head, sql_ex.data_info.line_term,
6393 sql_ex.data_info.line_term_len);
6394
6395
6396 if (sql_ex.data_info.line_start)
6397 {
6398 my_b_printf(head," STARTING BY ");
6399 pretty_print_str(head, sql_ex.data_info.line_start,
6400 sql_ex.data_info.line_start_len);
6401 }
6402 if ((long) skip_lines > 0)
6403 my_b_printf(head, " IGNORE %ld LINES", (long) skip_lines);
6404
6405 if (num_fields)
6406 {
6407 uint i;
6408 const char* field = fields;
6409 my_b_printf(head, " (");
6410 for (i = 0; i < num_fields; i++)
6411 {
6412 if (i)
6413 my_b_printf(head, ",");
6414 id_len= my_strmov_quoted_identifier((char *) str_buf, field);
6415 str_buf[id_len]= '\0';
6416 my_b_printf(head, "%s", str_buf);
6417
6418 field += field_lens[i] + 1;
6419 }
6420 my_b_printf(head, ")");
6421 }
6422
6423 my_b_printf(head, "%s\n", print_event_info->delimiter);
6424 DBUG_VOID_RETURN;
6425 }
6426 #endif /* MYSQL_CLIENT */
6427
6428 #ifndef MYSQL_CLIENT
6429
6430 /**
6431 Load_log_event::set_fields()
6432
6433 @note
6434 This function can not use the member variable
6435 for the database, since LOAD DATA INFILE on the slave
6436 can be for a different database than the current one.
6437 This is the reason for the affected_db argument to this method.
6438 */
6439
set_fields(const char * affected_db,List<Item> & field_list,Name_resolution_context * context)6440 void Load_log_event::set_fields(const char* affected_db,
6441 List<Item> &field_list,
6442 Name_resolution_context *context)
6443 {
6444 uint i;
6445 const char* field = fields;
6446 for (i= 0; i < num_fields; i++)
6447 {
6448 field_list.push_back(new Item_field(context,
6449 affected_db, table_name, field));
6450 field+= field_lens[i] + 1;
6451 }
6452 }
6453 #endif /* !MYSQL_CLIENT */
6454
6455
6456 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
6457 /**
6458 Does the data loading job when executing a LOAD DATA on the slave.
6459
6460 @param net
6461 @param rli
6462 @param use_rli_only_for_errors If set to 1, rli is provided to
6463 Load_log_event::exec_event only for this
6464 function to have rli->get_rpl_log_name and
6465 rli->last_slave_error, both being used by
6466 error reports. If set to 0, rli is provided
6467 for full use, i.e. for error reports and
6468 position advancing.
6469
6470 @todo
6471 fix this; this can be done by testing rules in
6472 Create_file_log_event::exec_event() and then discarding Append_block and
6473 al.
6474 @todo
6475 this is a bug - this needs to be moved to the I/O thread
6476
6477 @retval
6478 0 Success
6479 @retval
6480 1 Failure
6481 */
6482
do_apply_event(NET * net,Relay_log_info const * rli,bool use_rli_only_for_errors)6483 int Load_log_event::do_apply_event(NET* net, Relay_log_info const *rli,
6484 bool use_rli_only_for_errors)
6485 {
6486 assert(thd->query().str == NULL);
6487 thd->reset_query(); // Should not be needed
6488 set_thd_db(thd, db, db_len);
6489 thd->is_slave_error= 0;
6490 clear_all_errors(thd, const_cast<Relay_log_info*>(rli));
6491
6492 /* see Query_log_event::do_apply_event() and BUG#13360 */
6493 assert(!rli->m_table_map.count());
6494 /*
6495 Usually lex_start() is called by mysql_parse(), but we need it here
6496 as the present method does not call mysql_parse().
6497 */
6498 lex_start(thd);
6499 thd->lex->local_file= local_fname;
6500 mysql_reset_thd_for_next_command(thd);
6501
6502 /*
6503 It is possible that the thread does not hold anonymous GTID
6504 ownership here, e.g. in case this is the first event of a relay
6505 log.
6506 */
6507 gtid_reacquire_ownership_if_anonymous(thd);
6508
6509 /*
6510 We test replicate_*_db rules. Note that we have already prepared
6511 the file to load, even if we are going to ignore and delete it
6512 now. So it is possible that we did a lot of disk writes for
6513 nothing. In other words, a big LOAD DATA INFILE on the master will
6514 still consume a lot of space on the slave (space in the relay log
6515 + space of temp files: twice the space of the file to load...)
6516 even if it will finally be ignored. TODO: fix this; this can be
6517 done by testing rules in Create_file_log_event::do_apply_event()
6518 and then discarding Append_block and al. Another way is do the
6519 filtering in the I/O thread (more efficient: no disk writes at
6520 all).
6521 */
6522 if (rpl_filter->db_ok(thd->db().str))
6523 {
6524 thd->set_time(&(common_header->when));
6525 thd->set_query_id(next_query_id());
6526 assert(!thd->get_stmt_da()->is_set());
6527
6528 TABLE_LIST tables;
6529 char table_buf[NAME_LEN + 1];
6530 my_stpcpy(table_buf, table_name);
6531 if (lower_case_table_names)
6532 my_casedn_str(system_charset_info, table_buf);
6533 tables.init_one_table(thd->strmake(thd->db().str, thd->db().length),
6534 thd->db().length,
6535 table_buf, strlen(table_buf),
6536 table_buf, TL_WRITE);
6537 tables.updating= 1;
6538
6539 // the table will be opened in mysql_load
6540 if (rpl_filter->is_on() && !rpl_filter->tables_ok(thd->db().str, &tables))
6541 {
6542 // TODO: this is a bug - this needs to be moved to the I/O thread
6543 if (net)
6544 skip_load_data_infile(net);
6545 }
6546 else
6547 {
6548 char llbuff[22];
6549 char *end;
6550 enum enum_duplicates handle_dup;
6551 char *load_data_query;
6552
6553 /*
6554 Forge LOAD DATA INFILE query which will be used in SHOW PROCESS LIST
6555 and written to slave's binlog if binlogging is on.
6556 */
6557 if (!(load_data_query= (char *)thd->alloc(get_query_buffer_length() + 1)))
6558 {
6559 /*
6560 This will set thd->fatal_error in case of OOM. So we surely will notice
6561 that something is wrong.
6562 */
6563 goto error;
6564 }
6565
6566 print_query(FALSE, NULL, load_data_query, &end, NULL, NULL);
6567 *end= 0;
6568 thd->set_query(load_data_query, static_cast<size_t>(end - load_data_query));
6569
6570 if (sql_ex.data_info.opt_flags & REPLACE_FLAG)
6571 handle_dup= DUP_REPLACE;
6572 else if (sql_ex.data_info.opt_flags & IGNORE_FLAG)
6573 {
6574 thd->lex->set_ignore(true);
6575 handle_dup= DUP_ERROR;
6576 }
6577 else
6578 {
6579 /*
6580 When replication is running fine, if it was DUP_ERROR on the
6581 master then we could choose IGNORE here, because if DUP_ERROR
6582 suceeded on master, and data is identical on the master and slave,
6583 then there should be no uniqueness errors on slave, so IGNORE is
6584 the same as DUP_ERROR. But in the unlikely case of uniqueness errors
6585 (because the data on the master and slave happen to be different
6586 (user error or bug), we want LOAD DATA to print an error message on
6587 the slave to discover the problem.
6588
6589 If reading from net (a 3.23 master), mysql_load() will change this
6590 to IGNORE.
6591 */
6592 handle_dup= DUP_ERROR;
6593 }
6594 /*
6595 We need to set thd->lex->sql_command and thd->lex->duplicates
6596 since InnoDB tests these variables to decide if this is a LOAD
6597 DATA ... REPLACE INTO ... statement even though mysql_parse()
6598 is not called. This is not needed in 5.0 since there the LOAD
6599 DATA ... statement is replicated using mysql_parse(), which
6600 sets the thd->lex fields correctly.
6601 */
6602 thd->lex->sql_command= SQLCOM_LOAD;
6603 thd->lex->duplicates= handle_dup;
6604
6605 sql_exchange ex((char*)fname, sql_ex.data_info.opt_flags & DUMPFILE_FLAG);
6606 String field_term(sql_ex.data_info.field_term,
6607 sql_ex.data_info.field_term_len,log_cs);
6608 String enclosed(sql_ex.data_info.enclosed,
6609 sql_ex.data_info.enclosed_len,log_cs);
6610 String line_term(sql_ex.data_info.line_term,
6611 sql_ex.data_info.line_term_len,log_cs);
6612 String line_start(sql_ex.data_info.line_start,
6613 sql_ex.data_info.line_start_len,log_cs);
6614 String escaped(sql_ex.data_info.escaped,
6615 sql_ex.data_info.escaped_len, log_cs);
6616 const String empty_str("", 0, log_cs);
6617 ex.field.field_term= &field_term;
6618 ex.field.enclosed= &enclosed;
6619 ex.line.line_term= &line_term;
6620 ex.line.line_start= &line_start;
6621 ex.field.escaped= &escaped;
6622
6623 ex.field.opt_enclosed= (sql_ex.data_info.opt_flags & OPT_ENCLOSED_FLAG);
6624 if (sql_ex.data_info.empty_flags & FIELD_TERM_EMPTY)
6625 ex.field.field_term= &empty_str;
6626
6627 ex.skip_lines= skip_lines;
6628 List<Item> field_list;
6629 thd->lex->select_lex->context.resolve_in_table_list_only(&tables);
6630 set_fields(tables.db, field_list, &thd->lex->select_lex->context);
6631 thd->variables.pseudo_thread_id= thread_id;
6632 if (net)
6633 {
6634 // mysql_load will use thd->net to read the file
6635 thd->get_protocol_classic()->set_vio(net->vio);
6636 // Make sure the client does not get confused about the packet sequence
6637 thd->get_protocol_classic()->set_pkt_nr(net->pkt_nr);
6638 }
6639 /*
6640 It is safe to use tmp_list twice because we are not going to
6641 update it inside mysql_load().
6642 */
6643 List<Item> tmp_list;
6644 /*
6645 Prepare column privilege check for LOAD statement.
6646 This is necessary because the replication code for LOAD bypasses
6647 regular privilege checking, which is done by check_one_table_access()
6648 in regular code path.
6649 We can assign INSERT privileges to the table since the slave thread
6650 operates with all privileges.
6651 */
6652 tables.set_privileges(INSERT_ACL);
6653 tables.set_want_privilege(INSERT_ACL);
6654
6655 if (open_temporary_tables(thd, &tables) ||
6656 mysql_load(thd, &ex, &tables, field_list, tmp_list, tmp_list,
6657 handle_dup, net != 0))
6658 thd->is_slave_error= 1;
6659 if (thd->cuted_fields)
6660 {
6661 /* log_pos is the position of the LOAD event in the master log */
6662 sql_print_warning("Slave: load data infile on table '%s' at "
6663 "log position %s in log '%s' produced %ld "
6664 "warning(s). Default database: '%s'",
6665 (char*) table_name,
6666 llstr(common_header->log_pos,llbuff),
6667 const_cast<Relay_log_info*>(rli)->get_rpl_log_name(),
6668 (ulong) thd->cuted_fields,
6669 print_slave_db_safe(thd->db().str));
6670 }
6671 if (net)
6672 {
6673 net->pkt_nr= thd->get_protocol_classic()->get_pkt_nr();
6674 }
6675 }
6676 }
6677 else
6678 {
6679 /*
6680 We will just ask the master to send us /dev/null if we do not
6681 want to load the data.
6682 TODO: this a bug - needs to be done in I/O thread
6683 */
6684 if (net)
6685 skip_load_data_infile(net);
6686 }
6687
6688 error:
6689 thd->get_protocol_classic()->set_vio(NULL);
6690 const char *remember_db= thd->db().str;
6691 thd->set_catalog(NULL_CSTR);
6692 thd->set_db(NULL_CSTR); /* will free the current database */
6693 thd->reset_query();
6694 thd->get_stmt_da()->set_overwrite_status(true);
6695 thd->is_error() ? trans_rollback_stmt(thd) : trans_commit_stmt(thd);
6696 thd->get_stmt_da()->set_overwrite_status(false);
6697 close_thread_tables(thd);
6698 /*
6699 - If transaction rollback was requested due to deadlock
6700 perform it and release metadata locks.
6701 - If inside a multi-statement transaction,
6702 defer the release of metadata locks until the current
6703 transaction is either committed or rolled back. This prevents
6704 other statements from modifying the table for the entire
6705 duration of this transaction. This provides commit ordering
6706 and guarantees serializability across multiple transactions.
6707 - If in autocommit mode, or outside a transactional context,
6708 automatically release metadata locks of the current statement.
6709 */
6710 if (thd->transaction_rollback_request)
6711 {
6712 trans_rollback_implicit(thd);
6713 thd->mdl_context.release_transactional_locks();
6714 }
6715 else if (! thd->in_multi_stmt_transaction_mode())
6716 thd->mdl_context.release_transactional_locks();
6717 else
6718 thd->mdl_context.release_statement_locks();
6719
6720 DBUG_EXECUTE_IF("LOAD_DATA_INFILE_has_fatal_error",
6721 thd->is_slave_error= 0; thd->is_fatal_error= 1;);
6722
6723 if (thd->is_slave_error)
6724 {
6725 /* this err/sql_errno code is copy-paste from net_send_error() */
6726 const char *err;
6727 int sql_errno;
6728 if (thd->is_error())
6729 {
6730 err= thd->get_stmt_da()->message_text();
6731 sql_errno= thd->get_stmt_da()->mysql_errno();
6732 }
6733 else
6734 {
6735 sql_errno=ER_UNKNOWN_ERROR;
6736 err=ER(sql_errno);
6737 }
6738 rli->report(ERROR_LEVEL, sql_errno,"\
6739 Error '%s' running LOAD DATA INFILE on table '%s'. Default database: '%s'",
6740 err, (char*)table_name, print_slave_db_safe(remember_db));
6741 free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
6742 return 1;
6743 }
6744 free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
6745
6746 if (thd->is_fatal_error)
6747 {
6748 char buf[256];
6749 my_snprintf(buf, sizeof(buf),
6750 "Running LOAD DATA INFILE on table '%-.64s'."
6751 " Default database: '%-.64s'",
6752 (char*)table_name,
6753 print_slave_db_safe(remember_db));
6754
6755 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
6756 ER(ER_SLAVE_FATAL_ERROR), buf);
6757 return 1;
6758 }
6759
6760 return ( use_rli_only_for_errors ? 0 : Log_event::do_apply_event(rli) );
6761 }
6762 #endif
6763
6764
6765 /**************************************************************************
6766 Rotate_log_event methods
6767 **************************************************************************/
6768
6769 /*
6770 Rotate_log_event::pack_info()
6771 */
6772
6773 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
pack_info(Protocol * protocol)6774 int Rotate_log_event::pack_info(Protocol *protocol)
6775 {
6776 char buf1[256], buf[22];
6777 String tmp(buf1, sizeof(buf1), log_cs);
6778 tmp.length(0);
6779 tmp.append(new_log_ident, ident_len);
6780 tmp.append(STRING_WITH_LEN(";pos="));
6781 tmp.append(llstr(pos,buf));
6782 protocol->store(tmp.ptr(), tmp.length(), &my_charset_bin);
6783 return 0;
6784 }
6785 #endif
6786
6787
6788 /*
6789 Rotate_log_event::print()
6790 */
6791
6792 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)6793 void Rotate_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
6794 {
6795 char buf[22];
6796 IO_CACHE *const head= &print_event_info->head_cache;
6797
6798 if (print_event_info->short_form)
6799 return;
6800 print_header(head, print_event_info, FALSE);
6801 my_b_printf(head, "\tRotate to ");
6802 if (new_log_ident)
6803 {
6804 MY_ATTRIBUTE((unused)) int write_res=
6805 my_b_write(head, (uchar*) new_log_ident, (uint)ident_len);
6806 assert(write_res == 0);
6807 }
6808 my_b_printf(head, " pos: %s\n", llstr(pos, buf));
6809 }
6810 #endif /* MYSQL_CLIENT */
6811
6812
6813
6814 /*
6815 Rotate_log_event::Rotate_log_event() (2 constructors)
6816 */
6817
6818
6819 #ifndef MYSQL_CLIENT
Rotate_log_event(const char * new_log_ident_arg,size_t ident_len_arg,ulonglong pos_arg,uint flags_arg)6820 Rotate_log_event::Rotate_log_event(const char* new_log_ident_arg,
6821 size_t ident_len_arg, ulonglong pos_arg,
6822 uint flags_arg)
6823 : binary_log::Rotate_event(new_log_ident_arg, ident_len_arg, flags_arg, pos_arg),
6824 Log_event(header(), footer(),
6825 Log_event::EVENT_NO_CACHE, Log_event::EVENT_IMMEDIATE_LOGGING)
6826 {
6827 #ifndef NDEBUG
6828 DBUG_ENTER("Rotate_log_event::Rotate_log_event(...,flags)");
6829 #endif
6830 new_log_ident= new_log_ident_arg;
6831 pos= pos_arg;
6832 ident_len= ident_len_arg ?
6833 ident_len_arg : (uint) strlen(new_log_ident_arg);
6834 flags= flags_arg;
6835
6836 #ifndef NDEBUG
6837 char buff[22];
6838 DBUG_PRINT("enter",("new_log_ident: %s pos: %s flags: %lu", new_log_ident_arg,
6839 llstr(pos_arg, buff), (ulong) flags));
6840 #endif
6841 if (flags & DUP_NAME)
6842 new_log_ident= my_strndup(key_memory_log_event,
6843 new_log_ident_arg, ident_len, MYF(MY_WME));
6844 if (new_log_ident != 0)
6845 is_valid_param= true;
6846 if (flags & RELAY_LOG)
6847 set_relay_log_event();
6848 DBUG_VOID_RETURN;
6849 }
6850 #endif
6851
6852
Rotate_log_event(const char * buf,uint event_len,const Format_description_event * description_event)6853 Rotate_log_event::Rotate_log_event(const char* buf, uint event_len,
6854 const Format_description_event* description_event)
6855 : binary_log::Rotate_event(buf, event_len, description_event),
6856 Log_event(header(), footer())
6857 {
6858 DBUG_ENTER("Rotate_log_event::Rotate_log_event(char*,...)");
6859
6860 if (new_log_ident != 0)
6861 is_valid_param= true;
6862 DBUG_PRINT("debug", ("new_log_ident: '%s'", new_log_ident));
6863 DBUG_VOID_RETURN;
6864 }
6865
6866
6867 /*
6868 Rotate_log_event::write()
6869 */
6870
6871 #ifndef MYSQL_CLIENT
write(IO_CACHE * file)6872 bool Rotate_log_event::write(IO_CACHE* file)
6873 {
6874 char buf[Binary_log_event::ROTATE_HEADER_LEN];
6875 int8store(buf + R_POS_OFFSET, pos);
6876 return (write_header(file, Binary_log_event::ROTATE_HEADER_LEN + ident_len) ||
6877 wrapper_my_b_safe_write(file, (uchar*) buf, Binary_log_event::ROTATE_HEADER_LEN) ||
6878 wrapper_my_b_safe_write(file, (uchar*) new_log_ident,
6879 (uint) ident_len) ||
6880 write_footer(file));
6881 }
6882 #endif
6883
6884
6885 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
6886
6887 /*
6888 Got a rotate log event from the master.
6889
6890 This is mainly used so that we can later figure out the logname and
6891 position for the master.
6892
6893 We can't rotate the slave's BINlog as this will cause infinitive rotations
6894 in a A -> B -> A setup.
6895 The NOTES below is a wrong comment which will disappear when 4.1 is merged.
6896
6897 This must only be called from the Slave SQL thread, since it calls
6898 flush_relay_log_info().
6899
6900 @retval
6901 0 ok
6902 */
do_update_pos(Relay_log_info * rli)6903 int Rotate_log_event::do_update_pos(Relay_log_info *rli)
6904 {
6905 int error= 0;
6906 DBUG_ENTER("Rotate_log_event::do_update_pos");
6907 #ifndef NDEBUG
6908 char buf[32];
6909 #endif
6910
6911 DBUG_PRINT("info", ("server_id=%lu; ::server_id=%lu",
6912 (ulong) this->server_id, (ulong) ::server_id));
6913 DBUG_PRINT("info", ("new_log_ident: %s", this->new_log_ident));
6914 DBUG_PRINT("info", ("pos: %s", llstr(this->pos, buf)));
6915
6916 /*
6917 If we are in a transaction or in a group: the only normal case is
6918 when the I/O thread was copying a big transaction, then it was
6919 stopped and restarted: we have this in the relay log:
6920
6921 BEGIN
6922 ...
6923 ROTATE (a fake one)
6924 ...
6925 COMMIT or ROLLBACK
6926
6927 In that case, we don't want to touch the coordinates which
6928 correspond to the beginning of the transaction. Starting from
6929 5.0.0, there also are some rotates from the slave itself, in the
6930 relay log, which shall not change the group positions.
6931 */
6932
6933 /*
6934 The way we check if SQL thread is currently in a group is different
6935 for STS and MTS.
6936 */
6937 bool in_group = rli->is_parallel_exec() ?
6938 (rli->mts_group_status == Relay_log_info::MTS_IN_GROUP) :
6939 rli->is_in_group();
6940
6941 if ((server_id != ::server_id || rli->replicate_same_server_id) &&
6942 !is_relay_log_event() &&
6943 !in_group)
6944 {
6945 if (!is_mts_db_partitioned(rli) && server_id != ::server_id)
6946 {
6947 // force the coordinator to start a new binlog segment.
6948 static_cast<Mts_submode_logical_clock*>
6949 (rli->current_mts_submode)->start_new_group();
6950 }
6951 if (rli->is_parallel_exec())
6952 {
6953 /*
6954 Rotate events are special events that are handled as a
6955 synchronization point. For that reason, the checkpoint
6956 routine is being called here.
6957 */
6958 if ((error= mts_checkpoint_routine(rli, 0, false,
6959 true/*need_data_lock=true*/)))
6960 goto err;
6961 }
6962
6963 /*
6964 Acquire protection against global BINLOG lock before rli->data_lock is
6965 locked (otherwise we would also block SHOW SLAVE STATUS).
6966 */
6967 assert(!thd->backup_binlog_lock.is_acquired());
6968 DBUG_PRINT("debug", ("Acquiring binlog protection lock"));
6969 mysql_mutex_assert_not_owner(&rli->data_lock);
6970 const ulong timeout= thd->variables.lock_wait_timeout;
6971 if (thd->backup_binlog_lock.acquire_protection(thd, MDL_EXPLICIT, timeout))
6972 {
6973 error= 1;
6974 goto err;
6975 }
6976
6977 mysql_mutex_lock(&rli->data_lock);
6978 DBUG_PRINT("info", ("old group_master_log_name: '%s' "
6979 "old group_master_log_pos: %lu",
6980 rli->get_group_master_log_name(),
6981 (ulong) rli->get_group_master_log_pos()));
6982
6983 memcpy((void *)rli->get_group_master_log_name(),
6984 new_log_ident, ident_len + 1);
6985 rli->notify_group_master_log_name_update();
6986 if ((error= rli->inc_group_relay_log_pos(pos,
6987 false/*need_data_lock=false*/)))
6988 {
6989 mysql_mutex_unlock(&rli->data_lock);
6990 DBUG_PRINT("debug", ("Releasing binlog protection lock"));
6991 thd->backup_binlog_lock.release_protection(thd);
6992 goto err;
6993 }
6994
6995 DBUG_PRINT("info", ("new group_master_log_name: '%s' "
6996 "new group_master_log_pos: %lu",
6997 rli->get_group_master_log_name(),
6998 (ulong) rli->get_group_master_log_pos()));
6999 mysql_mutex_unlock(&rli->data_lock);
7000
7001 DBUG_PRINT("debug", ("Releasing binlog protection lock"));
7002 thd->backup_binlog_lock.release_protection(thd);
7003
7004 if (rli->is_parallel_exec())
7005 {
7006 bool real_event= server_id && !is_artificial_event();
7007 rli->reset_notified_checkpoint(0,
7008 real_event ?
7009 common_header->when.tv_sec +
7010 (time_t) exec_time : 0,
7011 true/*need_data_lock=true*/,
7012 real_event? true : false);
7013 }
7014
7015 /*
7016 Reset thd->variables.option_bits and sql_mode etc, because this could be the signal of
7017 a master's downgrade from 5.0 to 4.0.
7018 However, no need to reset rli_description_event: indeed, if the next
7019 master is 5.0 (even 5.0.1) we will soon get a Format_desc; if the next
7020 master is 4.0 then the events are in the slave's format (conversion).
7021 */
7022 set_slave_thread_options(thd);
7023 set_slave_thread_default_charset(thd, rli);
7024 thd->variables.sql_mode= global_system_variables.sql_mode;
7025 thd->variables.auto_increment_increment=
7026 thd->variables.auto_increment_offset= 1;
7027 /*
7028 Rotate_log_events are generated on Slaves with server_id=0
7029 for all the ignored events, so that the positions in the repository
7030 is updated properly even for ignored events.
7031
7032 This kind of Rotate_log_event is generated when
7033
7034 1) the event is generated on the same host and reached due
7035 to circular replication (server_id == ::server_id)
7036
7037 2) the event is from the host which is listed in ignore_server_ids
7038
7039 3) IO thread is receiving HEARTBEAT event from the master
7040
7041 4) IO thread is receiving PREVIOUS_GTID_LOG_EVENT from the master.
7042
7043 We have to free thd's mem_root here after we update the positions
7044 in the repository table. Otherwise, imagine a situation where
7045 Slave is keep getting ignored events only and no other (non-ignored)
7046 events from the Master, Slave never executes free_root (that generally
7047 happens from Query_log_event::do_apply_event or
7048 Rows_log_event::do_apply_event when they find end of the group event).
7049 */
7050 if (server_id == 0)
7051 free_root(thd->mem_root, MYF(MY_KEEP_PREALLOC));
7052 }
7053 else
7054 rli->inc_event_relay_log_pos();
7055
7056 err:
7057 DBUG_RETURN(error);
7058 }
7059
7060
7061 Log_event::enum_skip_reason
do_shall_skip(Relay_log_info * rli)7062 Rotate_log_event::do_shall_skip(Relay_log_info *rli)
7063 {
7064 enum_skip_reason reason= Log_event::do_shall_skip(rli);
7065
7066 switch (reason) {
7067 case Log_event::EVENT_SKIP_NOT:
7068 case Log_event::EVENT_SKIP_COUNT:
7069 return Log_event::EVENT_SKIP_NOT;
7070
7071 case Log_event::EVENT_SKIP_IGNORE:
7072 return Log_event::EVENT_SKIP_IGNORE;
7073 }
7074 assert(0);
7075 return Log_event::EVENT_SKIP_NOT; // To keep compiler happy
7076 }
7077
7078 #endif
7079
7080
7081 /**************************************************************************
7082 Intvar_log_event methods
7083 **************************************************************************/
7084
7085 /*
7086 Intvar_log_event::pack_info()
7087 */
7088
7089 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
pack_info(Protocol * protocol)7090 int Intvar_log_event::pack_info(Protocol *protocol)
7091 {
7092 char buf[256], *pos;
7093 pos= strmake(buf, (get_var_type_string()).c_str(), sizeof(buf)-23);
7094 *pos++= '=';
7095 pos= longlong10_to_str(val, pos, -10);
7096 protocol->store(buf, (uint) (pos-buf), &my_charset_bin);
7097 return 0;
7098 }
7099 #endif
7100
7101
7102 /*
7103 Intvar_log_event::Intvar_log_event()
7104 */
Intvar_log_event(const char * buf,const Format_description_event * description_event)7105 Intvar_log_event::Intvar_log_event(const char* buf,
7106 const Format_description_event*
7107 description_event)
7108 : binary_log::Intvar_event(buf, description_event),
7109 Log_event(header(), footer())
7110 {
7111 is_valid_param= true;
7112 }
7113
7114 /*
7115 Intvar_log_event::write()
7116 */
7117
7118 #ifndef MYSQL_CLIENT
write(IO_CACHE * file)7119 bool Intvar_log_event::write(IO_CACHE* file)
7120 {
7121 uchar buf[9];
7122 buf[I_TYPE_OFFSET]= (uchar) type;
7123 int8store(buf + I_VAL_OFFSET, val);
7124 return (write_header(file, sizeof(buf)) ||
7125 wrapper_my_b_safe_write(file, buf, sizeof(buf)) ||
7126 write_footer(file));
7127 }
7128 #endif
7129
7130
7131 /*
7132 Intvar_log_event::print()
7133 */
7134
7135 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)7136 void Intvar_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
7137 {
7138 char llbuff[22];
7139 const char *msg= NULL;
7140 IO_CACHE *const head= &print_event_info->head_cache;
7141
7142 if (!print_event_info->short_form)
7143 {
7144 print_header(head, print_event_info, FALSE);
7145 my_b_printf(head, "\tIntvar\n");
7146 }
7147
7148 my_b_printf(head, "SET ");
7149 switch (type) {
7150 case LAST_INSERT_ID_EVENT:
7151 msg="LAST_INSERT_ID";
7152 break;
7153 case INSERT_ID_EVENT:
7154 msg="INSERT_ID";
7155 break;
7156 case INVALID_INT_EVENT:
7157 default: // cannot happen
7158 msg="INVALID_INT";
7159 break;
7160 }
7161 my_b_printf(head, "%s=%s%s\n",
7162 msg, llstr(val,llbuff), print_event_info->delimiter);
7163 }
7164 #endif
7165
7166
7167 #if defined(HAVE_REPLICATION)&& !defined(MYSQL_CLIENT)
7168
7169 /*
7170 Intvar_log_event::do_apply_event()
7171 */
7172
do_apply_event(Relay_log_info const * rli)7173 int Intvar_log_event::do_apply_event(Relay_log_info const *rli)
7174 {
7175 /*
7176 We are now in a statement until the associated query log event has
7177 been processed.
7178 */
7179 const_cast<Relay_log_info*>(rli)->set_flag(Relay_log_info::IN_STMT);
7180
7181 if (rli->deferred_events_collecting)
7182 return rli->deferred_events->add(this);
7183
7184 switch (type) {
7185 case LAST_INSERT_ID_EVENT:
7186 thd->first_successful_insert_id_in_prev_stmt= val;
7187 thd->substitute_null_with_insert_id= TRUE;
7188 break;
7189 case INSERT_ID_EVENT:
7190 thd->force_one_auto_inc_interval(val);
7191 break;
7192 }
7193 return 0;
7194 }
7195
do_update_pos(Relay_log_info * rli)7196 int Intvar_log_event::do_update_pos(Relay_log_info *rli)
7197 {
7198 rli->inc_event_relay_log_pos();
7199 return 0;
7200 }
7201
7202
7203 Log_event::enum_skip_reason
do_shall_skip(Relay_log_info * rli)7204 Intvar_log_event::do_shall_skip(Relay_log_info *rli)
7205 {
7206 /*
7207 It is a common error to set the slave skip counter to 1 instead of
7208 2 when recovering from an insert which used a auto increment,
7209 rand, or user var. Therefore, if the slave skip counter is 1, we
7210 just say that this event should be skipped by ignoring it, meaning
7211 that we do not change the value of the slave skip counter since it
7212 will be decreased by the following insert event.
7213 */
7214 return continue_group(rli);
7215 }
7216
7217 #endif
7218
7219
7220 /**************************************************************************
7221 Rand_log_event methods
7222 **************************************************************************/
7223
7224 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
pack_info(Protocol * protocol)7225 int Rand_log_event::pack_info(Protocol *protocol)
7226 {
7227 char buf1[256], *pos;
7228 pos= my_stpcpy(buf1,"rand_seed1=");
7229 pos= int10_to_str((long) seed1, pos, 10);
7230 pos= my_stpcpy(pos, ",rand_seed2=");
7231 pos= int10_to_str((long) seed2, pos, 10);
7232 protocol->store(buf1, (uint) (pos-buf1), &my_charset_bin);
7233 return 0;
7234 }
7235 #endif
7236
7237
Rand_log_event(const char * buf,const Format_description_event * description_event)7238 Rand_log_event::Rand_log_event(const char* buf,
7239 const Format_description_event* description_event)
7240 : binary_log::Rand_event(buf, description_event),
7241 Log_event(header(), footer())
7242 {
7243 is_valid_param= true;
7244 }
7245
7246
7247 #ifndef MYSQL_CLIENT
write(IO_CACHE * file)7248 bool Rand_log_event::write(IO_CACHE* file)
7249 {
7250 uchar buf[16];
7251 int8store(buf + RAND_SEED1_OFFSET, seed1);
7252 int8store(buf + RAND_SEED2_OFFSET, seed2);
7253 return (write_header(file, sizeof(buf)) ||
7254 wrapper_my_b_safe_write(file, buf, sizeof(buf)) ||
7255 write_footer(file));
7256 }
7257 #endif
7258
7259
7260 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)7261 void Rand_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
7262 {
7263 IO_CACHE *const head= &print_event_info->head_cache;
7264
7265 char llbuff[22],llbuff2[22];
7266 if (!print_event_info->short_form)
7267 {
7268 print_header(head, print_event_info, FALSE);
7269 my_b_printf(head, "\tRand\n");
7270 }
7271 my_b_printf(head, "SET @@RAND_SEED1=%s, @@RAND_SEED2=%s%s\n",
7272 llstr(seed1, llbuff),llstr(seed2, llbuff2),
7273 print_event_info->delimiter);
7274 }
7275 #endif /* MYSQL_CLIENT */
7276
7277
7278 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
do_apply_event(Relay_log_info const * rli)7279 int Rand_log_event::do_apply_event(Relay_log_info const *rli)
7280 {
7281 /*
7282 We are now in a statement until the associated query log event has
7283 been processed.
7284 */
7285 const_cast<Relay_log_info*>(rli)->set_flag(Relay_log_info::IN_STMT);
7286
7287 if (rli->deferred_events_collecting)
7288 return rli->deferred_events->add(this);
7289
7290 thd->rand.seed1= (ulong) seed1;
7291 thd->rand.seed2= (ulong) seed2;
7292 return 0;
7293 }
7294
do_update_pos(Relay_log_info * rli)7295 int Rand_log_event::do_update_pos(Relay_log_info *rli)
7296 {
7297 rli->inc_event_relay_log_pos();
7298 return 0;
7299 }
7300
7301
7302 Log_event::enum_skip_reason
do_shall_skip(Relay_log_info * rli)7303 Rand_log_event::do_shall_skip(Relay_log_info *rli)
7304 {
7305 /*
7306 It is a common error to set the slave skip counter to 1 instead of
7307 2 when recovering from an insert which used a auto increment,
7308 rand, or user var. Therefore, if the slave skip counter is 1, we
7309 just say that this event should be skipped by ignoring it, meaning
7310 that we do not change the value of the slave skip counter since it
7311 will be decreased by the following insert event.
7312 */
7313 return continue_group(rli);
7314 }
7315
7316 /**
7317 Exec deferred Int-, Rand- and User- var events prefixing
7318 a Query-log-event event.
7319
7320 @param thd THD handle
7321
7322 @return false on success, true if a failure in an event applying occurred.
7323 */
slave_execute_deferred_events(THD * thd)7324 bool slave_execute_deferred_events(THD *thd)
7325 {
7326 bool res= false;
7327 Relay_log_info *rli= thd->rli_slave;
7328
7329 assert(rli && (!rli->deferred_events_collecting || rli->deferred_events));
7330
7331 if (!rli->deferred_events_collecting || rli->deferred_events->is_empty())
7332 return res;
7333
7334 res= rli->deferred_events->execute(rli);
7335 rli->deferred_events->rewind();
7336 return res;
7337 }
7338
7339 #endif /* !MYSQL_CLIENT */
7340
7341
7342 /**************************************************************************
7343 Xid_log_event methods
7344 **************************************************************************/
7345
7346 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
pack_info(Protocol * protocol)7347 int Xid_log_event::pack_info(Protocol *protocol)
7348 {
7349 char buf[128], *pos;
7350 pos= my_stpcpy(buf, "COMMIT /* xid=");
7351 pos= longlong10_to_str(xid, pos, 10);
7352 pos= my_stpcpy(pos, " */");
7353 protocol->store(buf, (uint) (pos-buf), &my_charset_bin);
7354 return 0;
7355 }
7356 #endif
7357
7358 Xid_log_event::
Xid_log_event(const char * buf,const Format_description_event * description_event)7359 Xid_log_event(const char* buf,
7360 const Format_description_event *description_event)
7361 : binary_log::Xid_event(buf, description_event),
7362 Xid_apply_log_event(buf, description_event, header(), footer())
7363 {
7364 is_valid_param= true;
7365 }
7366
7367 #ifndef MYSQL_CLIENT
write(IO_CACHE * file)7368 bool Xid_log_event::write(IO_CACHE* file)
7369 {
7370 DBUG_EXECUTE_IF("do_not_write_xid", return 0;);
7371 return (write_header(file, sizeof(xid)) ||
7372 wrapper_my_b_safe_write(file, (uchar*) &xid, sizeof(xid)) ||
7373 write_footer(file));
7374 }
7375 #endif
7376
7377
7378 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)7379 void Xid_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
7380 {
7381 IO_CACHE *const head= &print_event_info->head_cache;
7382
7383 if (!print_event_info->short_form)
7384 {
7385 char buf[64];
7386 longlong10_to_str(xid, buf, 10);
7387
7388 print_header(head, print_event_info, FALSE);
7389 my_b_printf(head, "\tXid = %s\n", buf);
7390 }
7391 my_b_printf(head, "COMMIT%s\n", print_event_info->delimiter);
7392 }
7393 #endif /* MYSQL_CLIENT */
7394
7395
7396 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
7397 /**
7398 The methods combines few commit actions to make it useable
7399 as in the single- so multi- threaded case.
7400
7401 @param thd_arg a pointer to THD handle
7402 @return false as success and
7403 true as an error
7404 */
7405
do_commit(THD * thd_arg)7406 bool Xid_log_event::do_commit(THD *thd_arg)
7407 {
7408 DBUG_EXECUTE_IF("dbug.reached_commit",
7409 {DBUG_SET("+d,dbug.enabled_commit");});
7410 bool error= trans_commit(thd_arg); /* Automatically rolls back on error. */
7411 DBUG_EXECUTE_IF("crash_after_apply",
7412 sql_print_information("Crashing crash_after_apply.");
7413 DBUG_SUICIDE(););
7414 thd_arg->mdl_context.release_transactional_locks();
7415
7416 error |= mysql_bin_log.gtid_end_transaction(thd_arg);
7417
7418 /*
7419 The parser executing a SQLCOM_COMMIT or SQLCOM_ROLLBACK will reset the
7420 tx isolation level and access mode when the statement is finishing a
7421 transaction.
7422
7423 For replicated workload, when dealing with pure transactional workloads,
7424 there will be no QUERY(COMMIT) finishing a transaction, but a
7425 Xid_log_event instead.
7426
7427 So, if the slave applier changed the current transaction isolation level,
7428 it needs to be restored to the session default value once the current
7429 transaction has been committed.
7430 */
7431 trans_reset_one_shot_chistics(thd);
7432
7433 /*
7434 Increment the global status commit count variable
7435 */
7436 if (!error)
7437 thd_arg->status_var.com_stat[SQLCOM_COMMIT]++;
7438
7439 return error;
7440 }
7441
7442 /**
7443 Worker commits Xid transaction and in case of its transactional
7444 info table marks the current group as done in the Coordnator's
7445 Group Assigned Queue.
7446
7447 @return zero as success or non-zero as an error
7448 */
do_apply_event_worker(Slave_worker * w)7449 int Xid_apply_log_event::do_apply_event_worker(Slave_worker *w)
7450 {
7451 int error= 0;
7452 bool skipped_commit_pos= true;
7453
7454 lex_start(thd);
7455 mysql_reset_thd_for_next_command(thd);
7456 Slave_committed_queue *coordinator_gaq= w->c_rli->gaq;
7457
7458 /* For a slave Xid_log_event is COMMIT */
7459 query_logger.general_log_print(thd, COM_QUERY,
7460 "COMMIT /* implicit, from Xid_log_event */");
7461
7462 DBUG_PRINT("mts", ("do_apply group master %s %llu group relay %s %llu event %s %llu.",
7463 w->get_group_master_log_name(),
7464 w->get_group_master_log_pos(),
7465 w->get_group_relay_log_name(),
7466 w->get_group_relay_log_pos(),
7467 w->get_event_relay_log_name(),
7468 w->get_event_relay_log_pos()));
7469
7470 DBUG_EXECUTE_IF("crash_before_update_pos",
7471 sql_print_information("Crashing crash_before_update_pos.");
7472 DBUG_SUICIDE(););
7473
7474 ulong gaq_idx= mts_group_idx;
7475 Slave_job_group *ptr_group= coordinator_gaq->get_job_group(gaq_idx);
7476
7477 if (!thd->get_transaction()->xid_state()->check_in_xa(false) &&
7478 w->is_transactional())
7479 {
7480 /*
7481 Regular (not XA) transaction updates the transactional info table
7482 along with the main transaction. Otherwise, the local flag turned
7483 and given its value the info table is updated after do_commit.
7484 todo: the flag won't be need upon the full xa crash-safety bug76233
7485 gets fixed.
7486 */
7487 skipped_commit_pos= false;
7488 if ((error= w->commit_positions(this, ptr_group,
7489 w->is_transactional())))
7490 goto err;
7491 }
7492
7493 DBUG_PRINT("mts", ("do_apply group master %s %llu group relay %s %llu event %s %llu.",
7494 w->get_group_master_log_name(),
7495 w->get_group_master_log_pos(),
7496 w->get_group_relay_log_name(),
7497 w->get_group_relay_log_pos(),
7498 w->get_event_relay_log_name(),
7499 w->get_event_relay_log_pos()));
7500
7501 DBUG_EXECUTE_IF("crash_after_update_pos_before_apply",
7502 sql_print_information("Crashing crash_after_update_pos_before_apply.");
7503 DBUG_SUICIDE(););
7504
7505 error= do_commit(thd);
7506 if (error)
7507 {
7508 if (!skipped_commit_pos)
7509 w->rollback_positions(ptr_group);
7510 }
7511 else if (skipped_commit_pos)
7512 error= w->commit_positions(this, ptr_group,
7513 w->is_transactional());
7514 err:
7515 return error;
7516 }
7517
do_apply_event(Relay_log_info const * rli)7518 int Xid_apply_log_event::do_apply_event(Relay_log_info const *rli)
7519 {
7520 DBUG_ENTER("Xid_log_event::do_apply_event");
7521 int error= 0;
7522 char saved_group_master_log_name[FN_REFLEN];
7523 char saved_group_relay_log_name[FN_REFLEN];
7524 volatile my_off_t saved_group_master_log_pos;
7525 volatile my_off_t saved_group_relay_log_pos;
7526
7527 char new_group_master_log_name[FN_REFLEN];
7528 char new_group_relay_log_name[FN_REFLEN];
7529 volatile my_off_t new_group_master_log_pos;
7530 volatile my_off_t new_group_relay_log_pos;
7531
7532 lex_start(thd);
7533 mysql_reset_thd_for_next_command(thd);
7534 /*
7535 Anonymous GTID ownership may be released here if the last
7536 statement before XID updated a non-transactional table and was
7537 written to the binary log as a separate transaction (either
7538 because binlog_format=row or because
7539 binlog_direct_non_transactional_updates=1). So we need to
7540 re-acquire anonymous ownership.
7541 */
7542 gtid_reacquire_ownership_if_anonymous(thd);
7543 Relay_log_info *rli_ptr= const_cast<Relay_log_info *>(rli);
7544 bool binlog_prot_acquired= false;
7545
7546 /* For a slave Xid_log_event is COMMIT */
7547 query_logger.general_log_print(thd, COM_QUERY,
7548 "COMMIT /* implicit, from Xid_log_event */");
7549
7550 if (!thd->backup_binlog_lock.is_acquired())
7551 {
7552 const ulong timeout= thd->variables.lock_wait_timeout;
7553
7554 DBUG_PRINT("debug", ("Acquiring binlog protection lock"));
7555 mysql_mutex_assert_not_owner(&rli->data_lock);
7556 if (thd->backup_binlog_lock.acquire_protection(thd, MDL_EXPLICIT,
7557 timeout))
7558 DBUG_RETURN(1);
7559
7560 binlog_prot_acquired= true;
7561 }
7562
7563 mysql_mutex_lock(&rli_ptr->data_lock);
7564
7565 /*
7566 Save the rli positions. We need them to temporarily reset the positions
7567 just before the commit.
7568 */
7569 strmake(saved_group_master_log_name, rli_ptr->get_group_master_log_name(),
7570 FN_REFLEN - 1);
7571 saved_group_master_log_pos= rli_ptr->get_group_master_log_pos();
7572 strmake(saved_group_relay_log_name, rli_ptr->get_group_relay_log_name(),
7573 FN_REFLEN - 1);
7574 saved_group_relay_log_pos= rli_ptr->get_group_relay_log_pos();
7575
7576 DBUG_PRINT("info", ("do_apply group master %s %llu group relay %s %llu event %s %llu\n",
7577 rli_ptr->get_group_master_log_name(),
7578 rli_ptr->get_group_master_log_pos(),
7579 rli_ptr->get_group_relay_log_name(),
7580 rli_ptr->get_group_relay_log_pos(),
7581 rli_ptr->get_event_relay_log_name(),
7582 rli_ptr->get_event_relay_log_pos()));
7583
7584 DBUG_EXECUTE_IF("crash_before_update_pos",
7585 sql_print_information("Crashing crash_before_update_pos.");
7586 DBUG_SUICIDE(););
7587
7588 /*
7589 We need to update the positions in here to make it transactional.
7590 */
7591 rli_ptr->inc_event_relay_log_pos();
7592 rli_ptr->set_group_relay_log_pos(rli_ptr->get_event_relay_log_pos());
7593 rli_ptr->set_group_relay_log_name(rli_ptr->get_event_relay_log_name());
7594
7595 rli_ptr->notify_group_relay_log_name_update();
7596
7597 if (common_header->log_pos) // 3.23 binlogs don't have log_posx
7598 rli_ptr->set_group_master_log_pos(common_header->log_pos);
7599
7600 const bool already_logged_transaction= is_already_logged_transaction(thd);
7601 /*
7602 rli repository being transactional means replication is crash safe.
7603 Positions are written into transactional tables ahead of commit and the
7604 changes are made permanent during commit.
7605 XA transactional does not actually commit so has to defer its flush_info().
7606 */
7607 if (!thd->get_transaction()->xid_state()->check_in_xa(false) &&
7608 rli_ptr->is_transactional() && !already_logged_transaction)
7609 {
7610 if ((error= rli_ptr->flush_info(true)))
7611 goto err;
7612 }
7613
7614 DBUG_PRINT("info", ("do_apply group master %s %llu group relay %s %llu event %s %llu\n",
7615 rli_ptr->get_group_master_log_name(),
7616 rli_ptr->get_group_master_log_pos(),
7617 rli_ptr->get_group_relay_log_name(),
7618 rli_ptr->get_group_relay_log_pos(),
7619 rli_ptr->get_event_relay_log_name(),
7620 rli_ptr->get_event_relay_log_pos()));
7621
7622 DBUG_EXECUTE_IF("crash_after_update_pos_before_apply",
7623 sql_print_information("Crashing crash_after_update_pos_before_apply.");
7624 DBUG_SUICIDE(););
7625
7626 /**
7627 Commit operation expects the global transaction state variable 'xa_state'to
7628 be set to 'XA_NOTR'. In order to simulate commit failure we set
7629 the 'xa_state' to 'XA_IDLE' so that the commit reports 'ER_XAER_RMFAIL'
7630 error.
7631 */
7632 DBUG_EXECUTE_IF("simulate_commit_failure",
7633 {
7634 thd->get_transaction()->xid_state()->set_state(
7635 XID_STATE::XA_IDLE);
7636 });
7637
7638 /*
7639 Save the new rli positions. These positions will be set back to group*
7640 positions on successful completion of the commit operation.
7641 */
7642 strmake(new_group_master_log_name, rli_ptr->get_group_master_log_name(),
7643 FN_REFLEN - 1);
7644 new_group_master_log_pos= rli_ptr->get_group_master_log_pos();
7645 strmake(new_group_relay_log_name, rli_ptr->get_group_relay_log_name(),
7646 FN_REFLEN - 1);
7647 new_group_relay_log_pos= rli_ptr->get_group_relay_log_pos();
7648 /*
7649 Rollback positions in memory just before commit. Position values will be
7650 reset to their new values only on successful commit operation.
7651 */
7652 rli_ptr->set_group_master_log_name(saved_group_master_log_name);
7653 rli_ptr->notify_group_master_log_name_update();
7654 rli_ptr->set_group_master_log_pos(saved_group_master_log_pos);
7655 rli_ptr->set_group_relay_log_name(saved_group_relay_log_name);
7656 rli_ptr->notify_group_relay_log_name_update();
7657 rli_ptr->set_group_relay_log_pos(saved_group_relay_log_pos);
7658
7659 DBUG_PRINT("info", ("Rolling back to group master %s %llu group relay %s"
7660 " %llu\n", rli_ptr->get_group_master_log_name(),
7661 rli_ptr->get_group_master_log_pos(),
7662 rli_ptr->get_group_relay_log_name(),
7663 rli_ptr->get_group_relay_log_pos()));
7664 mysql_mutex_unlock(&rli_ptr->data_lock);
7665 error= do_commit(thd);
7666 mysql_mutex_lock(&rli_ptr->data_lock);
7667 if (error)
7668 {
7669 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
7670 "Error in Xid_log_event: Commit could not be completed, '%s'",
7671 thd->get_stmt_da()->message_text());
7672 }
7673 else
7674 {
7675 DBUG_EXECUTE_IF("crash_after_commit_before_update_pos",
7676 sql_print_information("Crashing "
7677 "crash_after_commit_before_update_pos.");
7678 DBUG_SUICIDE(););
7679 /* Update positions on successful commit */
7680 rli_ptr->set_group_master_log_name(new_group_master_log_name);
7681 rli_ptr->notify_group_master_log_name_update();
7682 rli_ptr->set_group_master_log_pos(new_group_master_log_pos);
7683 rli_ptr->set_group_relay_log_name(new_group_relay_log_name);
7684 rli_ptr->notify_group_relay_log_name_update();
7685 rli_ptr->set_group_relay_log_pos(new_group_relay_log_pos);
7686
7687 DBUG_PRINT("info", ("Updating positions on succesful commit to group master"
7688 " %s %llu group relay %s %llu\n",
7689 rli_ptr->get_group_master_log_name(),
7690 rli_ptr->get_group_master_log_pos(),
7691 rli_ptr->get_group_relay_log_name(),
7692 rli_ptr->get_group_relay_log_pos()));
7693
7694 /*
7695 For transactional repository the positions are flushed ahead of commit.
7696 Where as for non transactional rli repository the positions are flushed
7697 only on succesful commit.
7698 */
7699 if (!rli_ptr->is_transactional() && !already_logged_transaction)
7700 rli_ptr->flush_info(false);
7701 }
7702 err:
7703 mysql_cond_broadcast(&rli_ptr->data_cond);
7704 mysql_mutex_unlock(&rli_ptr->data_lock);
7705
7706 if (binlog_prot_acquired)
7707 {
7708 DBUG_PRINT("debug", ("Releasing binlog protection lock"));
7709 thd->backup_binlog_lock.release_protection(thd);
7710 }
7711
7712 DBUG_RETURN(error);
7713 }
7714
7715 Log_event::enum_skip_reason
do_shall_skip(Relay_log_info * rli)7716 Xid_apply_log_event::do_shall_skip(Relay_log_info *rli)
7717 {
7718 DBUG_ENTER("Xid_log_event::do_shall_skip");
7719 if (rli->slave_skip_counter > 0) {
7720 thd->variables.option_bits&= ~OPTION_BEGIN;
7721 DBUG_RETURN(Log_event::EVENT_SKIP_COUNT);
7722 }
7723 DBUG_RETURN(Log_event::do_shall_skip(rli));
7724 }
7725 #endif /* !MYSQL_CLIENT */
7726
7727 /**************************************************************************
7728 XA_prepare_log_event methods
7729 **************************************************************************/
7730
7731 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
pack_info(Protocol * protocol)7732 int XA_prepare_log_event::pack_info(Protocol *protocol)
7733 {
7734 char buf[ser_buf_size];
7735 char query[sizeof("XA COMMIT ONE PHASE") + 1 + sizeof(buf)];
7736
7737 /* RHS of the following assert is unknown to client sources */
7738 compile_time_assert(ser_buf_size == XID::ser_buf_size);
7739 serialize_xid(buf, my_xid.formatID, my_xid.gtrid_length,
7740 my_xid.bqual_length, my_xid.data);
7741 sprintf(query,
7742 (one_phase ? "XA COMMIT %s ONE PHASE" : "XA PREPARE %s"),
7743 buf);
7744
7745 protocol->store(query, strlen(query), &my_charset_bin);
7746 return 0;
7747 }
7748 #endif
7749
7750
7751 #ifndef MYSQL_CLIENT
write(IO_CACHE * file)7752 bool XA_prepare_log_event::write(IO_CACHE* file)
7753 {
7754 uint8 one_byte= one_phase;
7755 uchar buf_f[4];
7756 uchar buf_g[4];
7757 uchar buf_b[4];
7758 int4store(buf_f, static_cast<XID*>(xid)->get_format_id());
7759 int4store(buf_g, static_cast<XID*>(xid)->get_gtrid_length());
7760 int4store(buf_b, static_cast<XID*>(xid)->get_bqual_length());
7761
7762 assert(xid_bufs_size == sizeof(buf_f) + sizeof(buf_g) + sizeof(buf_b));
7763
7764 return write_header(file, sizeof(one_byte) + xid_bufs_size +
7765 static_cast<XID*>(xid)->get_gtrid_length() +
7766 static_cast<XID*>(xid)->get_bqual_length())
7767 ||
7768 wrapper_my_b_safe_write(file, &one_byte, sizeof(one_byte)) ||
7769 wrapper_my_b_safe_write(file, buf_f, sizeof(buf_f)) ||
7770 wrapper_my_b_safe_write(file, buf_g, sizeof(buf_g)) ||
7771 wrapper_my_b_safe_write(file, buf_b, sizeof(buf_b)) ||
7772 wrapper_my_b_safe_write(file, (uchar*) static_cast<XID*>(xid)->get_data(),
7773 static_cast<XID*>(xid)->get_gtrid_length() +
7774 static_cast<XID*>(xid)->get_bqual_length()) ||
7775 write_footer(file);
7776 }
7777 #endif
7778
7779
7780 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)7781 void XA_prepare_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
7782 {
7783 IO_CACHE *const head= &print_event_info->head_cache;
7784 char buf[ser_buf_size];
7785
7786 print_header(head, print_event_info, FALSE);
7787 serialize_xid(buf, my_xid.formatID, my_xid.gtrid_length,
7788 my_xid.bqual_length, my_xid.data);
7789 my_b_printf(head, "\tXA PREPARE %s\n", buf);
7790 my_b_printf(head, one_phase ? "XA COMMIT %s ONE PHASE\n%s\n" : "XA PREPARE %s\n%s\n",
7791 buf, print_event_info->delimiter);
7792 }
7793 #endif /* MYSQL_CLIENT */
7794
7795 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
7796
7797 /**
7798 Differs from Xid_log_event::do_commit in that it carries out
7799 XA prepare (not the commit).
7800 It also can commit on one phase when the event's member @c one_phase
7801 set to true.
7802
7803 @param thd a pointer to THD handle
7804 @return false as success and
7805 true as an error
7806 */
7807
do_commit(THD * thd)7808 bool XA_prepare_log_event::do_commit(THD *thd)
7809 {
7810 bool error= false;
7811 xid_t xid;
7812
7813 enum_gtid_statement_status state= gtid_pre_statement_checks(thd);
7814 if (state == GTID_STATEMENT_EXECUTE)
7815 {
7816 if (gtid_pre_statement_post_implicit_commit_checks(thd))
7817 state= GTID_STATEMENT_CANCEL;
7818 }
7819 if (state == GTID_STATEMENT_CANCEL)
7820 {
7821 uint error= thd->get_stmt_da()->mysql_errno();
7822 assert(error != 0);
7823 thd->rli_slave->report(ERROR_LEVEL, error,
7824 "Error executing XA PREPARE event: '%s'",
7825 thd->get_stmt_da()->message_text());
7826 thd->is_slave_error= 1;
7827 return true;
7828 }
7829 else if (state == GTID_STATEMENT_SKIP)
7830 return false;
7831
7832 xid.set(my_xid.formatID,
7833 my_xid.data, my_xid.gtrid_length,
7834 my_xid.data + my_xid.gtrid_length, my_xid.bqual_length);
7835 if (!one_phase)
7836 {
7837 /*
7838 This is XA-prepare branch.
7839 */
7840 thd->lex->sql_command= SQLCOM_XA_PREPARE;
7841 thd->lex->m_sql_cmd= new Sql_cmd_xa_prepare(&xid);
7842 error= thd->lex->m_sql_cmd->execute(thd);
7843 }
7844 else
7845 {
7846 thd->lex->sql_command= SQLCOM_XA_COMMIT;
7847 thd->lex->m_sql_cmd= new Sql_cmd_xa_commit(&xid, XA_ONE_PHASE);
7848 error= thd->lex->m_sql_cmd->execute(thd);
7849 }
7850
7851 if (!error)
7852 error = mysql_bin_log.gtid_end_transaction(thd);
7853
7854 return error;
7855 }
7856 #endif
7857
7858
7859 /**************************************************************************
7860 User_var_log_event methods
7861 **************************************************************************/
7862
7863 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
pack_info(Protocol * protocol)7864 int User_var_log_event::pack_info(Protocol* protocol)
7865 {
7866 char *buf= 0;
7867 char quoted_id[1 + FN_REFLEN * 2 + 2];// quoted identifier
7868 size_t id_len= my_strmov_quoted_identifier(this->thd, quoted_id, name, name_len);
7869 quoted_id[id_len]= '\0';
7870 size_t val_offset= 2 + id_len;
7871 size_t event_len= val_offset;
7872
7873 if (is_null)
7874 {
7875 if (!(buf= (char*) my_malloc(key_memory_log_event,
7876 val_offset + 5, MYF(MY_WME))))
7877 return 1;
7878 my_stpcpy(buf + val_offset, "NULL");
7879 event_len= val_offset + 4;
7880 }
7881 else
7882 {
7883 switch (type) {
7884 case REAL_TYPE:
7885 double real_val;
7886 float8get(&real_val, val);
7887 if (!(buf= (char*) my_malloc(key_memory_log_event,
7888 val_offset + MY_GCVT_MAX_FIELD_WIDTH + 1,
7889 MYF(MY_WME))))
7890 return 1;
7891 event_len+= my_gcvt(real_val, MY_GCVT_ARG_DOUBLE, MY_GCVT_MAX_FIELD_WIDTH,
7892 buf + val_offset, NULL);
7893 break;
7894 case INT_TYPE:
7895 if (!(buf= (char*) my_malloc(key_memory_log_event,
7896 val_offset + 22, MYF(MY_WME))))
7897 return 1;
7898 event_len= longlong10_to_str(uint8korr(val), buf + val_offset,
7899 ((flags & User_var_log_event::UNSIGNED_F) ?
7900 10 : -10))-buf;
7901 break;
7902 case DECIMAL_TYPE:
7903 {
7904 if (!(buf= (char*) my_malloc(key_memory_log_event,
7905 val_offset + DECIMAL_MAX_STR_LENGTH + 1,
7906 MYF(MY_WME))))
7907 return 1;
7908 String str(buf+val_offset, DECIMAL_MAX_STR_LENGTH + 1, &my_charset_bin);
7909 my_decimal dec;
7910 binary2my_decimal(E_DEC_FATAL_ERROR, (uchar*) (val+2), &dec, val[0],
7911 val[1]);
7912 my_decimal2string(E_DEC_FATAL_ERROR, &dec, 0, 0, 0, &str);
7913 event_len= str.length() + val_offset;
7914 break;
7915 }
7916 case STRING_TYPE:
7917 /* 15 is for 'COLLATE' and other chars */
7918 buf= (char*) my_malloc(key_memory_log_event,
7919 event_len+val_len*2+1+2*MY_CS_NAME_SIZE+15,
7920 MYF(MY_WME));
7921 CHARSET_INFO *cs;
7922 if (!buf)
7923 return 1;
7924 if (!(cs= get_charset(charset_number, MYF(0))))
7925 {
7926 my_stpcpy(buf+val_offset, "???");
7927 event_len+= 3;
7928 }
7929 else
7930 {
7931 char *p= strxmov(buf + val_offset, "_", cs->csname, " ", NullS);
7932 p= str_to_hex(p, val, val_len);
7933 p= strxmov(p, " COLLATE ", cs->name, NullS);
7934 event_len= p-buf;
7935 }
7936 break;
7937 case ROW_TYPE:
7938 default:
7939 assert(1);
7940 return 1;
7941 }
7942 }
7943 buf[0]= '@';
7944 memcpy(buf + 1, quoted_id, id_len);
7945 buf[1 + id_len]= '=';
7946 protocol->store(buf, event_len, &my_charset_bin);
7947 my_free(buf);
7948 return 0;
7949 }
7950 #endif /* !MYSQL_CLIENT */
7951
7952
7953 User_var_log_event::
User_var_log_event(const char * buf,uint event_len,const Format_description_event * description_event)7954 User_var_log_event(const char* buf, uint event_len,
7955 const Format_description_event* description_event)
7956 : binary_log::User_var_event(buf, event_len, description_event),
7957 Log_event(header(), footer())
7958 #ifndef MYSQL_CLIENT
7959 ,deferred(false), query_id(0)
7960 #endif
7961 {
7962 if (name != 0)
7963 is_valid_param= true;
7964 }
7965
7966
7967 #ifndef MYSQL_CLIENT
write(IO_CACHE * file)7968 bool User_var_log_event::write(IO_CACHE* file)
7969 {
7970 char buf[UV_NAME_LEN_SIZE];
7971 char buf1[UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
7972 UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE];
7973 uchar buf2[MY_MAX(8, DECIMAL_MAX_FIELD_SIZE + 2)], *pos= buf2;
7974 uint unsigned_len= 0;
7975 uint buf1_length;
7976 ulong event_length;
7977
7978 int4store(buf, name_len);
7979
7980 if ((buf1[0]= is_null))
7981 {
7982 buf1_length= 1;
7983 val_len= 0; // Length of 'pos'
7984 }
7985 else
7986 {
7987 buf1[1]= type;
7988 int4store(buf1 + 2, charset_number);
7989
7990 switch (type) {
7991 case REAL_TYPE:
7992 float8store(buf2, *(double*) val);
7993 break;
7994 case INT_TYPE:
7995 int8store(buf2, *(longlong*) val);
7996 unsigned_len= 1;
7997 break;
7998 case DECIMAL_TYPE:
7999 {
8000 my_decimal *dec= (my_decimal *)val;
8001 dec->sanity_check();
8002 buf2[0]= (char)(dec->intg + dec->frac);
8003 buf2[1]= (char)dec->frac;
8004 decimal2bin(dec, buf2+2, buf2[0], buf2[1]);
8005 val_len= decimal_bin_size(buf2[0], buf2[1]) + 2;
8006 break;
8007 }
8008 case STRING_TYPE:
8009 pos= (uchar*) val;
8010 break;
8011 case ROW_TYPE:
8012 default:
8013 assert(1);
8014 return 0;
8015 }
8016 int4store(buf1 + 2 + UV_CHARSET_NUMBER_SIZE, val_len);
8017 buf1_length= 10;
8018 }
8019
8020 /* Length of the whole event */
8021 event_length= sizeof(buf)+ name_len + buf1_length + val_len + unsigned_len;
8022
8023 return (write_header(file, event_length) ||
8024 wrapper_my_b_safe_write(file, (uchar*) buf, sizeof(buf)) ||
8025 wrapper_my_b_safe_write(file, (uchar*) name, name_len) ||
8026 wrapper_my_b_safe_write(file, (uchar*) buf1, buf1_length) ||
8027 wrapper_my_b_safe_write(file, pos, val_len) ||
8028 wrapper_my_b_safe_write(file, &flags, unsigned_len) ||
8029 write_footer(file));
8030 }
8031 #endif
8032
8033
8034 /*
8035 User_var_log_event::print()
8036 */
8037
8038 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)8039 void User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
8040 {
8041 IO_CACHE *const head= &print_event_info->head_cache;
8042 char quoted_id[1 + NAME_LEN * 2 + 2];// quoted length of the identifier
8043 char name_id[NAME_LEN];
8044 size_t quoted_len= 0;
8045
8046 if (!print_event_info->short_form)
8047 {
8048 print_header(head, print_event_info, FALSE);
8049 my_b_printf(head, "\tUser_var\n");
8050 }
8051 my_stpcpy(name_id, name);
8052 name_id[name_len]= '\0';
8053 my_b_printf(head, "SET @");
8054 quoted_len= my_strmov_quoted_identifier((char *) quoted_id,
8055 (const char *) name_id);
8056 quoted_id[quoted_len]= '\0';
8057 MY_ATTRIBUTE((unused)) int write_res=
8058 my_b_write(head, (uchar*) quoted_id, quoted_len);
8059 assert(write_res == 0);
8060
8061 if (is_null)
8062 {
8063 my_b_printf(head, ":=NULL%s\n", print_event_info->delimiter);
8064 }
8065 else
8066 {
8067 switch (type) {
8068 case REAL_TYPE:
8069 double real_val;
8070 char real_buf[FMT_G_BUFSIZE(14)];
8071 float8get(&real_val, val);
8072 sprintf(real_buf, "%.14g", real_val);
8073 my_b_printf(head, ":=%s%s\n", real_buf, print_event_info->delimiter);
8074 break;
8075 case INT_TYPE:
8076 char int_buf[22];
8077 longlong10_to_str(uint8korr(val), int_buf,
8078 ((flags & User_var_log_event::UNSIGNED_F) ? 10 : -10));
8079 my_b_printf(head, ":=%s%s\n", int_buf, print_event_info->delimiter);
8080 break;
8081 case DECIMAL_TYPE:
8082 {
8083 char str_buf[200];
8084 int str_len= sizeof(str_buf) - 1;
8085 int precision= (int)val[0];
8086 int scale= (int)val[1];
8087 decimal_digit_t dec_buf[10];
8088 decimal_t dec;
8089 dec.len= 10;
8090 dec.buf= dec_buf;
8091
8092 bin2decimal((uchar*) val+2, &dec, precision, scale);
8093 decimal2string(&dec, str_buf, &str_len, 0, 0, 0);
8094 str_buf[str_len]= 0;
8095 my_b_printf(head, ":=%s%s\n", str_buf, print_event_info->delimiter);
8096 break;
8097 }
8098 case STRING_TYPE:
8099 {
8100 /*
8101 Let's express the string in hex. That's the most robust way. If we
8102 print it in character form instead, we need to escape it with
8103 character_set_client which we don't know (we will know it in 5.0, but
8104 in 4.1 we don't know it easily when we are printing
8105 User_var_log_event). Explanation why we would need to bother with
8106 character_set_client (quoting Bar):
8107 > Note, the parser doesn't switch to another unescaping mode after
8108 > it has met a character set introducer.
8109 > For example, if an SJIS client says something like:
8110 > SET @a= _ucs2 \0a\0b'
8111 > the string constant is still unescaped according to SJIS, not
8112 > according to UCS2.
8113 */
8114 char *hex_str;
8115 CHARSET_INFO *cs;
8116
8117 hex_str= (char *)my_malloc(key_memory_log_event,
8118 2*val_len+1+2,MYF(MY_WME)); // 2 hex digits / byte
8119 if (!hex_str)
8120 return;
8121 str_to_hex(hex_str, val, val_len);
8122 /*
8123 For proper behaviour when mysqlbinlog|mysql, we need to explicitely
8124 specify the variable's collation. It will however cause problems when
8125 people want to mysqlbinlog|mysql into another server not supporting the
8126 character set. But there's not much to do about this and it's unlikely.
8127 */
8128 if (!(cs= get_charset(charset_number, MYF(0))))
8129 /*
8130 Generate an unusable command (=> syntax error) is probably the best
8131 thing we can do here.
8132 */
8133 my_b_printf(head, ":=???%s\n", print_event_info->delimiter);
8134 else
8135 my_b_printf(head, ":=_%s %s COLLATE `%s`%s\n",
8136 cs->csname, hex_str, cs->name,
8137 print_event_info->delimiter);
8138 my_free(hex_str);
8139 }
8140 break;
8141 case ROW_TYPE:
8142 default:
8143 assert(1);
8144 return;
8145 }
8146 }
8147 }
8148 #endif
8149
8150
8151 /*
8152 User_var_log_event::do_apply_event()
8153 */
8154
8155 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
do_apply_event(Relay_log_info const * rli)8156 int User_var_log_event::do_apply_event(Relay_log_info const *rli)
8157 {
8158 DBUG_ENTER("User_var_log_event::do_apply_event");
8159 Item *it= 0;
8160 CHARSET_INFO *charset;
8161 query_id_t sav_query_id= 0; /* memorize orig id when deferred applying */
8162
8163 if (rli->deferred_events_collecting)
8164 {
8165 set_deferred(current_thd->query_id);
8166 int ret= rli->deferred_events->add(this);
8167 DBUG_RETURN(ret);
8168 }
8169 else if (is_deferred())
8170 {
8171 sav_query_id= current_thd->query_id;
8172 current_thd->query_id= query_id; /* recreating original time context */
8173 }
8174
8175 if (!(charset= get_charset(charset_number, MYF(MY_WME))))
8176 {
8177 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
8178 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
8179 "Invalid character set for User var event");
8180 DBUG_RETURN(1);
8181 }
8182 double real_val;
8183 longlong int_val;
8184
8185 /*
8186 We are now in a statement until the associated query log event has
8187 been processed.
8188 */
8189 const_cast<Relay_log_info*>(rli)->set_flag(Relay_log_info::IN_STMT);
8190
8191 if (is_null)
8192 {
8193 it= new Item_null();
8194 }
8195 else
8196 {
8197 switch (type) {
8198 case REAL_TYPE:
8199 if (val_len != 8)
8200 {
8201 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
8202 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
8203 "Invalid variable length at User var event");
8204 DBUG_RETURN(1);
8205 }
8206 float8get(&real_val, val);
8207 it= new Item_float(real_val, 0);
8208 val= (char*) &real_val; // Pointer to value in native format
8209 val_len= 8;
8210 break;
8211 case INT_TYPE:
8212 if (val_len != 8)
8213 {
8214 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
8215 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
8216 "Invalid variable length at User var event");
8217 DBUG_RETURN(1);
8218 }
8219 int_val= (longlong) uint8korr(val);
8220 it= new Item_int(int_val);
8221 val= (char*) &int_val; // Pointer to value in native format
8222 val_len= 8;
8223 break;
8224 case DECIMAL_TYPE:
8225 {
8226 if (val_len < 3)
8227 {
8228 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
8229 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
8230 "Invalid variable length at User var event");
8231 DBUG_RETURN(1);
8232 }
8233 Item_decimal *dec= new Item_decimal((uchar*) val+2, val[0], val[1]);
8234 it= dec;
8235 val= (char *)dec->val_decimal(NULL);
8236 val_len= sizeof(my_decimal);
8237 break;
8238 }
8239 case STRING_TYPE:
8240 it= new Item_string(val, val_len, charset);
8241 break;
8242 case ROW_TYPE:
8243 default:
8244 assert(1);
8245 DBUG_RETURN(0);
8246 }
8247 }
8248 Item_func_set_user_var *e=
8249 new Item_func_set_user_var(Name_string(name, name_len, false), it, false);
8250 /*
8251 Item_func_set_user_var can't substitute something else on its place =>
8252 0 can be passed as last argument (reference on item)
8253
8254 Fix_fields() can fail, in which case a call of update_hash() might
8255 crash the server, so if fix fields fails, we just return with an
8256 error.
8257 */
8258 if (e->fix_fields(thd, 0))
8259 DBUG_RETURN(1);
8260
8261 /*
8262 A variable can just be considered as a table with
8263 a single record and with a single column. Thus, like
8264 a column value, it could always have IMPLICIT derivation.
8265 */
8266 e->update_hash(val, val_len, (Item_result)type, charset, DERIVATION_IMPLICIT,
8267 (flags & binary_log::User_var_event::UNSIGNED_F));
8268 if (!is_deferred())
8269 free_root(thd->mem_root, 0);
8270 else
8271 current_thd->query_id= sav_query_id; /* restore current query's context */
8272
8273 DBUG_RETURN(0);
8274 }
8275
do_update_pos(Relay_log_info * rli)8276 int User_var_log_event::do_update_pos(Relay_log_info *rli)
8277 {
8278 rli->inc_event_relay_log_pos();
8279 return 0;
8280 }
8281
8282 Log_event::enum_skip_reason
do_shall_skip(Relay_log_info * rli)8283 User_var_log_event::do_shall_skip(Relay_log_info *rli)
8284 {
8285 /*
8286 It is a common error to set the slave skip counter to 1 instead
8287 of 2 when recovering from an insert which used a auto increment,
8288 rand, or user var. Therefore, if the slave skip counter is 1, we
8289 just say that this event should be skipped by ignoring it, meaning
8290 that we do not change the value of the slave skip counter since it
8291 will be decreased by the following insert event.
8292 */
8293 return continue_group(rli);
8294 }
8295 #endif /* !MYSQL_CLIENT */
8296
8297
8298 /**************************************************************************
8299 Unknown_log_event methods
8300 **************************************************************************/
8301
8302 #ifdef HAVE_REPLICATION
8303 #ifdef MYSQL_CLIENT
print(FILE * file_arg,PRINT_EVENT_INFO * print_event_info)8304 void Unknown_log_event::print(FILE* file_arg, PRINT_EVENT_INFO* print_event_info)
8305 {
8306 if (print_event_info->short_form)
8307 return;
8308
8309 if (what != ENCRYPTED)
8310 {
8311 print_header(&print_event_info->head_cache, print_event_info, FALSE);
8312 my_b_printf(&print_event_info->head_cache, "\n# %s", "Unknown event\n");
8313 }
8314 else
8315 my_b_printf(&print_event_info->head_cache, "\n# %s", "Encrypted event\n");
8316 }
8317 #endif
8318
8319 /**************************************************************************
8320 Stop_log_event methods
8321 **************************************************************************/
8322
8323 /*
8324 Stop_log_event::print()
8325 */
8326
8327 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)8328 void Stop_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
8329 {
8330 if (print_event_info->short_form)
8331 return;
8332
8333 print_header(&print_event_info->head_cache, print_event_info, FALSE);
8334 my_b_printf(&print_event_info->head_cache, "\tStop\n");
8335 }
8336 #endif /* MYSQL_CLIENT */
8337
8338
8339 #ifndef MYSQL_CLIENT
8340 /*
8341 The master stopped. We used to clean up all temporary tables but
8342 this is useless as, as the master has shut down properly, it has
8343 written all DROP TEMPORARY TABLE (prepared statements' deletion is
8344 TODO only when we binlog prep stmts). We used to clean up
8345 slave_load_tmpdir, but this is useless as it has been cleared at the
8346 end of LOAD DATA INFILE. So we have nothing to do here. The place
8347 were we must do this cleaning is in
8348 Start_log_event_v3::do_apply_event(), not here. Because if we come
8349 here, the master was sane.
8350
8351 This must only be called from the Slave SQL thread, since it calls
8352 flush_relay_log_info().
8353 */
do_update_pos(Relay_log_info * rli)8354 int Stop_log_event::do_update_pos(Relay_log_info *rli)
8355 {
8356 int error_inc= 0;
8357 int error_flush= 0;
8358 /*
8359 We do not want to update master_log pos because we get a rotate event
8360 before stop, so by now group_master_log_name is set to the next log.
8361 If we updated it, we will have incorrect master coordinates and this
8362 could give false triggers in MASTER_POS_WAIT() that we have reached
8363 the target position when in fact we have not.
8364 The group position is always unchanged in MTS mode because the event
8365 is never executed so can't be scheduled to a Worker.
8366 */
8367 if ((thd->variables.option_bits & OPTION_BEGIN) || rli->is_parallel_exec())
8368 rli->inc_event_relay_log_pos();
8369 else
8370 {
8371 error_inc= rli->inc_group_relay_log_pos(0, true/*need_data_lock=true*/);
8372 error_flush= rli->flush_info(TRUE);
8373 }
8374 return (error_inc || error_flush);
8375 }
8376
8377 #endif /* !MYSQL_CLIENT */
8378 #endif /* HAVE_REPLICATION */
8379
8380
8381 /**************************************************************************
8382 Create_file_log_event methods
8383 **************************************************************************/
8384
8385 #ifndef MYSQL_CLIENT
8386 /*
8387 Create_file_log_event::write_data_body()
8388 */
8389
write_data_body(IO_CACHE * file)8390 bool Create_file_log_event::write_data_body(IO_CACHE* file)
8391 {
8392 bool res;
8393 if ((res= Load_log_event::write_data_body(file)) || fake_base)
8394 return res;
8395 return (event_encrypter.encrypt_and_write(file, (uchar*) "", 1) ||
8396 event_encrypter.encrypt_and_write(file, block, block_len));
8397 }
8398
8399
8400 /*
8401 Create_file_log_event::write_data_header()
8402 */
8403
write_data_header(IO_CACHE * file)8404 bool Create_file_log_event::write_data_header(IO_CACHE* file)
8405 {
8406 bool res;
8407 uchar buf[Binary_log_event::CREATE_FILE_HEADER_LEN];
8408 if ((res= Load_log_event::write_data_header(file)) || fake_base)
8409 return res;
8410 int4store(buf + CF_FILE_ID_OFFSET, file_id);
8411 return event_encrypter.encrypt_and_write(file, buf, Binary_log_event::CREATE_FILE_HEADER_LEN) != 0;
8412 }
8413
8414
8415 /*
8416 Create_file_log_event::write_base()
8417 */
8418
write_base(IO_CACHE * file)8419 bool Create_file_log_event::write_base(IO_CACHE* file)
8420 {
8421 bool res;
8422 fake_base= 1; // pretend we are Load event
8423 common_header->type_code= Load_log_event::get_type_code();
8424 DBUG_EXECUTE_IF("simulate_cache_write_failure",
8425 {
8426 res= TRUE;
8427 my_error(ER_UNKNOWN_ERROR, MYF(0));
8428 return res;
8429 });
8430 res= write(file);
8431 fake_base= 0;
8432 common_header->type_code= binary_log::CREATE_FILE_EVENT;
8433 return res;
8434 }
8435
8436 #endif /* !MYSQL_CLIENT */
8437
8438 /*
8439 Create_file_log_event ctor
8440 */
8441
8442 Create_file_log_event::
Create_file_log_event(const char * buf,uint len,const Format_description_event * description_event)8443 Create_file_log_event(const char* buf, uint len,
8444 const Format_description_event* description_event)
8445 : binary_log::Load_event(buf, 0, description_event),
8446 Load_log_event(buf,0,description_event),
8447 binary_log::Create_file_event(buf, len, description_event)
8448 {
8449 DBUG_ENTER("Create_file_log_event::Create_file_log_event(char*,...)");
8450 /**
8451 We need to set exec_time here, which is ued to calcutate seconds behind
8452 master on the slave.
8453 */
8454 exec_time= load_exec_time;
8455 sql_ex.data_info= sql_ex_data;
8456 if (inited_from_old || block != 0)
8457 is_valid_param= true;
8458 if (fake_base)
8459 common_header->type_code= Load_log_event::get_type_code();
8460 else
8461 common_header->type_code= binary_log::CREATE_FILE_EVENT;
8462 DBUG_VOID_RETURN;
8463 }
8464
8465
8466 /*
8467 Create_file_log_event::print()
8468 */
8469
8470 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info,bool enable_local)8471 void Create_file_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info,
8472 bool enable_local)
8473 {
8474 if (print_event_info->short_form)
8475 {
8476 if (enable_local && check_fname_outside_temp_buf())
8477 Load_log_event::print(file, print_event_info);
8478 return;
8479 }
8480
8481 if (enable_local)
8482 {
8483 Load_log_event::print(file, print_event_info,
8484 !check_fname_outside_temp_buf());
8485 /**
8486 reduce the size of io cache so that the write function is called
8487 for every call to my_b_printf().
8488 */
8489 DBUG_EXECUTE_IF ("simulate_create_event_write_error",
8490 {(&print_event_info->head_cache)->write_pos=
8491 (&print_event_info->head_cache)->write_end;
8492 DBUG_SET("+d,simulate_file_write_error");});
8493 /*
8494 That one is for "file_id: etc" below: in mysqlbinlog we want the #, in
8495 SHOW BINLOG EVENTS we don't.
8496 */
8497 my_b_printf(&print_event_info->head_cache, "#");
8498 }
8499
8500 my_b_printf(&print_event_info->head_cache,
8501 " file_id: %d block_len: %d\n", file_id, block_len);
8502 }
8503
8504
print(FILE * file,PRINT_EVENT_INFO * print_event_info)8505 void Create_file_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
8506 {
8507 print(file, print_event_info, 0);
8508 }
8509 #endif /* MYSQL_CLIENT */
8510
8511
8512 /*
8513 Create_file_log_event::pack_info()
8514 */
8515
8516 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
pack_info(Protocol * protocol)8517 int Create_file_log_event::pack_info(Protocol *protocol)
8518 {
8519 char buf[NAME_LEN*2 + 30 + 21*2], *pos;
8520 pos= my_stpcpy(buf, "db=");
8521 memcpy(pos, db, db_len);
8522 pos= my_stpcpy(pos + db_len, ";table=");
8523 memcpy(pos, table_name, table_name_len);
8524 pos= my_stpcpy(pos + table_name_len, ";file_id=");
8525 pos= int10_to_str((long) file_id, pos, 10);
8526 pos= my_stpcpy(pos, ";block_len=");
8527 pos= int10_to_str((long) block_len, pos, 10);
8528 protocol->store(buf, (uint) (pos-buf), &my_charset_bin);
8529 return 0;
8530 }
8531 #endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
8532
8533
8534 /**
8535 Create_file_log_event::do_apply_event()
8536 Constructor for Create_file_log_event to intantiate an event
8537 from the relay log on the slave.
8538
8539 @retval
8540 0 Success
8541 @retval
8542 1 Failure
8543 */
8544
8545 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
do_apply_event(Relay_log_info const * rli)8546 int Create_file_log_event::do_apply_event(Relay_log_info const *rli)
8547 {
8548 char fname_buf[FN_REFLEN+TEMP_FILE_MAX_LEN];
8549 char *ext;
8550 int fd = -1;
8551 IO_CACHE file;
8552 int error = 1;
8553
8554 lex_start(thd);
8555 mysql_reset_thd_for_next_command(thd);
8556 THD_STAGE_INFO(thd, stage_making_temp_file_create_before_load_data);
8557 memset(&file, 0, sizeof(file));
8558 ext= slave_load_file_stem(fname_buf, file_id, server_id, ".info");
8559 /* old copy may exist already */
8560 mysql_file_delete(key_file_log_event_info, fname_buf, MYF(0));
8561 /**
8562 To simulate file creation failure, convert the file name to a
8563 directory by appending a "/" to the file name.
8564 */
8565 DBUG_EXECUTE_IF("simulate_file_create_error_create_log_event",
8566 {
8567 strcat(fname_buf,"/");
8568 });
8569 if ((fd= mysql_file_create(key_file_log_event_info,
8570 fname_buf, CREATE_MODE,
8571 O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW,
8572 MYF(MY_WME))) < 0 ||
8573 init_io_cache(&file, fd, IO_SIZE, WRITE_CACHE, (my_off_t)0, 0,
8574 MYF(MY_WME|MY_NABP)))
8575 {
8576 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
8577 "Error in Create_file event: could not open file '%s', '%s'",
8578 fname_buf, thd->get_stmt_da()->message_text());
8579 goto err;
8580 }
8581
8582 // a trick to avoid allocating another buffer
8583 fname= fname_buf;
8584 fname_len= (uint) (my_stpcpy(ext, ".data") - fname);
8585 if (write_base(&file))
8586 {
8587 my_stpcpy(ext, ".info"); // to have it right in the error message
8588 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
8589 "Error in Create_file event: could not write to file '%s', '%s'",
8590 fname_buf, thd->get_stmt_da()->message_text());
8591 goto err;
8592 }
8593 end_io_cache(&file);
8594 mysql_file_close(fd, MYF(0));
8595
8596 // fname_buf now already has .data, not .info, because we did our trick
8597 /* old copy may exist already */
8598 mysql_file_delete(key_file_log_event_data, fname_buf, MYF(0));
8599 DBUG_EXECUTE_IF("simulate_file_create_error_create_log_event_2",
8600 {
8601 strcat(fname_buf, "/");
8602 });
8603 if ((fd= mysql_file_create(key_file_log_event_data,
8604 fname_buf, CREATE_MODE,
8605 O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW,
8606 MYF(MY_WME))) < 0)
8607 {
8608 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
8609 "Error in Create_file event: could not open file '%s', '%s'",
8610 fname_buf, thd->get_stmt_da()->message_text());
8611 goto err;
8612 }
8613 /**
8614 To simulate file write failure,close the file before the write operation.
8615 Write will fail with an error reporting file is UNOPENED.
8616 */
8617 DBUG_EXECUTE_IF("simulate_file_write_error_create_log_event",
8618 {
8619 mysql_file_close(fd, MYF(0));
8620 });
8621 if (mysql_file_write(fd, block, block_len, MYF(MY_WME+MY_NABP)))
8622 {
8623 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
8624 "Error in Create_file event: write to '%s' failed, '%s'",
8625 fname_buf, thd->get_stmt_da()->message_text());
8626 goto err;
8627 }
8628 error=0; // Everything is ok
8629
8630 err:
8631 if (error)
8632 {
8633 end_io_cache(&file);
8634 /*
8635 Error occured. Delete .info and .data files if they are created.
8636 */
8637 my_stpcpy(ext,".info");
8638 mysql_file_delete(key_file_log_event_info, fname_buf, MYF(0));
8639 my_stpcpy(ext,".data");
8640 mysql_file_delete(key_file_log_event_data, fname_buf, MYF(0));
8641 }
8642 if (fd >= 0)
8643 mysql_file_close(fd, MYF(0));
8644 return error != 0;
8645 }
8646 #endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
8647
8648
8649 /**************************************************************************
8650 Append_block_log_event methods
8651 **************************************************************************/
8652
8653 /*
8654 Append_block_log_event ctor
8655 */
8656
8657 #ifndef MYSQL_CLIENT
Append_block_log_event(THD * thd_arg,const char * db_arg,uchar * block_arg,uint block_len_arg,bool using_trans)8658 Append_block_log_event::Append_block_log_event(THD *thd_arg,
8659 const char *db_arg,
8660 uchar *block_arg,
8661 uint block_len_arg,
8662 bool using_trans)
8663 : binary_log::Append_block_event(db_arg, block_arg, block_len_arg, thd_arg->file_id),
8664 Log_event(thd_arg, 0,
8665 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
8666 Log_event::EVENT_STMT_CACHE,
8667 Log_event::EVENT_NORMAL_LOGGING,
8668 header(), footer())
8669 {
8670 if (block != 0)
8671 is_valid_param= true;
8672 }
8673 #endif
8674
8675
8676 /*
8677 Append_block_log_event ctor
8678 */
8679
Append_block_log_event(const char * buf,uint len,const Format_description_event * description_event)8680 Append_block_log_event::Append_block_log_event(const char* buf, uint len,
8681 const Format_description_event*
8682 description_event)
8683 : binary_log::Append_block_event(buf, len, description_event),
8684 Log_event(header(), footer())
8685 {
8686
8687 DBUG_ENTER("Append_block_log_event::Append_block_log_event(char*,...)");
8688 if (block != 0)
8689 is_valid_param= true;
8690 DBUG_VOID_RETURN;
8691 }
8692
8693
8694 /*
8695 Append_block_log_event::write()
8696 */
8697
8698 #ifndef MYSQL_CLIENT
write(IO_CACHE * file)8699 bool Append_block_log_event::write(IO_CACHE* file)
8700 {
8701 uchar buf[Binary_log_event::APPEND_BLOCK_HEADER_LEN];
8702 int4store(buf + AB_FILE_ID_OFFSET, file_id);
8703 return (write_header(file, Binary_log_event::APPEND_BLOCK_HEADER_LEN +
8704 block_len) ||
8705 wrapper_my_b_safe_write(file, buf,
8706 Binary_log_event::APPEND_BLOCK_HEADER_LEN) ||
8707 wrapper_my_b_safe_write(file, block, block_len) ||
8708 write_footer(file));
8709 }
8710 #endif
8711
8712
8713 /*
8714 Append_block_log_event::print()
8715 */
8716
8717 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)8718 void Append_block_log_event::print(FILE* file,
8719 PRINT_EVENT_INFO* print_event_info)
8720 {
8721 if (print_event_info->short_form)
8722 return;
8723 print_header(&print_event_info->head_cache, print_event_info, FALSE);
8724 my_b_printf(&print_event_info->head_cache,
8725 "\n#%s: file_id: %d block_len: %d\n",
8726 get_type_str(), file_id, block_len);
8727 }
8728 #endif /* MYSQL_CLIENT */
8729
8730
8731 /*
8732 Append_block_log_event::pack_info()
8733 */
8734
8735 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
pack_info(Protocol * protocol)8736 int Append_block_log_event::pack_info(Protocol *protocol)
8737 {
8738 char buf[256];
8739 size_t length;
8740 length= my_snprintf(buf, sizeof(buf), ";file_id=%u;block_len=%u",
8741 file_id, block_len);
8742 protocol->store(buf, length, &my_charset_bin);
8743 return 0;
8744 }
8745
8746
8747 /*
8748 Append_block_log_event::get_create_or_append()
8749 */
8750
get_create_or_append() const8751 int Append_block_log_event::get_create_or_append() const
8752 {
8753 return 0; /* append to the file, fail if not exists */
8754 }
8755
8756 /*
8757 Append_block_log_event::do_apply_event()
8758 */
8759
do_apply_event(Relay_log_info const * rli)8760 int Append_block_log_event::do_apply_event(Relay_log_info const *rli)
8761 {
8762 char fname[FN_REFLEN+TEMP_FILE_MAX_LEN];
8763 int fd;
8764 int error = 1;
8765 DBUG_ENTER("Append_block_log_event::do_apply_event");
8766
8767 THD_STAGE_INFO(thd, stage_making_temp_file_append_before_load_data);
8768 slave_load_file_stem(fname, file_id, server_id, ".data");
8769 if (get_create_or_append())
8770 {
8771 /*
8772 Usually lex_start() is called by mysql_parse(), but we need it here
8773 as the present method does not call mysql_parse().
8774 */
8775 lex_start(thd);
8776 mysql_reset_thd_for_next_command(thd);
8777 /* old copy may exist already */
8778 mysql_file_delete(key_file_log_event_data, fname, MYF(0));
8779 DBUG_EXECUTE_IF("simulate_file_create_error_Append_block_event",
8780 {
8781 strcat(fname, "/");
8782 });
8783 if ((fd= mysql_file_create(key_file_log_event_data,
8784 fname, CREATE_MODE,
8785 O_WRONLY | O_BINARY | O_EXCL | O_NOFOLLOW,
8786 MYF(MY_WME))) < 0)
8787 {
8788 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
8789 "Error in %s event: could not create file '%s', '%s'",
8790 get_type_str(), fname, thd->get_stmt_da()->message_text());
8791 goto err;
8792 }
8793 }
8794 else if ((fd= mysql_file_open(key_file_log_event_data,
8795 fname,
8796 O_WRONLY | O_APPEND | O_BINARY | O_NOFOLLOW,
8797 MYF(MY_WME))) < 0)
8798 {
8799 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
8800 "Error in %s event: could not open file '%s', '%s'",
8801 get_type_str(), fname, thd->get_stmt_da()->message_text());
8802 goto err;
8803 }
8804 DBUG_EXECUTE_IF("remove_slave_load_file_before_write",
8805 {
8806 my_delete_allow_opened(fname, MYF(0));
8807 });
8808
8809 DBUG_EXECUTE_IF("simulate_file_write_error_Append_block_event",
8810 {
8811 mysql_file_close(fd, MYF(0));
8812 });
8813 if (mysql_file_write(fd, block, block_len, MYF(MY_WME+MY_NABP)))
8814 {
8815 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
8816 "Error in %s event: write to '%s' failed, '%s'",
8817 get_type_str(), fname, thd->get_stmt_da()->message_text());
8818 goto err;
8819 }
8820 error=0;
8821
8822 err:
8823 if (fd >= 0)
8824 mysql_file_close(fd, MYF(0));
8825 DBUG_RETURN(error);
8826 }
8827 #endif
8828
8829
8830 /**************************************************************************
8831 Delete_file_log_event methods
8832 **************************************************************************/
8833
8834 /*
8835 Delete_file_log_event ctor
8836 */
8837
8838 #ifndef MYSQL_CLIENT
Delete_file_log_event(THD * thd_arg,const char * db_arg,bool using_trans)8839 Delete_file_log_event::Delete_file_log_event(THD *thd_arg, const char* db_arg,
8840 bool using_trans)
8841 : binary_log::Delete_file_event(thd_arg->file_id, db_arg),
8842 Log_event(thd_arg, 0,
8843 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
8844 Log_event::EVENT_STMT_CACHE,
8845 Log_event::EVENT_NORMAL_LOGGING,
8846 header(), footer())
8847 {
8848 if (file_id != 0)
8849 is_valid_param= true;
8850 }
8851 #endif
8852
8853 /*
8854 Delete_file_log_event ctor
8855 */
8856
Delete_file_log_event(const char * buf,uint len,const Format_description_event * description_event)8857 Delete_file_log_event::Delete_file_log_event(const char* buf, uint len,
8858 const Format_description_event*
8859 description_event)
8860 : binary_log::Delete_file_event(buf, len, description_event),
8861 Log_event(header(), footer())
8862 {
8863 if (file_id != 0)
8864 is_valid_param= true;
8865 }
8866
8867
8868 /*
8869 Delete_file_log_event::write()
8870 */
8871
8872 #ifndef MYSQL_CLIENT
write(IO_CACHE * file)8873 bool Delete_file_log_event::write(IO_CACHE* file)
8874 {
8875 uchar buf[Binary_log_event::DELETE_FILE_HEADER_LEN];
8876 int4store(buf + DF_FILE_ID_OFFSET, file_id);
8877 return (write_header(file, sizeof(buf)) ||
8878 wrapper_my_b_safe_write(file, buf, sizeof(buf)) ||
8879 write_footer(file));
8880 }
8881 #endif
8882
8883
8884 /*
8885 Delete_file_log_event::print()
8886 */
8887
8888 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)8889 void Delete_file_log_event::print(FILE* file,
8890 PRINT_EVENT_INFO* print_event_info)
8891 {
8892 if (print_event_info->short_form)
8893 return;
8894 print_header(&print_event_info->head_cache, print_event_info, FALSE);
8895 my_b_printf(&print_event_info->head_cache,
8896 "\n#Delete_file: file_id=%u\n", file_id);
8897 }
8898 #endif /* MYSQL_CLIENT */
8899
8900 /*
8901 Delete_file_log_event::pack_info()
8902 */
8903
8904 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
pack_info(Protocol * protocol)8905 int Delete_file_log_event::pack_info(Protocol *protocol)
8906 {
8907 char buf[64];
8908 size_t length;
8909 length= my_snprintf(buf, sizeof(buf), ";file_id=%u", (uint) file_id);
8910 protocol->store(buf, length, &my_charset_bin);
8911 return 0;
8912 }
8913 #endif
8914
8915 /*
8916 Delete_file_log_event::do_apply_event()
8917 */
8918
8919 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
do_apply_event(Relay_log_info const * rli)8920 int Delete_file_log_event::do_apply_event(Relay_log_info const *rli)
8921 {
8922 char fname[FN_REFLEN+TEMP_FILE_MAX_LEN];
8923 lex_start(thd);
8924 mysql_reset_thd_for_next_command(thd);
8925 char *ext= slave_load_file_stem(fname, file_id, server_id, ".data");
8926 mysql_file_delete(key_file_log_event_data, fname, MYF(MY_WME));
8927 my_stpcpy(ext, ".info");
8928 mysql_file_delete(key_file_log_event_info, fname, MYF(MY_WME));
8929 return 0;
8930 }
8931 #endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
8932
8933
8934 /**************************************************************************
8935 Execute_load_log_event methods
8936 **************************************************************************/
8937
8938 /*
8939 Execute_load_log_event ctor
8940 */
8941
8942 #ifndef MYSQL_CLIENT
Execute_load_log_event(THD * thd_arg,const char * db_arg,bool using_trans)8943 Execute_load_log_event::Execute_load_log_event(THD *thd_arg,
8944 const char* db_arg,
8945 bool using_trans)
8946 : binary_log::Execute_load_event(thd_arg->file_id, db_arg),
8947 Log_event(thd_arg, 0,
8948 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
8949 Log_event::EVENT_STMT_CACHE,
8950 Log_event::EVENT_NORMAL_LOGGING,
8951 header(), footer())
8952 {
8953 if (file_id != 0)
8954 is_valid_param= true;
8955 }
8956 #endif
8957
8958
8959 /*
8960 Execute_load_log_event ctor
8961 */
8962
Execute_load_log_event(const char * buf,uint len,const Format_description_event * description_event)8963 Execute_load_log_event::Execute_load_log_event(const char* buf, uint len,
8964 const Format_description_event*
8965 description_event)
8966 : binary_log::Execute_load_event(buf, len, description_event),
8967 Log_event(header(), footer())
8968 {
8969 if (file_id != 0)
8970 is_valid_param= true;
8971 }
8972
8973
8974 /*
8975 Execute_load_log_event::write()
8976 */
8977
8978 #ifndef MYSQL_CLIENT
write(IO_CACHE * file)8979 bool Execute_load_log_event::write(IO_CACHE* file)
8980 {
8981 uchar buf[Binary_log_event::EXEC_LOAD_HEADER_LEN];
8982 int4store(buf + EL_FILE_ID_OFFSET, file_id);
8983 return (write_header(file, sizeof(buf)) ||
8984 wrapper_my_b_safe_write(file, buf, sizeof(buf)) ||
8985 write_footer(file));
8986 }
8987 #endif
8988
8989
8990 /*
8991 Execute_load_log_event::print()
8992 */
8993
8994 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)8995 void Execute_load_log_event::print(FILE* file,
8996 PRINT_EVENT_INFO* print_event_info)
8997 {
8998 if (print_event_info->short_form)
8999 return;
9000 print_header(&print_event_info->head_cache, print_event_info, FALSE);
9001 my_b_printf(&print_event_info->head_cache, "\n#Exec_load: file_id=%d\n",
9002 file_id);
9003 }
9004 #endif
9005
9006 /*
9007 Execute_load_log_event::pack_info()
9008 */
9009
9010 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
pack_info(Protocol * protocol)9011 int Execute_load_log_event::pack_info(Protocol *protocol)
9012 {
9013 char buf[64];
9014 size_t length;
9015 length= my_snprintf(buf, sizeof(buf), ";file_id=%u", (uint) file_id);
9016 protocol->store(buf, length, &my_charset_bin);
9017 return 0;
9018 }
9019
9020
9021 /*
9022 Execute_load_log_event::do_apply_event()
9023 */
9024
do_apply_event(Relay_log_info const * rli)9025 int Execute_load_log_event::do_apply_event(Relay_log_info const *rli)
9026 {
9027 char fname[FN_REFLEN+TEMP_FILE_MAX_LEN];
9028 char *ext;
9029 int fd;
9030 int error= 1;
9031 IO_CACHE file;
9032 Load_log_event *lev= 0;
9033
9034 lex_start(thd);
9035 mysql_reset_thd_for_next_command(thd);
9036 ext= slave_load_file_stem(fname, file_id, server_id, ".info");
9037 /**
9038 To simulate file open failure, convert the file name to a
9039 directory by appending a "/" to the file name. File open
9040 will fail with an error reporting it is not a directory.
9041 */
9042 DBUG_EXECUTE_IF("simulate_file_open_error_exec_event",
9043 {
9044 strcat(fname,"/");
9045 });
9046 if ((fd= mysql_file_open(key_file_log_event_info,
9047 fname, O_RDONLY | O_BINARY | O_NOFOLLOW,
9048 MYF(MY_WME))) < 0 ||
9049 init_io_cache(&file, fd, IO_SIZE, READ_CACHE, (my_off_t)0, 0,
9050 MYF(MY_WME|MY_NABP)))
9051 {
9052 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
9053 "Error in Exec_load event: could not open file, '%s'",
9054 thd->get_stmt_da()->message_text());
9055 goto err;
9056 }
9057 if (!(lev= (Load_log_event*)
9058 Log_event::read_log_event(&file,
9059 (mysql_mutex_t*) 0,
9060 rli->get_rli_description_event(),
9061 opt_slave_sql_verify_checksum)) ||
9062 lev->get_type_code() != binary_log::NEW_LOAD_EVENT)
9063 {
9064 rli->report(ERROR_LEVEL, ER_FILE_CORRUPT, ER(ER_FILE_CORRUPT),
9065 fname);
9066 goto err;
9067 }
9068 lev->thd = thd;
9069 /*
9070 lev->do_apply_event should use rli only for errors.
9071 lev->do_apply_event is the place where the table is loaded (it
9072 calls mysql_load()).
9073 */
9074 if (lev->do_apply_event(0,rli,1))
9075 {
9076 /*
9077 We want to indicate the name of the file that could not be loaded
9078 (SQL_LOADxxx).
9079 But as we are here we are sure the error is in rli->last_slave_error and
9080 rli->last_slave_errno (example of error: duplicate entry for key), so we
9081 don't want to overwrite it with the filename.
9082 What we want instead is add the filename to the current error message.
9083 */
9084 char *tmp= my_strdup(key_memory_log_event,
9085 rli->last_error().message, MYF(MY_WME));
9086 if (tmp)
9087 {
9088 rli->report(ERROR_LEVEL, rli->last_error().number,
9089 "%s. Failed executing load from '%s'", tmp, fname);
9090 my_free(tmp);
9091 }
9092 goto err;
9093 }
9094 /*
9095 We have an open file descriptor to the .info file; we need to close it
9096 or Windows will refuse to delete the file in mysql_file_delete().
9097 */
9098 if (fd >= 0)
9099 {
9100 mysql_file_close(fd, MYF(0));
9101 end_io_cache(&file);
9102 fd= -1;
9103 }
9104 error = 0;
9105
9106 err:
9107 DBUG_EXECUTE_IF("simulate_file_open_error_exec_event",
9108 {
9109 my_stpcpy(ext, ".info");
9110 });
9111 mysql_file_delete(key_file_log_event_info, fname, MYF(MY_WME));
9112 my_stpcpy(ext, ".data");
9113 mysql_file_delete(key_file_log_event_data, fname, MYF(MY_WME));
9114 delete lev;
9115 if (fd >= 0)
9116 {
9117 mysql_file_close(fd, MYF(0));
9118 end_io_cache(&file);
9119 }
9120 return error;
9121 }
9122
9123 #endif /* defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
9124
9125
9126 /**************************************************************************
9127 Begin_load_query_log_event methods
9128 **************************************************************************/
9129
9130 #ifndef MYSQL_CLIENT
9131 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)9132 Begin_load_query_log_event(THD* thd_arg, const char* db_arg, uchar* block_arg,
9133 uint block_len_arg, bool using_trans)
9134 : binary_log::Append_block_event(db_arg, block_arg, block_len_arg,
9135 thd_arg->file_id),
9136 Append_block_log_event(thd_arg, db_arg, block_arg, block_len_arg,
9137 using_trans),
9138 binary_log::Begin_load_query_event()
9139 {
9140 common_header->type_code= binary_log::BEGIN_LOAD_QUERY_EVENT;
9141 file_id= thd_arg->file_id= mysql_bin_log.next_file_id();
9142 }
9143 #endif
9144
9145
9146 Begin_load_query_log_event::
Begin_load_query_log_event(const char * buf,uint len,const Format_description_event * desc_event)9147 Begin_load_query_log_event(const char* buf, uint len,
9148 const Format_description_event* desc_event)
9149 : binary_log::Append_block_event(buf, len, desc_event),
9150 Append_block_log_event(buf, len, desc_event),
9151 binary_log::Begin_load_query_event(buf, len, desc_event)
9152 {
9153 }
9154
9155
9156 #if defined( HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
get_create_or_append() const9157 int Begin_load_query_log_event::get_create_or_append() const
9158 {
9159 return 1; /* create the file */
9160 }
9161 #endif /* defined( HAVE_REPLICATION) && !defined(MYSQL_CLIENT) */
9162
9163
9164 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
9165 Log_event::enum_skip_reason
do_shall_skip(Relay_log_info * rli)9166 Begin_load_query_log_event::do_shall_skip(Relay_log_info *rli)
9167 {
9168 /*
9169 If the slave skip counter is 1, then we should not start executing
9170 on the next event.
9171 */
9172 return continue_group(rli);
9173 }
9174 #endif
9175
9176
9177 /**************************************************************************
9178 Execute_load_query_log_event methods
9179 **************************************************************************/
9180
9181
9182 #ifndef MYSQL_CLIENT
9183 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,binary_log::enum_load_dup_handling dup_handling_arg,bool using_trans,bool immediate,bool suppress_use,int errcode)9184 Execute_load_query_log_event(THD *thd_arg, const char* query_arg,
9185 ulong query_length_arg, uint fn_pos_start_arg,
9186 uint fn_pos_end_arg,
9187 binary_log::enum_load_dup_handling dup_handling_arg,
9188 bool using_trans, bool immediate, bool suppress_use,
9189 int errcode)
9190 : binary_log::Query_event(query_arg, thd_arg->catalog().str, thd_arg->db().str,
9191 query_length_arg,
9192 thd_arg->thread_id(), thd_arg->variables.sql_mode,
9193 thd_arg->variables.auto_increment_increment,
9194 thd_arg->variables.auto_increment_offset,
9195 thd_arg->variables.lc_time_names->number,
9196 (ulonglong)thd_arg->table_map_for_update,
9197 errcode,
9198 thd_arg->db().str ? strlen(thd_arg->db().str) : 0,
9199 thd_arg->catalog().str ? strlen(thd_arg->catalog().str) : 0),
9200 Query_log_event(thd_arg, query_arg, query_length_arg, using_trans, immediate,
9201 suppress_use, errcode),
9202 binary_log::Execute_load_query_event(thd_arg->file_id, fn_pos_start_arg,
9203 fn_pos_end_arg, dup_handling_arg)
9204 {
9205 if (Query_log_event::is_valid() && file_id != 0)
9206 is_valid_param= true;
9207 common_header->type_code= binary_log::EXECUTE_LOAD_QUERY_EVENT;
9208 }
9209 #endif /* !MYSQL_CLIENT */
9210
9211
9212 Execute_load_query_log_event::
Execute_load_query_log_event(const char * buf,uint event_len,const Format_description_event * desc_event)9213 Execute_load_query_log_event(const char* buf, uint event_len,
9214 const Format_description_event* desc_event)
9215 : binary_log::Query_event(buf, event_len, desc_event,
9216 binary_log::EXECUTE_LOAD_QUERY_EVENT),
9217 Query_log_event(buf, event_len, desc_event,
9218 binary_log::EXECUTE_LOAD_QUERY_EVENT),
9219 binary_log::Execute_load_query_event(buf, event_len, desc_event)
9220 {
9221 if (!Query_log_event::is_valid())
9222 {
9223 //clear all the variables set in execute_load_query_event
9224 file_id= 0; fn_pos_start= 0; fn_pos_end= 0;
9225 dup_handling= binary_log::LOAD_DUP_ERROR;
9226 }
9227 if (Query_log_event::is_valid() && file_id != 0)
9228 is_valid_param= true;
9229 }
9230
9231
get_post_header_size_for_derived()9232 ulong Execute_load_query_log_event::get_post_header_size_for_derived()
9233 {
9234 return Binary_log_event::EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN;
9235 }
9236
9237
9238 #ifndef MYSQL_CLIENT
9239 bool
write_post_header_for_derived(IO_CACHE * file)9240 Execute_load_query_log_event::write_post_header_for_derived(IO_CACHE* file)
9241 {
9242 uchar buf[Binary_log_event::EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN];
9243 int4store(buf, file_id);
9244 int4store(buf + 4, fn_pos_start);
9245 int4store(buf + 4 + 4, fn_pos_end);
9246 *(buf + 4 + 4 + 4)= (uchar) dup_handling;
9247 return wrapper_my_b_safe_write(file, buf, Binary_log_event::EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN);
9248 }
9249 #endif
9250
9251
9252 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)9253 void Execute_load_query_log_event::print(FILE* file,
9254 PRINT_EVENT_INFO* print_event_info)
9255 {
9256 print(file, print_event_info, 0);
9257 }
9258
9259 /**
9260 Prints the query as LOAD DATA LOCAL and with rewritten filename.
9261 */
print(FILE * file,PRINT_EVENT_INFO * print_event_info,const char * local_fname)9262 void Execute_load_query_log_event::print(FILE* file,
9263 PRINT_EVENT_INFO* print_event_info,
9264 const char *local_fname)
9265 {
9266 MY_ATTRIBUTE((unused)) int write_res;
9267 IO_CACHE *const head= &print_event_info->head_cache;
9268
9269 print_query_header(head, print_event_info);
9270 /**
9271 reduce the size of io cache so that the write function is called
9272 for every call to my_b_printf().
9273 */
9274 DBUG_EXECUTE_IF ("simulate_execute_event_write_error",
9275 {head->write_pos= head->write_end;
9276 DBUG_SET("+d,simulate_file_write_error");});
9277
9278 if (local_fname)
9279 {
9280 write_res= my_b_write(head, (uchar*) query, fn_pos_start);
9281 assert(write_res == 0);
9282 my_b_printf(head, " LOCAL INFILE ");
9283 pretty_print_str(head, local_fname, strlen(local_fname));
9284
9285 if (dup_handling == binary_log::LOAD_DUP_REPLACE)
9286 my_b_printf(head, " REPLACE");
9287 my_b_printf(head, " INTO");
9288 write_res= my_b_write(head, (uchar*) query + fn_pos_end, q_len-fn_pos_end);
9289 assert(write_res == 0);
9290 my_b_printf(head, "\n%s\n", print_event_info->delimiter);
9291 }
9292 else
9293 {
9294 write_res= my_b_write(head, (uchar*) query, q_len);
9295 assert(write_res == 0);
9296 my_b_printf(head, "\n%s\n", print_event_info->delimiter);
9297 }
9298
9299 if (!print_event_info->short_form)
9300 my_b_printf(head, "# file_id: %d \n", file_id);
9301 }
9302 #endif
9303
9304
9305 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
pack_info(Protocol * protocol)9306 int Execute_load_query_log_event::pack_info(Protocol *protocol)
9307 {
9308 char *buf, *pos;
9309 if (!(buf= (char*) my_malloc(key_memory_log_event,
9310 9 + (db_len * 2) + 2 + q_len + 10 + 21,
9311 MYF(MY_WME))))
9312 return 1;
9313 pos= buf;
9314 if (db && db_len)
9315 {
9316 /*
9317 Statically allocates room to store '\0' and an identifier
9318 that may have NAME_LEN * 2 due to quoting and there are
9319 two quoting characters that wrap them.
9320 */
9321 char quoted_db[1 + NAME_LEN * 2 + 2];// quoted length of the identifier
9322 size_t size= 0;
9323 size= my_strmov_quoted_identifier(this->thd, quoted_db, db, 0);
9324 pos= my_stpcpy(buf, "use ");
9325 memcpy(pos, quoted_db, size);
9326 pos= my_stpcpy(pos + size, "; ");
9327 }
9328 if (query && q_len)
9329 {
9330 memcpy(pos, query, q_len);
9331 pos+= q_len;
9332 }
9333 pos= my_stpcpy(pos, " ;file_id=");
9334 pos= int10_to_str((long) file_id, pos, 10);
9335 protocol->store(buf, pos-buf, &my_charset_bin);
9336 my_free(buf);
9337 return 0;
9338 }
9339
9340
9341 int
do_apply_event(Relay_log_info const * rli)9342 Execute_load_query_log_event::do_apply_event(Relay_log_info const *rli)
9343 {
9344 char *p;
9345 char *buf;
9346 char *fname;
9347 char *fname_end;
9348 int error;
9349
9350 buf= (char*) my_malloc(key_memory_log_event,
9351 q_len + 1 - (fn_pos_end - fn_pos_start) +
9352 (FN_REFLEN + TEMP_FILE_MAX_LEN) + 10 + 8 + 5, MYF(MY_WME));
9353
9354 DBUG_EXECUTE_IF("LOAD_DATA_INFILE_has_fatal_error", my_free(buf); buf= NULL;);
9355
9356 /* Replace filename and LOCAL keyword in query before executing it */
9357 if (buf == NULL)
9358 {
9359 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
9360 ER(ER_SLAVE_FATAL_ERROR), "Not enough memory");
9361 return 1;
9362 }
9363
9364 p= buf;
9365 memcpy(p, query, fn_pos_start);
9366 p+= fn_pos_start;
9367 fname= (p= strmake(p, STRING_WITH_LEN(" INFILE \'")));
9368 p= slave_load_file_stem(p, file_id, server_id, ".data");
9369 fname_end= p= strend(p); // Safer than p=p+5
9370 *(p++)='\'';
9371 switch (dup_handling) {
9372 case binary_log::LOAD_DUP_IGNORE:
9373 p= strmake(p, STRING_WITH_LEN(" IGNORE"));
9374 break;
9375 case binary_log::LOAD_DUP_REPLACE:
9376 p= strmake(p, STRING_WITH_LEN(" REPLACE"));
9377 break;
9378 default:
9379 /* Ordinary load data */
9380 break;
9381 }
9382 p= strmake(p, STRING_WITH_LEN(" INTO "));
9383 p= strmake(p, query+fn_pos_end, q_len-fn_pos_end);
9384
9385 error= Query_log_event::do_apply_event(rli, buf, p-buf);
9386
9387 /* Forging file name for deletion in same buffer */
9388 *fname_end= 0;
9389
9390 /*
9391 If there was an error the slave is going to stop, leave the
9392 file so that we can re-execute this event at START SLAVE.
9393 */
9394 if (!error)
9395 mysql_file_delete(key_file_log_event_data, fname, MYF(MY_WME));
9396
9397 my_free(buf);
9398 return error;
9399 }
9400 #endif
9401
9402
9403 /**************************************************************************
9404 sql_ex_info methods
9405 **************************************************************************/
9406
9407 /*
9408 sql_ex_info::write_data()
9409 */
9410
write_data(IO_CACHE * file)9411 bool sql_ex_info::write_data(IO_CACHE* file)
9412 {
9413 if (data_info.new_format())
9414 {
9415 return (write_str_at_most_255_bytes(file, data_info.field_term,
9416 (uint) data_info.field_term_len, event_encrypter) ||
9417 write_str_at_most_255_bytes(file, data_info.enclosed,
9418 (uint) data_info.enclosed_len, event_encrypter) ||
9419 write_str_at_most_255_bytes(file, data_info.line_term,
9420 (uint) data_info.line_term_len, event_encrypter) ||
9421 write_str_at_most_255_bytes(file, data_info.line_start,
9422 (uint) data_info.line_start_len, event_encrypter) ||
9423 write_str_at_most_255_bytes(file, data_info.escaped,
9424 (uint) data_info.escaped_len, event_encrypter) ||
9425 event_encrypter->encrypt_and_write(file,(uchar*) &(data_info.opt_flags), 1));
9426 }
9427 else
9428 {
9429 /**
9430 @todo This is sensitive to field padding. We should write a
9431 char[7], not an old_sql_ex. /sven
9432 */
9433 binary_log::old_sql_ex old_ex;
9434 old_ex.field_term= *(data_info.field_term);
9435 old_ex.enclosed= *(data_info.enclosed);
9436 old_ex.line_term= *(data_info.line_term);
9437 old_ex.line_start= *(data_info.line_start);
9438 old_ex.escaped= *(data_info.escaped);
9439 old_ex.opt_flags= data_info.opt_flags;
9440 old_ex.empty_flags= data_info.empty_flags;
9441 return event_encrypter->encrypt_and_write(file, (uchar*) &old_ex, sizeof(old_ex)) != 0;
9442 }
9443 }
9444
9445
9446 /**
9447 sql_ex_info::init()
9448 This method initializes the members of strcuture variable sql_ex_info,
9449 defined in a Load_log_event. The structure, initializes the sub struct
9450 data_info, with the subclause characters in a LOAD_DATA_INFILE query.
9451
9452 */
init(const char * buf,const char * buf_end,bool use_new_format)9453 const char *sql_ex_info::init(const char *buf, const char *buf_end,
9454 bool use_new_format)
9455 {
9456 return data_info.init(buf, buf_end, use_new_format);
9457 }
9458 #ifndef NDEBUG
9459 #ifndef MYSQL_CLIENT
9460 static uchar dbug_extra_row_data_val= 0;
9461
9462 /**
9463 set_extra_data
9464
9465 Called during self-test to generate various
9466 self-consistent binlog row event extra
9467 thread data structures which can be checked
9468 when reading the binlog.
9469
9470 @param arr Buffer to use
9471 */
set_extra_data(uchar * arr)9472 const uchar* set_extra_data(uchar* arr)
9473 {
9474 uchar val= (dbug_extra_row_data_val++) %
9475 (EXTRA_ROW_INFO_MAX_PAYLOAD + 1); /* 0 .. MAX_PAYLOAD + 1 */
9476 arr[EXTRA_ROW_INFO_LEN_OFFSET]= val + EXTRA_ROW_INFO_HDR_BYTES;
9477 arr[EXTRA_ROW_INFO_FORMAT_OFFSET]= val;
9478 for (uchar i=0; i<val; i++)
9479 arr[EXTRA_ROW_INFO_HDR_BYTES+i]= val;
9480
9481 return arr;
9482 }
9483
9484 #endif // #ifndef MYSQL_CLIENT
9485
9486 /**
9487 check_extra_data
9488
9489 Called during self-test to check that
9490 binlog row event extra data is self-
9491 consistent as defined by the set_extra_data
9492 function above.
9493
9494 Will assert(false) if not.
9495
9496 @param extra_row_data
9497 */
check_extra_data(uchar * extra_row_data)9498 void check_extra_data(uchar* extra_row_data)
9499 {
9500 assert(extra_row_data);
9501 uint16 len= extra_row_data[EXTRA_ROW_INFO_LEN_OFFSET];
9502 uint8 val= len - EXTRA_ROW_INFO_HDR_BYTES;
9503 assert(extra_row_data[EXTRA_ROW_INFO_FORMAT_OFFSET] == val);
9504 for (uint16 i= 0; i < val; i++)
9505 {
9506 assert(extra_row_data[EXTRA_ROW_INFO_HDR_BYTES + i] == val);
9507 }
9508 }
9509
9510 #endif // #ifndef NDEBUG
9511
9512 /**************************************************************************
9513 Rows_log_event member functions
9514 **************************************************************************/
9515
9516 #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)9517 Rows_log_event::Rows_log_event(THD *thd_arg, TABLE *tbl_arg, const Table_id& tid,
9518 MY_BITMAP const *cols, bool using_trans,
9519 Log_event_type event_type,
9520 const uchar* extra_row_info)
9521 : binary_log::Rows_event(event_type),
9522 Log_event(thd_arg, 0,
9523 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
9524 Log_event::EVENT_STMT_CACHE,
9525 Log_event::EVENT_NORMAL_LOGGING,
9526 header(), footer())
9527 #ifdef HAVE_REPLICATION
9528 , m_curr_row(NULL), m_curr_row_end(NULL), m_key(NULL), m_key_info(NULL),
9529 m_distinct_keys(Key_compare(&m_key_info)), m_distinct_key_spare_buf(NULL)
9530 #endif
9531 {
9532 common_header->type_code= m_type;
9533 m_row_count= 0;
9534 m_table_id= tid;
9535 m_width= tbl_arg ? tbl_arg->s->fields : 1;
9536 m_rows_buf= 0; m_rows_cur= 0; m_rows_end= 0; m_flags= 0;
9537 m_type= event_type; m_extra_row_data=0;
9538
9539 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 NDEBUG
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(key_memory_log_event,
9558 extra_data_len, MYF(MY_WME));
9559
9560 if (likely(m_extra_row_data != NULL))
9561 {
9562 memcpy(m_extra_row_data, extra_row_info,
9563 extra_data_len);
9564 }
9565 }
9566
9567 /* if bitmap_init fails, caught in is_valid() */
9568 if (likely(!bitmap_init(&m_cols,
9569 m_width <= sizeof(m_bitbuf)*8 ? m_bitbuf : NULL,
9570 m_width,
9571 false)))
9572 {
9573 /* Cols can be zero if this is a dummy binrows event */
9574 if (likely(cols != NULL))
9575 {
9576 memcpy(m_cols.bitmap, cols->bitmap, no_bytes_in_map(cols));
9577 create_last_word_mask(&m_cols);
9578 }
9579 }
9580 else
9581 {
9582 // Needed because bitmap_init() does not set it to null on failure
9583 m_cols.bitmap= 0;
9584 }
9585 /*
9586 -Check that malloc() succeeded in allocating memory for the rows
9587 buffer and the COLS vector.
9588 -Checking that an Update_rows_log_event
9589 is valid is done while setting the Update_rows_log_event::is_valid
9590 */
9591 if (m_rows_buf && m_cols.bitmap)
9592 is_valid_param= true;
9593 }
9594 #endif
9595
Rows_log_event(const char * buf,uint event_len,const Format_description_event * description_event)9596 Rows_log_event::Rows_log_event(const char *buf, uint event_len,
9597 const Format_description_event
9598 *description_event)
9599 : binary_log::Rows_event(buf, event_len, description_event),
9600 Log_event(header(), footer()),
9601 m_row_count(0),
9602 #ifndef MYSQL_CLIENT
9603 m_table(NULL),
9604 #endif
9605 m_rows_buf(0), m_rows_cur(0), m_rows_end(0)
9606 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
9607 , m_curr_row(NULL), m_curr_row_end(NULL), m_key(NULL), m_key_info(NULL),
9608 m_distinct_keys(Key_compare(&m_key_info)), m_distinct_key_spare_buf(NULL)
9609 #endif
9610 {
9611 DBUG_ENTER("Rows_log_event::Rows_log_event(const char*,...)");
9612
9613 assert(header()->type_code == m_type);
9614
9615
9616 if (m_extra_row_data)
9617 DBUG_EXECUTE_IF("extra_row_data_check",
9618 /* Check extra data has expected value */
9619 check_extra_data(m_extra_row_data););
9620
9621
9622 /*
9623 m_cols and m_cols_ai are of the type MY_BITMAP, which are members of
9624 class Rows_log_event, and are used while applying the row events on
9625 the slave.
9626 The bitmap integer is initialized by copying the contents of the
9627 vector column_before_image for m_cols.bitamp, and vector
9628 column_after_image for m_cols_ai.bitmap. m_cols_ai is only initialized
9629 for UPDATE_ROWS_EVENTS, else it is equal to the before image.
9630 */
9631 memset(&m_cols, 0, sizeof(m_cols));
9632 /* if bitmap_init fails, is_valid will be set to false */
9633 if (likely(!bitmap_init(&m_cols,
9634 m_width <= sizeof(m_bitbuf) * 8 ? m_bitbuf : NULL,
9635 m_width,
9636 false)))
9637 {
9638 if (!columns_before_image.empty())
9639 {
9640 memcpy(m_cols.bitmap, &columns_before_image[0], (m_width + 7) / 8);
9641 create_last_word_mask(&m_cols);
9642 DBUG_DUMP("m_cols", (uchar*) m_cols.bitmap, no_bytes_in_map(&m_cols));
9643 } //end if columns_before_image.empty()
9644 else
9645 m_cols.bitmap= NULL;
9646 }
9647 else
9648 {
9649 // Needed because bitmap_init() does not set it to null on failure
9650 m_cols.bitmap= NULL;
9651 DBUG_VOID_RETURN;
9652 }
9653 m_cols_ai.bitmap= m_cols.bitmap; //See explanation below while setting is_valid.
9654
9655 if ((m_type == binary_log::UPDATE_ROWS_EVENT) ||
9656 (m_type == binary_log::UPDATE_ROWS_EVENT_V1))
9657 {
9658 /* if bitmap_init fails, is_valid will be set to false*/
9659 if (likely(!bitmap_init(&m_cols_ai,
9660 m_width <= sizeof(m_bitbuf_ai) * 8 ?
9661 m_bitbuf_ai : NULL,
9662 m_width,
9663 false)))
9664 {
9665 if (!columns_after_image.empty())
9666 {
9667 memcpy(m_cols_ai.bitmap, &columns_after_image[0], (m_width + 7) / 8);
9668 create_last_word_mask(&m_cols_ai);
9669 DBUG_DUMP("m_cols_ai", (uchar*) m_cols_ai.bitmap,
9670 no_bytes_in_map(&m_cols_ai));
9671 }
9672 else
9673 m_cols_ai.bitmap= NULL;
9674 }
9675 else
9676 {
9677 // Needed because bitmap_init() does not set it to null on failure
9678 m_cols_ai.bitmap= 0;
9679 DBUG_VOID_RETURN;
9680 }
9681 }
9682
9683
9684 /*
9685 m_rows_buf, m_cur_row and m_rows_end are pointers to the vector rows.
9686 m_rows_buf is the pointer to the first byte of first row in the event.
9687 m_curr_row points to current row being applied on the slave. Initially,
9688 this points to the same element as m_rows_buf in the vector.
9689 m_rows_end points to the last byte in the last row in the event.
9690
9691 These pointers are used while applying the events on to the slave, and
9692 are not required for decoding.
9693 */
9694 if (likely(!row.empty()))
9695 {
9696 m_rows_buf= &row[0];
9697 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
9698 m_curr_row= m_rows_buf;
9699 #endif
9700 m_rows_end= m_rows_buf + row.size() - 1;
9701 m_rows_cur= m_rows_end;
9702 }
9703 /*
9704 -Check that malloc() succeeded in allocating memory for the row
9705 buffer and the COLS vector.
9706 -Checking that an Update_rows_log_event
9707 is valid is done while setting the Update_rows_log_event::is_valid
9708 */
9709 if (m_rows_buf && m_cols.bitmap)
9710 is_valid_param= true;
9711 DBUG_VOID_RETURN;
9712 }
9713
~Rows_log_event()9714 Rows_log_event::~Rows_log_event()
9715 {
9716 if (m_cols.bitmap)
9717 {
9718 if (m_cols.bitmap == m_bitbuf) // no my_malloc happened
9719 m_cols.bitmap= 0; // so no my_free in bitmap_free
9720 bitmap_free(&m_cols); // To pair with bitmap_init().
9721 }
9722 }
get_data_size()9723 size_t Rows_log_event::get_data_size()
9724 {
9725 int const general_type_code= get_general_type_code();
9726
9727 uchar buf[sizeof(m_width) + 1];
9728 uchar *end= net_store_length(buf, m_width);
9729
9730 DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master",
9731 return 6 + no_bytes_in_map(&m_cols) + (end - buf) +
9732 (general_type_code == binary_log::UPDATE_ROWS_EVENT ?
9733 no_bytes_in_map(&m_cols_ai) : 0) +
9734 (m_rows_cur - m_rows_buf););
9735
9736 int data_size= 0;
9737 bool is_v2_event= common_header->type_code > binary_log::DELETE_ROWS_EVENT_V1;
9738 if (is_v2_event)
9739 {
9740 data_size= Binary_log_event::ROWS_HEADER_LEN_V2 +
9741 (m_extra_row_data ?
9742 ROWS_V_TAG_LEN + m_extra_row_data[EXTRA_ROW_INFO_LEN_OFFSET]:
9743 0);
9744 }
9745 else
9746 {
9747 data_size= Binary_log_event::ROWS_HEADER_LEN_V1;
9748 }
9749 data_size+= no_bytes_in_map(&m_cols);
9750 data_size+= (uint) (end - buf);
9751
9752 if (general_type_code == binary_log::UPDATE_ROWS_EVENT)
9753 data_size+= no_bytes_in_map(&m_cols_ai);
9754
9755 data_size+= (uint) (m_rows_cur - m_rows_buf);
9756 return data_size;
9757 }
9758
9759
9760 #ifndef MYSQL_CLIENT
do_add_row_data(uchar * row_data,size_t length)9761 int Rows_log_event::do_add_row_data(uchar *row_data, size_t length)
9762 {
9763 /*
9764 When the table has a primary key, we would probably want, by default, to
9765 log only the primary key value instead of the entire "before image". This
9766 would save binlog space. TODO
9767 */
9768 DBUG_ENTER("Rows_log_event::do_add_row_data");
9769 DBUG_PRINT("enter", ("row_data: 0x%lx length: %lu", (ulong) row_data,
9770 (ulong) length));
9771
9772 /*
9773 If length is zero, there is nothing to write, so we just
9774 return. Note that this is not an optimization, since calling
9775 realloc() with size 0 means free().
9776 */
9777 if (length == 0)
9778 {
9779 m_row_count++;
9780 DBUG_RETURN(0);
9781 }
9782
9783 DBUG_DUMP("row_data", row_data, min<size_t>(length, 32));
9784
9785 assert(m_rows_buf <= m_rows_cur);
9786 assert(!m_rows_buf || (m_rows_end && m_rows_buf < m_rows_end));
9787 assert(m_rows_cur <= m_rows_end);
9788
9789 /* The cast will always work since m_rows_cur <= m_rows_end */
9790 if (static_cast<size_t>(m_rows_end - m_rows_cur) <= length)
9791 {
9792 size_t const block_size= 1024;
9793 ulong cur_size= m_rows_cur - m_rows_buf;
9794 DBUG_EXECUTE_IF("simulate_too_big_row_case1",
9795 cur_size= UINT_MAX32 - (block_size * 10);
9796 length= UINT_MAX32 - (block_size * 10););
9797 DBUG_EXECUTE_IF("simulate_too_big_row_case2",
9798 cur_size= UINT_MAX32 - (block_size * 10);
9799 length= block_size * 10;);
9800 DBUG_EXECUTE_IF("simulate_too_big_row_case3",
9801 cur_size= block_size * 10;
9802 length= UINT_MAX32 - (block_size * 10););
9803 DBUG_EXECUTE_IF("simulate_too_big_row_case4",
9804 cur_size= UINT_MAX32 - (block_size * 10);
9805 length= (block_size * 10) - block_size + 1;);
9806 ulong remaining_space= UINT_MAX32 - cur_size;
9807 /* Check that the new data fits within remaining space and we can add
9808 block_size without wrapping.
9809 */
9810 if (length > remaining_space ||
9811 ((length + block_size) > remaining_space))
9812 {
9813 sql_print_error("The row data is greater than 4GB, which is too big to "
9814 "write to the binary log.");
9815 DBUG_RETURN(ER_BINLOG_ROW_LOGGING_FAILED);
9816 }
9817 const size_t new_alloc=
9818 block_size * ((cur_size + length + block_size - 1) / block_size);
9819 if (new_alloc)
9820 row.resize(new_alloc);
9821
9822 /* If the memory moved, we need to move the pointers */
9823 if (new_alloc && &row[0] != m_rows_buf)
9824 {
9825 m_rows_buf= &row[0];
9826 if (m_rows_buf && m_cols.bitmap)
9827 is_valid_param= true;
9828 m_rows_cur= m_rows_buf + cur_size;
9829 }
9830
9831 /*
9832 The end pointer should always be changed to point to the end of
9833 the allocated memory.
9834 */
9835 m_rows_end= m_rows_buf + new_alloc;
9836 }
9837
9838 assert(m_rows_cur + length <= m_rows_end);
9839 memcpy(m_rows_cur, row_data, length);
9840 m_rows_cur+= length;
9841 m_row_count++;
9842 DBUG_RETURN(0);
9843 }
9844 #endif
9845
9846 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
9847
9848 /**
9849 Checks if any of the columns in the given table is
9850 signaled in the bitmap.
9851
9852 For each column in the given table checks if it is
9853 signaled in the bitmap. This is most useful when deciding
9854 whether a before image (BI) can be used or not for
9855 searching a row. If no column is signaled, then the
9856 image cannot be used for searching a record (regardless
9857 of using position(), index scan or table scan). Here is
9858 an example:
9859
9860 MASTER> SET @@binlog_row_image='MINIMAL';
9861 MASTER> CREATE TABLE t1 (a int, b int, c int, primary key(c));
9862 SLAVE> CREATE TABLE t1 (a int, b int);
9863 MASTER> INSERT INTO t1 VALUES (1,2,3);
9864 MASTER> UPDATE t1 SET a=2 WHERE b=2;
9865
9866 For the update statement only the PK (column c) is
9867 logged in the before image (BI). As such, given that
9868 the slave has no column c, it will not be able to
9869 find the row, because BI has no values for the columns
9870 the slave knows about (column a and b).
9871
9872 @param table the table reference on the slave.
9873 @param cols the bitmap signaling columns available in
9874 the BI.
9875
9876 @return TRUE if BI contains usable colums for searching,
9877 FALSE otherwise.
9878 */
9879 static
is_any_column_signaled_for_table(TABLE * table,MY_BITMAP * cols)9880 my_bool is_any_column_signaled_for_table(TABLE *table, MY_BITMAP *cols)
9881 {
9882 DBUG_ENTER("is_any_column_signaled_for_table");
9883
9884 for (Field **ptr= table->field ;
9885 *ptr && ((*ptr)->field_index < cols->n_bits);
9886 ptr++)
9887 {
9888 if (bitmap_is_set(cols, (*ptr)->field_index))
9889 DBUG_RETURN(TRUE);
9890 }
9891
9892 DBUG_RETURN (FALSE);
9893 }
9894
9895 /**
9896 Checks if the fields in the given key are signaled in
9897 the bitmap.
9898
9899 Validates whether the before image is usable for the
9900 given key. It can be the case that the before image
9901 does not contain values for the key (eg, master was
9902 using 'minimal' option for image logging and slave has
9903 different index structure on the table). Here is an
9904 example:
9905
9906 MASTER> SET @@binlog_row_image='MINIMAL';
9907 MASTER> CREATE TABLE t1 (a int, b int, c int, primary key(c));
9908 SLAVE> CREATE TABLE t1 (a int, b int, c int, key(a,c));
9909 MASTER> INSERT INTO t1 VALUES (1,2,3);
9910 MASTER> UPDATE t1 SET a=2 WHERE b=2;
9911
9912 When finding the row on the slave, one cannot use the
9913 index (a,c) to search for the row, because there is only
9914 data in the before image for column c. This function
9915 checks the fields needed for a given key and searches
9916 the bitmap to see if all the fields required are
9917 signaled.
9918
9919 @param keyinfo reference to key.
9920 @param cols the bitmap signaling which columns
9921 have available data.
9922
9923 @return TRUE if all fields are signaled in the bitmap
9924 for the given key, FALSE otherwise.
9925 */
9926 static
are_all_columns_signaled_for_key(KEY * keyinfo,MY_BITMAP * cols)9927 my_bool are_all_columns_signaled_for_key(KEY *keyinfo, MY_BITMAP *cols)
9928 {
9929 DBUG_ENTER("are_all_columns_signaled_for_key");
9930
9931 for (uint i=0 ; i < keyinfo->user_defined_key_parts ;i++)
9932 {
9933 uint fieldnr= keyinfo->key_part[i].fieldnr - 1;
9934 if (fieldnr >= cols->n_bits ||
9935 !bitmap_is_set(cols, fieldnr))
9936 DBUG_RETURN(FALSE);
9937 }
9938
9939 DBUG_RETURN(TRUE);
9940 }
9941
9942 /**
9943 Searches the table for a given key that can be used
9944 according to the existing values, ie, columns set
9945 in the bitmap.
9946
9947 The caller can specify which type of key to find by
9948 setting the following flags in the key_type parameter:
9949
9950 - PRI_KEY_FLAG
9951 Returns the primary key.
9952
9953 - UNIQUE_KEY_FLAG
9954 Returns a unique key (flagged with HA_NOSAME)
9955
9956 - MULTIPLE_KEY_FLAG
9957 Returns a key that is not unique (flagged with HA_NOSAME
9958 and without HA_NULL_PART_KEY) nor PK.
9959
9960 The above flags can be used together, in which case, the
9961 search is conducted in the above listed order. Eg, the
9962 following flag:
9963
9964 (PRI_KEY_FLAG | UNIQUE_KEY_FLAG | MULTIPLE_KEY_FLAG)
9965
9966 means that a primary key is returned if it is suitable. If
9967 not then the unique keys are searched. If no unique key is
9968 suitable, then the keys are searched. Finally, if no key
9969 is suitable, MAX_KEY is returned.
9970
9971 @param table reference to the table.
9972 @param bi_cols a bitmap that filters out columns that should
9973 not be considered while searching the key.
9974 Columns that should be considered are set.
9975 @param key_type the type of key to search for.
9976
9977 @return MAX_KEY if no key, according to the key_type specified
9978 is suitable. Returns the key otherwise.
9979
9980 */
9981 static
9982 uint
search_key_in_table(TABLE * table,MY_BITMAP * bi_cols,uint key_type)9983 search_key_in_table(TABLE *table, MY_BITMAP *bi_cols, uint key_type)
9984 {
9985 DBUG_ENTER("search_key_in_table");
9986
9987 KEY *keyinfo;
9988 uint res= MAX_KEY;
9989 uint key;
9990
9991 if (key_type & PRI_KEY_FLAG &&
9992 (table->s->primary_key < MAX_KEY))
9993 {
9994 DBUG_PRINT("debug", ("Searching for PK"));
9995 keyinfo= table->s->key_info + table->s->primary_key;
9996 if (are_all_columns_signaled_for_key(keyinfo, bi_cols))
9997 DBUG_RETURN(table->s->primary_key);
9998 }
9999
10000 if (key_type & UNIQUE_KEY_FLAG)
10001 {
10002 DBUG_PRINT("debug", ("Searching for UK"));
10003 for (key=0,keyinfo= table->key_info ;
10004 (key < table->s->keys) && (res == MAX_KEY);
10005 key++,keyinfo++)
10006 {
10007 /*
10008 - Unique keys cannot be disabled, thence we skip the check.
10009 - Skip unique keys with nullable parts
10010 - Skip primary keys
10011 */
10012 if (!((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME) ||
10013 (key == table->s->primary_key))
10014 continue;
10015 res= are_all_columns_signaled_for_key(keyinfo, bi_cols) ?
10016 key : MAX_KEY;
10017
10018 if (res < MAX_KEY)
10019 DBUG_RETURN(res);
10020 }
10021 DBUG_PRINT("debug", ("UK has NULLABLE parts or not all columns signaled."));
10022 }
10023
10024 if (key_type & MULTIPLE_KEY_FLAG && table->s->keys)
10025 {
10026 DBUG_PRINT("debug", ("Searching for K."));
10027 for (key=0,keyinfo= table->key_info ;
10028 (key < table->s->keys) && (res == MAX_KEY);
10029 key++,keyinfo++)
10030 {
10031 /*
10032 - Skip innactive keys
10033 - Skip unique keys without nullable parts
10034 - Skip indices that do not support ha_index_next() e.g. full-text
10035 - Skip primary keys
10036 */
10037 if (!(table->s->keys_in_use.is_set(key)) ||
10038 ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME) ||
10039 !(table->file->index_flags(key, 0, true) & HA_READ_NEXT) ||
10040 (key == table->s->primary_key))
10041 continue;
10042
10043 res= are_all_columns_signaled_for_key(keyinfo, bi_cols) ?
10044 key : MAX_KEY;
10045
10046 if (res < MAX_KEY)
10047 DBUG_RETURN(res);
10048 }
10049 DBUG_PRINT("debug", ("Not all columns signaled for K."));
10050 }
10051
10052 DBUG_RETURN(res);
10053 }
10054
10055 void
decide_row_lookup_algorithm_and_key()10056 Rows_log_event::decide_row_lookup_algorithm_and_key()
10057 {
10058
10059 DBUG_ENTER("decide_row_lookup_algorithm_and_key");
10060
10061 /*
10062 Decision table:
10063 - I --> Index scan / search
10064 - T --> Table scan
10065 - Hi --> Hash over index
10066 - Ht --> Hash over the entire table
10067
10068 |--------------+-----------+------+------+------|
10069 | Index\Option | I , T , H | I, T | I, H | T, H |
10070 |--------------+-----------+------+------+------|
10071 | PK / UK | I | I | I | Hi |
10072 | K | Hi | I | Hi | Hi |
10073 | No Index | Ht | T | Ht | Ht |
10074 |--------------+-----------+------+------+------|
10075
10076 */
10077
10078 TABLE *table= this->m_table;
10079 uint event_type= this->get_general_type_code();
10080 MY_BITMAP *cols= &this->m_cols;
10081 bool delete_update_lookup_condition= false;
10082 this->m_rows_lookup_algorithm= ROW_LOOKUP_NOT_NEEDED;
10083 this->m_key_index= MAX_KEY;
10084 this->m_key_info= NULL;
10085
10086 // row lookup not needed
10087 if (event_type == binary_log::WRITE_ROWS_EVENT ||
10088 (delete_update_lookup_condition= ((event_type == binary_log::DELETE_ROWS_EVENT ||
10089 event_type == binary_log::UPDATE_ROWS_EVENT) &&
10090 get_flags(COMPLETE_ROWS_F) &&
10091 !m_table->file->rpl_lookup_rows())))
10092 {
10093 if (delete_update_lookup_condition &&
10094 table->s->primary_key == MAX_KEY)
10095 {
10096 if (!table->s->rfr_lookup_warning)
10097 {
10098 sql_print_warning("Slave: read free replication is disabled "
10099 "for TokuDB/RocksDB table `%s.%s` "
10100 "as it does not have implicit primary key, "
10101 "continue with rows lookup",
10102 print_slave_db_safe(table->s->db.str),
10103 m_table->s->table_name.str);
10104 table->s->rfr_lookup_warning= true;
10105 }
10106 }
10107 else
10108 DBUG_VOID_RETURN;
10109 }
10110
10111 if (!(slave_rows_search_algorithms_options & SLAVE_ROWS_INDEX_SCAN))
10112 goto TABLE_OR_INDEX_HASH_SCAN;
10113
10114 /* PK or UK => use LOOKUP_INDEX_SCAN */
10115 this->m_key_index= search_key_in_table(table, cols, (PRI_KEY_FLAG | UNIQUE_KEY_FLAG));
10116 if (this->m_key_index != MAX_KEY)
10117 {
10118 DBUG_PRINT("info", ("decide_row_lookup_algorithm_and_key: decided - INDEX_SCAN"));
10119 this->m_rows_lookup_algorithm= ROW_LOOKUP_INDEX_SCAN;
10120 goto end;
10121 }
10122
10123 TABLE_OR_INDEX_HASH_SCAN:
10124
10125 /*
10126 NOTE: Engines like Blackhole cannot use HASH_SCAN, because
10127 they do not syncronize reads .
10128 */
10129 if (!(slave_rows_search_algorithms_options & SLAVE_ROWS_HASH_SCAN) ||
10130 (table->file->ha_table_flags() & HA_READ_OUT_OF_SYNC))
10131 goto TABLE_OR_INDEX_FULL_SCAN;
10132
10133 /* search for a key to see if we can narrow the lookup domain further. */
10134 this->m_key_index= search_key_in_table(table, cols, (PRI_KEY_FLAG | UNIQUE_KEY_FLAG | MULTIPLE_KEY_FLAG));
10135 this->m_rows_lookup_algorithm= ROW_LOOKUP_HASH_SCAN;
10136 if (m_key_index < MAX_KEY)
10137 m_distinct_key_spare_buf= (uchar*) thd->alloc(table->key_info[m_key_index].key_length);
10138 DBUG_PRINT("info", ("decide_row_lookup_algorithm_and_key: decided - HASH_SCAN"));
10139 goto end;
10140
10141 TABLE_OR_INDEX_FULL_SCAN:
10142
10143 this->m_key_index= MAX_KEY;
10144
10145 /* If we can use an index, try to narrow the scan a bit further. */
10146 if (slave_rows_search_algorithms_options & SLAVE_ROWS_INDEX_SCAN)
10147 this->m_key_index= search_key_in_table(table, cols, (PRI_KEY_FLAG | UNIQUE_KEY_FLAG | MULTIPLE_KEY_FLAG));
10148
10149 if (this->m_key_index != MAX_KEY)
10150 {
10151 DBUG_PRINT("info", ("decide_row_lookup_algorithm_and_key: decided - INDEX_SCAN"));
10152 this->m_rows_lookup_algorithm= ROW_LOOKUP_INDEX_SCAN;
10153 }
10154 else
10155 {
10156 DBUG_PRINT("info", ("decide_row_lookup_algorithm_and_key: decided - TABLE_SCAN"));
10157 this->m_rows_lookup_algorithm= ROW_LOOKUP_TABLE_SCAN;
10158 }
10159
10160 end:
10161
10162 /* m_key_index is ready, set m_key_info now. */
10163 m_key_info= m_table->key_info + m_key_index;
10164 /*
10165 m_key_info will influence key comparison code in HASH_SCAN mode,
10166 so the m_distinct_keys set should still be empty.
10167 */
10168 assert(m_distinct_keys.empty());
10169
10170 #ifndef NDEBUG
10171 const char* s= ((m_rows_lookup_algorithm == Rows_log_event::ROW_LOOKUP_TABLE_SCAN) ? "TABLE_SCAN" :
10172 ((m_rows_lookup_algorithm == Rows_log_event::ROW_LOOKUP_HASH_SCAN) ? "HASH_SCAN" :
10173 "INDEX_SCAN"));
10174
10175 // only for testing purposes
10176 slave_rows_last_search_algorithm_used= m_rows_lookup_algorithm;
10177 DBUG_PRINT("debug", ("Row lookup method: %s", s));
10178 #endif
10179
10180 DBUG_VOID_RETURN;
10181 }
10182
10183 /*
10184 Encapsulates the operations to be done before applying
10185 row events for update and delete.
10186
10187 @ret value error code
10188 0 success
10189 */
10190 int
row_operations_scan_and_key_setup()10191 Rows_log_event::row_operations_scan_and_key_setup()
10192 {
10193 int error= 0;
10194 DBUG_ENTER("Row_log_event::row_operations_scan_and_key_setup");
10195
10196 /*
10197 Prepare memory structures for search operations. If
10198 search is performed:
10199
10200 1. using hash search => initialize the hash
10201 2. using key => decide on key to use and allocate mem structures
10202 3. using table scan => do nothing
10203 */
10204 decide_row_lookup_algorithm_and_key();
10205
10206 switch (m_rows_lookup_algorithm)
10207 {
10208 case ROW_LOOKUP_HASH_SCAN:
10209 {
10210 if (m_hash.init())
10211 error= HA_ERR_OUT_OF_MEM;
10212 goto err;
10213 }
10214 case ROW_LOOKUP_INDEX_SCAN:
10215 {
10216 assert (m_key_index < MAX_KEY);
10217 // Allocate buffer for key searches
10218 m_key= (uchar*)my_malloc(key_memory_log_event,
10219 m_key_info->key_length, MYF(MY_WME));
10220 if (!m_key)
10221 error= HA_ERR_OUT_OF_MEM;
10222 goto err;
10223 }
10224 case ROW_LOOKUP_TABLE_SCAN:
10225 default: break;
10226 }
10227 err:
10228 DBUG_RETURN(error);
10229 }
10230
10231 /*
10232 Encapsulates the operations to be done after applying
10233 row events for update and delete.
10234
10235 @ret value error code
10236 0 success
10237 */
10238
10239 int
row_operations_scan_and_key_teardown(int error)10240 Rows_log_event::row_operations_scan_and_key_teardown(int error)
10241 {
10242 DBUG_ENTER("Rows_log_event::row_operations_scan_and_key_teardown");
10243
10244 assert(!m_table->file->inited);
10245 switch (m_rows_lookup_algorithm)
10246 {
10247 case ROW_LOOKUP_HASH_SCAN:
10248 {
10249 m_hash.deinit(); // we don't need the hash anymore.
10250 goto err;
10251 }
10252
10253 case ROW_LOOKUP_INDEX_SCAN:
10254 {
10255 if (m_table->s->keys > 0)
10256 {
10257 my_free(m_key); // Free for multi_malloc
10258 m_key= NULL;
10259 m_key_index= MAX_KEY;
10260 m_key_info= NULL;
10261 }
10262 goto err;
10263 }
10264
10265 case ROW_LOOKUP_TABLE_SCAN:
10266 default: break;
10267 }
10268
10269 err:
10270 m_rows_lookup_algorithm= ROW_LOOKUP_UNDEFINED;
10271 DBUG_RETURN(error);
10272 }
10273
10274 /*
10275 Compares table->record[0] and table->record[1]
10276
10277 Returns TRUE if different.
10278 */
record_compare(TABLE * table,MY_BITMAP * cols)10279 static bool record_compare(TABLE *table, MY_BITMAP *cols)
10280 {
10281 DBUG_ENTER("record_compare");
10282
10283 /*
10284 Need to set the X bit and the filler bits in both records since
10285 there are engines that do not set it correctly.
10286
10287 In addition, since MyISAM checks that one hasn't tampered with the
10288 record, it is necessary to restore the old bytes into the record
10289 after doing the comparison.
10290
10291 TODO[record format ndb]: Remove it once NDB returns correct
10292 records. Check that the other engines also return correct records.
10293 */
10294
10295 DBUG_DUMP("record[0]", table->record[0], table->s->reclength);
10296 DBUG_DUMP("record[1]", table->record[1], table->s->reclength);
10297
10298 bool result= false;
10299 uchar saved_x[2]= {0, 0}, saved_filler[2]= {0, 0};
10300
10301 if (table->s->null_bytes > 0)
10302 {
10303 for (int i = 0 ; i < 2 ; ++i)
10304 {
10305 /*
10306 If we have an X bit then we need to take care of it.
10307 */
10308 if (!(table->s->db_options_in_use & HA_OPTION_PACK_RECORD))
10309 {
10310 saved_x[i]= table->record[i][0];
10311 table->record[i][0]|= 1U;
10312 }
10313
10314 /*
10315 If (last_null_bit_pos == 0 && null_bytes > 1), then:
10316
10317 X bit (if any) + N nullable fields + M Field_bit fields = 8 bits
10318
10319 Ie, the entire byte is used.
10320 */
10321 if (table->s->last_null_bit_pos > 0)
10322 {
10323 saved_filler[i]= table->record[i][table->s->null_bytes - 1];
10324 table->record[i][table->s->null_bytes - 1]|=
10325 256U - (1U << table->s->last_null_bit_pos);
10326 }
10327 }
10328 }
10329
10330 /**
10331 Compare full record only if:
10332 - there are no blob fields (otherwise we would also need
10333 to compare blobs contents as well);
10334 - there are no varchar fields (otherwise we would also need
10335 to compare varchar contents as well);
10336 - there are no null fields, otherwise NULLed fields
10337 contents (i.e., the don't care bytes) may show arbitrary
10338 values, depending on how each engine handles internally.
10339 - if all the bitmap is set (both are full rows)
10340 */
10341 if ((table->s->blob_fields +
10342 table->s->varchar_fields +
10343 table->s->null_fields) == 0 &&
10344 bitmap_is_set_all(cols))
10345 {
10346 result= cmp_record(table,record[1]);
10347 }
10348
10349 /*
10350 Fallback to field-by-field comparison:
10351 1. start by checking if the field is signaled:
10352 2. if it is, first compare the null bit if the field is nullable
10353 3. then compare the contents of the field, if it is not
10354 set to null
10355 */
10356 else
10357 {
10358 for (Field **ptr=table->field ;
10359 *ptr && ((*ptr)->field_index < cols->n_bits) && !result;
10360 ptr++)
10361 {
10362 Field *field= *ptr;
10363 if (bitmap_is_set(cols, field->field_index) && !field->is_virtual_gcol())
10364 {
10365 /* compare null bit */
10366 if (field->is_null() != field->is_null_in_record(table->record[1]))
10367 result= true;
10368
10369 /* compare content, only if fields are not set to NULL */
10370 else if (!field->is_null())
10371 result= field->cmp_binary_offset(table->s->rec_buff_length);
10372 }
10373 }
10374 }
10375
10376 /*
10377 Restore the saved bytes.
10378
10379 TODO[record format ndb]: Remove this code once NDB returns the
10380 correct record format.
10381 */
10382 if (table->s->null_bytes > 0)
10383 {
10384 for (int i = 0 ; i < 2 ; ++i)
10385 {
10386 if (!(table->s->db_options_in_use & HA_OPTION_PACK_RECORD))
10387 table->record[i][0]= saved_x[i];
10388
10389 if (table->s->last_null_bit_pos)
10390 table->record[i][table->s->null_bytes - 1]= saved_filler[i];
10391 }
10392 }
10393
10394 DBUG_RETURN(result);
10395 }
10396
do_post_row_operations(Relay_log_info const * rli,int error)10397 void Rows_log_event::do_post_row_operations(Relay_log_info const *rli, int error)
10398 {
10399
10400 /*
10401 If m_curr_row_end was not set during event execution (e.g., because
10402 of errors) we can't proceed to the next row. If the error is transient
10403 (i.e., error==0 at this point) we must call unpack_current_row() to set
10404 m_curr_row_end.
10405 */
10406
10407 DBUG_PRINT("info", ("curr_row: 0x%lu; curr_row_end: 0x%lu; rows_end: 0x%lu",
10408 (ulong) m_curr_row, (ulong) m_curr_row_end, (ulong) m_rows_end));
10409
10410 if (!m_curr_row_end && !error)
10411 {
10412 const uchar *previous_m_curr_row= m_curr_row;
10413 error= unpack_current_row(rli, &m_cols);
10414
10415 if (!error && previous_m_curr_row == m_curr_row)
10416 {
10417 error= 1;
10418 }
10419 }
10420
10421 // at this moment m_curr_row_end should be set
10422 assert(error || m_curr_row_end != NULL);
10423 assert(error || m_curr_row <= m_curr_row_end);
10424 assert(error || m_curr_row_end <= m_rows_end);
10425
10426 m_curr_row= m_curr_row_end;
10427
10428 if (error == 0 && !m_table->file->has_transactions())
10429 {
10430 thd->get_transaction()->set_unsafe_rollback_flags(Transaction_ctx::SESSION,
10431 TRUE);
10432 thd->get_transaction()->set_unsafe_rollback_flags(Transaction_ctx::STMT,
10433 TRUE);
10434 }
10435 }
10436
handle_idempotent_and_ignored_errors(Relay_log_info const * rli,int * err)10437 int Rows_log_event::handle_idempotent_and_ignored_errors(Relay_log_info const *rli, int *err)
10438 {
10439 int error= *err;
10440 if (error)
10441 {
10442 int actual_error= convert_handler_error(error, thd, m_table);
10443 bool idempotent_error= (idempotent_error_code(error) &&
10444 (rbr_exec_mode == RBR_EXEC_MODE_IDEMPOTENT));
10445 bool ignored_error= (idempotent_error == 0 ?
10446 ignored_error_code(actual_error) : 0);
10447
10448 if (idempotent_error || ignored_error)
10449 {
10450 loglevel ll;
10451 if (idempotent_error)
10452 ll= WARNING_LEVEL;
10453 else
10454 ll= INFORMATION_LEVEL;
10455 slave_rows_error_report(ll, error, rli, thd, m_table,
10456 get_type_str(),
10457 const_cast<Relay_log_info*>(rli)->get_rpl_log_name(),
10458 (ulong) common_header->log_pos);
10459 thd->get_stmt_da()->reset_condition_info(thd);
10460 clear_all_errors(thd, const_cast<Relay_log_info*>(rli));
10461 *err= 0;
10462 if (idempotent_error == 0)
10463 return ignored_error;
10464 }
10465 }
10466
10467 return *err;
10468 }
10469
do_apply_row(Relay_log_info const * rli)10470 int Rows_log_event::do_apply_row(Relay_log_info const *rli)
10471 {
10472 DBUG_ENTER("Rows_log_event::do_apply_row");
10473
10474 int error= 0;
10475
10476 /* in_use can have been set to NULL in close_tables_for_reopen */
10477 THD* old_thd= m_table->in_use;
10478 if (!m_table->in_use)
10479 m_table->in_use= thd;
10480
10481 error= do_exec_row(rli);
10482
10483 if(error)
10484 {
10485 DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
10486 assert(error != HA_ERR_RECORD_DELETED);
10487 }
10488
10489 m_table->in_use = old_thd;
10490
10491 DBUG_RETURN(error);
10492 }
10493
10494 /**
10495 Does the cleanup
10496 - closes the index if opened by open_record_scan
10497 - closes the table if opened for scanning.
10498 */
10499 int
close_record_scan()10500 Rows_log_event::close_record_scan()
10501 {
10502 DBUG_ENTER("Rows_log_event::close_record_scan");
10503 int error= 0;
10504
10505 // if there is something to actually close
10506 if (m_key_index < MAX_KEY)
10507 {
10508 if (m_table->file->inited)
10509 error= m_table->file->ha_index_end();
10510 }
10511 else if (m_table->file->inited)
10512 error= m_table->file->ha_rnd_end();
10513
10514 DBUG_RETURN(error);
10515 }
10516
10517 /**
10518 Fetches next row. If it is a HASH_SCAN over an index, it populates
10519 table->record[0] with the next row corresponding to the index. If
10520 the indexes are in non-contigous ranges it fetches record corresponding
10521 to the key value in the next range.
10522
10523 @parms: bool first_read : signifying if this is the first time we are reading a row
10524 over an index.
10525 @return_value: - error code when there are no more reeords to be fetched or some other
10526 error occured,
10527 - 0 otherwise.
10528 */
10529 int
next_record_scan(bool first_read)10530 Rows_log_event::next_record_scan(bool first_read)
10531 {
10532 DBUG_ENTER("Rows_log_event::next_record_scan");
10533 assert(m_table->file->inited);
10534 TABLE *table= m_table;
10535 int error= 0;
10536
10537 if (m_key_index >= MAX_KEY)
10538 error= table->file->ha_rnd_next(table->record[0]);
10539 else
10540 {
10541 /*
10542 We need to set the null bytes to ensure that the filler bit are
10543 all set when returning. There are storage engines that just set
10544 the necessary bits on the bytes and don't set the filler bits
10545 correctly.
10546 */
10547 if (table->s->null_bytes > 0)
10548 table->record[0][table->s->null_bytes - 1]|=
10549 256U - (1U << table->s->last_null_bit_pos);
10550
10551 if (!first_read)
10552 {
10553 /*
10554 if we fail to fetch next record corresponding to a key value, we
10555 move to the next key value. If we are out of key values as well an error
10556 will be returned.
10557 */
10558 error= table->file->ha_index_next_same(table->record[0], m_key,
10559 m_key_info->key_length);
10560 if(m_rows_lookup_algorithm == ROW_LOOKUP_HASH_SCAN)
10561 {
10562 /*
10563 if we are out of rows for this particular key value, we reposition the
10564 marker according to the next key value that we have in the list.
10565 */
10566 if (error)
10567 {
10568 if (m_itr != m_distinct_keys.end())
10569 {
10570 m_key= *m_itr;
10571 m_itr++;
10572 first_read= true;
10573 }
10574 else
10575 error= HA_ERR_KEY_NOT_FOUND;
10576 }
10577 }
10578 }
10579
10580 if (first_read)
10581 if ((error= table->file->ha_index_read_map(table->record[0], m_key,
10582 HA_WHOLE_KEY,
10583 HA_READ_KEY_EXACT)))
10584 {
10585 DBUG_PRINT("info",("no record matching the key found in the table"));
10586 if (error == HA_ERR_RECORD_DELETED)
10587 error= HA_ERR_KEY_NOT_FOUND;
10588 }
10589 }
10590
10591 DBUG_RETURN(error);
10592 }
10593
10594 /**
10595 Initializes scanning of rows. Opens an index and initializes an iterator
10596 over a list of distinct keys (m_distinct_keys) if it is a HASH_SCAN
10597 over an index or the table if its a HASH_SCAN over the table.
10598 */
10599 int
open_record_scan()10600 Rows_log_event::open_record_scan()
10601 {
10602 int error= 0;
10603 TABLE *table= m_table;
10604 DBUG_ENTER("Rows_log_event::open_record_scan");
10605
10606 if (m_key_index < MAX_KEY )
10607 {
10608 if(m_rows_lookup_algorithm == ROW_LOOKUP_HASH_SCAN)
10609 {
10610 /* initialize the iterator over the list of distinct keys that we have */
10611 m_itr= m_distinct_keys.begin();
10612
10613 /* get the first element from the list of keys and increment the
10614 iterator
10615 */
10616 m_key= *m_itr;
10617 m_itr++;
10618 }
10619 else {
10620 /* this is an INDEX_SCAN we need to store the key in m_key */
10621 assert((m_rows_lookup_algorithm == ROW_LOOKUP_INDEX_SCAN) && m_key);
10622 key_copy(m_key, m_table->record[0], m_key_info, 0);
10623 }
10624
10625 /*
10626 Save copy of the record in table->record[1]. It might be needed
10627 later if linear search is used to find exact match.
10628 */
10629 store_record(table,record[1]);
10630
10631 DBUG_PRINT("info",("locating record using a key (index_read)"));
10632
10633 /* The m_key_index'th key is active and usable: search the table using the index */
10634 if (!table->file->inited && (error= table->file->ha_index_init(m_key_index, FALSE)))
10635 {
10636 DBUG_PRINT("info",("ha_index_init returns error %d",error));
10637 goto end;
10638 }
10639
10640 DBUG_DUMP("key data", m_key, m_key_info->key_length);
10641 }
10642 else
10643 {
10644 if ((error= table->file->ha_rnd_init(1)))
10645 {
10646 DBUG_PRINT("info",("error initializing table scan"
10647 " (ha_rnd_init returns %d)",error));
10648 table->file->print_error(error, MYF(0));
10649 }
10650 }
10651
10652 end:
10653 DBUG_RETURN(error);
10654 }
10655
10656 /**
10657 Populates the m_distinct_keys with unique keys to be modified
10658 during HASH_SCAN over keys.
10659 @return_value -0 success
10660 -Err_code
10661 */
10662 int
add_key_to_distinct_keyset()10663 Rows_log_event::add_key_to_distinct_keyset()
10664 {
10665 int error= 0;
10666 DBUG_ENTER("Rows_log_event::add_key_to_distinct_keyset");
10667 assert(m_key_index < MAX_KEY);
10668 key_copy(m_distinct_key_spare_buf, m_table->record[0], m_key_info, 0);
10669 std::pair<std::set<uchar *, Key_compare>::iterator,bool> ret=
10670 m_distinct_keys.insert(m_distinct_key_spare_buf);
10671 if (ret.second)
10672 {
10673 /* Insert is successful, so allocate a new buffer for next key */
10674 m_distinct_key_spare_buf= (uchar*) thd->alloc(m_key_info->key_length);
10675 if (!m_distinct_key_spare_buf)
10676 {
10677 error= HA_ERR_OUT_OF_MEM;
10678 goto err;
10679 }
10680 }
10681
10682 err:
10683 DBUG_RETURN(error);
10684 }
10685
10686
do_index_scan_and_update(Relay_log_info const * rli)10687 int Rows_log_event::do_index_scan_and_update(Relay_log_info const *rli)
10688 {
10689 DBUG_ENTER("Rows_log_event::do_index_scan_and_update");
10690 assert(m_table && m_table->in_use != NULL);
10691
10692 int error= 0;
10693 const uchar *saved_m_curr_row= m_curr_row;
10694
10695 /*
10696 rpl_row_tabledefs.test specifies that
10697 if the extra field on the slave does not have a default value
10698 and this is okay with Delete or Update events.
10699 Todo: fix wl3228 hld that requires defaults for all types of events
10700 */
10701
10702 prepare_record(m_table, &m_cols, FALSE);
10703 if ((error= unpack_current_row(rli, &m_cols)))
10704 goto end;
10705
10706 /*
10707 Trying to do an index scan without a usable key
10708 This is a valid state because we allow the user
10709 to set Slave_rows_search_algorithm= 'INDEX_SCAN'.
10710
10711 Therefore on tables with no indexes we will end
10712 up here.
10713 */
10714 if (m_key_index >= MAX_KEY)
10715 {
10716 error= HA_ERR_END_OF_FILE;
10717 goto end;
10718 }
10719
10720 #ifndef NDEBUG
10721 DBUG_PRINT("info",("looking for the following record"));
10722 DBUG_DUMP("record[0]", m_table->record[0], m_table->s->reclength);
10723 #endif
10724
10725 if (m_key_index != m_table->s->primary_key)
10726 /* we dont have a PK, or PK is not usable */
10727 goto INDEX_SCAN;
10728
10729 if ((m_table->file->ha_table_flags() & HA_READ_BEFORE_WRITE_REMOVAL))
10730 {
10731 /*
10732 Read removal is possible since the engine supports write without
10733 previous read using full primary key
10734 */
10735 DBUG_PRINT("info", ("using read before write removal"));
10736 assert(m_key_index == m_table->s->primary_key);
10737
10738 /*
10739 Tell the handler to ignore if key exists or not, since it's
10740 not yet known if the key does exist(when using rbwr)
10741 */
10742 m_table->file->extra(HA_EXTRA_IGNORE_NO_KEY);
10743
10744 goto end;
10745 }
10746
10747 if ((m_table->file->ha_table_flags() & HA_PRIMARY_KEY_REQUIRED_FOR_POSITION))
10748 {
10749 /*
10750 Use a more efficient method to fetch the record given by
10751 table->record[0] if the engine allows it. We first compute a
10752 row reference using the position() member function (it will be
10753 stored in table->file->ref) and then use rnd_pos() to position
10754 the "cursor" (i.e., record[0] in this case) at the correct row.
10755
10756 TODO: Check that the correct record has been fetched by
10757 comparing it with the original record. Take into account that the
10758 record on the master and slave can be of different
10759 length. Something along these lines should work:
10760
10761 ADD>>> store_record(table,record[1]);
10762 int error= table->file->rnd_pos(table->record[0], table->file->ref);
10763 ADD>>> assert(memcmp(table->record[1], table->record[0],
10764 table->s->reclength) == 0);
10765
10766 */
10767
10768 DBUG_PRINT("info",("locating record using primary key (position)"));
10769 if (m_table->file->inited && (error= m_table->file->ha_index_end()))
10770 goto end;
10771
10772 error= m_table->file->rnd_pos_by_record(m_table->record[0]);
10773 if (error)
10774 {
10775 DBUG_PRINT("info",("rnd_pos returns error %d",error));
10776 if (error == HA_ERR_RECORD_DELETED)
10777 error= HA_ERR_KEY_NOT_FOUND;
10778 }
10779
10780 goto end;
10781 }
10782
10783 // We can't use position() - try other methods.
10784
10785 INDEX_SCAN:
10786
10787 /* Use the m_key_index'th key */
10788
10789 if ((error= open_record_scan()))
10790 goto end;
10791
10792 error= next_record_scan(true);
10793 if (error)
10794 {
10795 DBUG_PRINT("info",("no record matching the key found in the table"));
10796 if (error == HA_ERR_RECORD_DELETED)
10797 error= HA_ERR_KEY_NOT_FOUND;
10798 goto end;
10799 }
10800
10801
10802 DBUG_PRINT("info",("found first matching record"));
10803 DBUG_DUMP("record[0]", m_table->record[0], m_table->s->reclength);
10804 /*
10805 Below is a minor "optimization". If the key (i.e., key number
10806 0) has the HA_NOSAME flag set, we know that we have found the
10807 correct record (since there can be no duplicates); otherwise, we
10808 have to compare the record with the one found to see if it is
10809 the correct one.
10810
10811 CAVEAT! This behaviour is essential for the replication of,
10812 e.g., the mysql.proc table since the correct record *shall* be
10813 found using the primary key *only*. There shall be no
10814 comparison of non-PK columns to decide if the correct record is
10815 found. I can see no scenario where it would be incorrect to
10816 chose the row to change only using a PK or an UNNI.
10817 */
10818 if (m_key_info->flags & HA_NOSAME || m_key_index == m_table->s->primary_key)
10819 {
10820 /* Unique does not have non nullable part */
10821 if (!(m_key_info->flags & (HA_NULL_PART_KEY)))
10822 goto end; // record found
10823 else
10824 {
10825 /*
10826 Unique has nullable part. We need to check if there is any field in the
10827 BI image that is null and part of UNNI.
10828 */
10829 bool null_found= FALSE;
10830 for (uint i=0; i < m_key_info->user_defined_key_parts && !null_found; i++)
10831 {
10832 uint fieldnr= m_key_info->key_part[i].fieldnr - 1;
10833 Field **f= m_table->field+fieldnr;
10834 null_found= (*f)->is_null();
10835 }
10836
10837 if (!null_found)
10838 goto end; // record found
10839
10840 /* else fall through to index scan */
10841 }
10842 }
10843
10844 /*
10845 In case key is not unique, we still have to iterate over records found
10846 and find the one which is identical to the row given. A copy of the
10847 record we are looking for is stored in record[1].
10848 */
10849 DBUG_PRINT("info",("non-unique index, scanning it to find matching record"));
10850
10851 while (record_compare(m_table, &m_cols))
10852 {
10853 while((error= next_record_scan(false)))
10854 {
10855 /* We just skip records that has already been deleted */
10856 if (error == HA_ERR_RECORD_DELETED)
10857 continue;
10858 DBUG_PRINT("info",("no record matching the given row found"));
10859 goto end;
10860 }
10861 }
10862
10863 end:
10864
10865 assert(error != HA_ERR_RECORD_DELETED);
10866
10867 if (error && error != HA_ERR_RECORD_DELETED)
10868 m_table->file->print_error(error, MYF(0));
10869 else
10870 error= do_apply_row(rli);
10871
10872 if (!error)
10873 error= close_record_scan();
10874 else
10875 /*
10876 we are already with errors. Keep the error code and
10877 try to close the scan anyway.
10878 */
10879 (void) close_record_scan();
10880
10881 if ((get_general_type_code() == binary_log::UPDATE_ROWS_EVENT) &&
10882 (saved_m_curr_row == m_curr_row))
10883 {
10884 /* we need to unpack the AI so that positions get updated */
10885 m_curr_row= m_curr_row_end;
10886 unpack_current_row(rli, &m_cols_ai);
10887 }
10888 m_table->default_column_bitmaps();
10889 DBUG_RETURN(error);
10890
10891 }
10892
do_hash_row(Relay_log_info const * rli)10893 int Rows_log_event::do_hash_row(Relay_log_info const *rli)
10894 {
10895 DBUG_ENTER("Rows_log_event::do_hash_row");
10896 assert(m_table && m_table->in_use != NULL);
10897 int error= 0;
10898
10899 /* create an empty entry to add to the hash table */
10900 HASH_ROW_ENTRY* entry= m_hash.make_entry();
10901 if (entry == NULL)
10902 {
10903 error= 1;
10904 goto end;
10905 }
10906 /* Prepare the record, unpack and save positions. */
10907 entry->positions->bi_start= m_curr_row; // save the bi start pos
10908 prepare_record(m_table, &m_cols, false);
10909 if ((error= unpack_current_row(rli, &m_cols)))
10910 goto end;
10911 entry->positions->bi_ends= m_curr_row_end; // save the bi end pos
10912
10913 /*
10914 Now that m_table->record[0] is filled in, we can add the entry
10915 to the hash table. Note that the put operation calculates the
10916 key based on record[0] contents (including BLOB fields).
10917 */
10918 m_hash.put(m_table, &m_cols, entry);
10919
10920 if (m_key_index < MAX_KEY)
10921 add_key_to_distinct_keyset();
10922
10923 /*
10924 We need to unpack the AI to advance the positions, so we
10925 know when we have reached m_rows_end and that we do not
10926 unpack the AI in the next iteration as if it was a BI.
10927 */
10928 if (get_general_type_code() == binary_log::UPDATE_ROWS_EVENT)
10929 {
10930 /* Save a copy of the BI. */
10931 store_record(m_table, record[1]);
10932
10933 /*
10934 This is the situation after hashing the BI:
10935
10936 ===|=== before image ====|=== after image ===|===
10937 ^ ^
10938 m_curr_row m_curr_row_end
10939 */
10940
10941 /* Set the position to the start of the record to be unpacked. */
10942 m_curr_row= m_curr_row_end;
10943
10944 /* We shouldn't need this, but lets not leave loose ends */
10945 prepare_record(m_table, &m_cols, false);
10946 error= unpack_current_row(rli, &m_cols_ai);
10947
10948 /*
10949 This is the situation after unpacking the AI:
10950
10951 ===|=== before image ====|=== after image ===|===
10952 ^ ^
10953 m_curr_row m_curr_row_end
10954 */
10955
10956 /* Restore back the copy of the BI. */
10957 restore_record(m_table, record[1]);
10958 }
10959
10960 end:
10961 DBUG_RETURN(error);
10962 }
10963
do_scan_and_update(Relay_log_info const * rli)10964 int Rows_log_event::do_scan_and_update(Relay_log_info const *rli)
10965 {
10966 DBUG_ENTER("Rows_log_event::do_scan_and_update");
10967 assert(m_table && m_table->in_use != NULL);
10968 assert(m_hash.is_empty() == false);
10969 TABLE *table= m_table;
10970 int error= 0;
10971 const uchar *saved_last_m_curr_row= NULL;
10972 const uchar *saved_last_m_curr_row_end= NULL;
10973 /* create an empty entry to add to the hash table */
10974 HASH_ROW_ENTRY* entry= NULL;
10975 int idempotent_errors= 0;
10976 int i= 0;
10977
10978 saved_last_m_curr_row=m_curr_row;
10979 saved_last_m_curr_row_end=m_curr_row_end;
10980
10981 DBUG_PRINT("info",("Hash was populated with %d records!", m_hash.size()));
10982
10983 /* open table or index depending on whether we have set m_key_index or not. */
10984 if ((error= open_record_scan()))
10985 goto err;
10986
10987 /*
10988 Scan the table only once and compare against entries in hash.
10989 When a match is found, apply the changes.
10990 */
10991 do
10992 {
10993 /* get the next record from the table */
10994 error= next_record_scan(i == 0);
10995 i++;
10996
10997 if(error)
10998 DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
10999 switch (error) {
11000 case 0:
11001 {
11002 entry= m_hash.get(table, &m_cols);
11003 store_record(table, record[1]);
11004
11005 /**
11006 If there are collisions we need to be sure that this is
11007 indeed the record we want. Loop through all records for
11008 the given key and explicitly compare them against the
11009 record we got from the storage engine.
11010 */
11011 while(entry)
11012 {
11013 m_curr_row= entry->positions->bi_start;
11014 m_curr_row_end= entry->positions->bi_ends;
11015
11016 prepare_record(table, &m_cols, false);
11017 if ((error= unpack_current_row(rli, &m_cols)))
11018 goto close_table;
11019
11020 if (record_compare(table, &m_cols))
11021 m_hash.next(&entry);
11022 else
11023 break; // we found a match
11024 }
11025
11026 /**
11027 We found the entry we needed, just apply the changes.
11028 */
11029 if (entry)
11030 {
11031 // just to be safe, copy the record from the SE to table->record[0]
11032 restore_record(table, record[1]);
11033
11034 /**
11035 At this point, both table->record[0] and
11036 table->record[1] have the SE row that matched the one
11037 in the hash table.
11038
11039 Thence if this is a DELETE we wouldn't need to mess
11040 around with positions anymore, but since this can be an
11041 update, we need to provide positions so that AI is
11042 unpacked correctly to table->record[0] in UPDATE
11043 implementation of do_exec_row().
11044 */
11045 m_curr_row= entry->positions->bi_start;
11046 m_curr_row_end= entry->positions->bi_ends;
11047
11048 /* we don't need this entry anymore, just delete it */
11049 if ((error= m_hash.del(entry)))
11050 goto err;
11051
11052 if ((error= do_apply_row(rli)))
11053 {
11054 if (handle_idempotent_and_ignored_errors(rli, &error))
11055 goto close_table;
11056
11057 do_post_row_operations(rli, error);
11058 }
11059 }
11060 }
11061 break;
11062
11063 case HA_ERR_RECORD_DELETED:
11064 // get next
11065 continue;
11066
11067 case HA_ERR_KEY_NOT_FOUND:
11068 /* If the slave exec mode is idempotent or the error is
11069 skipped error, then don't break */
11070 if (handle_idempotent_and_ignored_errors(rli, &error))
11071 goto close_table;
11072 idempotent_errors++;
11073 continue;
11074
11075 case HA_ERR_END_OF_FILE:
11076 default:
11077 // exception (hash is not empty and we have reached EOF or
11078 // other error happened)
11079 goto close_table;
11080 }
11081 }
11082 /**
11083 if the rbr_exec_mode is set to Idempotent, we cannot expect the hash to
11084 be empty. In such cases we count the number of idempotent errors and check
11085 if it is equal to or greater than the number of rows left in the hash.
11086 */
11087 while (((idempotent_errors < m_hash.size()) && !m_hash.is_empty()) &&
11088 (!error || (error == HA_ERR_RECORD_DELETED)));
11089
11090 close_table:
11091 if (error == HA_ERR_RECORD_DELETED)
11092 error= 0;
11093
11094 if (error)
11095 {
11096 table->file->print_error(error, MYF(0));
11097 DBUG_PRINT("info", ("Failed to get next record"
11098 " (ha_rnd_next returns %d)",error));
11099 /*
11100 we are already with errors. Keep the error code and
11101 try to close the scan anyway.
11102 */
11103 (void) close_record_scan();
11104 }
11105 else
11106 error= close_record_scan();
11107
11108 assert((m_hash.is_empty() && !error) ||
11109 (!m_hash.is_empty() &&
11110 ((error) || (idempotent_errors >= m_hash.size()))));
11111
11112 err:
11113
11114 if ((m_hash.is_empty() && !error) || (idempotent_errors >= m_hash.size()))
11115 {
11116 /**
11117 Reset the last positions, because the positions are lost while
11118 handling entries in the hash.
11119 */
11120 m_curr_row= saved_last_m_curr_row;
11121 m_curr_row_end= saved_last_m_curr_row_end;
11122 }
11123
11124 DBUG_RETURN(error);
11125 }
11126
do_hash_scan_and_update(Relay_log_info const * rli)11127 int Rows_log_event::do_hash_scan_and_update(Relay_log_info const *rli)
11128 {
11129 DBUG_ENTER("Rows_log_event::do_hash_scan_and_update");
11130 assert(m_table && m_table->in_use != NULL);
11131
11132 // HASHING PART
11133
11134 /* unpack the BI (and AI, if it exists) and add it to the hash map. */
11135 if (int error= this->do_hash_row(rli))
11136 DBUG_RETURN(error);
11137
11138 /* We have not yet hashed all rows in the buffer. Do not proceed to the SCAN part. */
11139 if (m_curr_row_end < m_rows_end)
11140 DBUG_RETURN (0);
11141
11142 DBUG_PRINT("info",("Hash was populated with %d records!", m_hash.size()));
11143 assert(m_curr_row_end == m_rows_end);
11144
11145 // SCANNING & UPDATE PART
11146
11147 DBUG_RETURN(this->do_scan_and_update(rli));
11148 }
11149
do_table_scan_and_update(Relay_log_info const * rli)11150 int Rows_log_event::do_table_scan_and_update(Relay_log_info const *rli)
11151 {
11152 int error= 0;
11153 const uchar* saved_m_curr_row= m_curr_row;
11154 TABLE* table= m_table;
11155
11156 DBUG_ENTER("Rows_log_event::do_table_scan_and_update");
11157 assert(m_curr_row != m_rows_end);
11158 DBUG_PRINT("info",("locating record using table scan (ha_rnd_next)"));
11159
11160 saved_m_curr_row= m_curr_row;
11161
11162 /** unpack the before image */
11163 prepare_record(table, &m_cols, FALSE);
11164 if (!(error= unpack_current_row(rli, &m_cols)))
11165 {
11166 /** save a copy so that we can compare against it later */
11167 store_record(m_table, record[1]);
11168
11169 int restart_count= 0; // Number of times scanning has restarted from top
11170
11171 if ((error= m_table->file->ha_rnd_init(1)))
11172 {
11173 DBUG_PRINT("info",("error initializing table scan"
11174 " (ha_rnd_init returns %d)",error));
11175 goto end;
11176 }
11177
11178 /* Continue until we find the right record or have made a full loop */
11179 do
11180 {
11181 restart_ha_rnd_next:
11182 error= m_table->file->ha_rnd_next(m_table->record[0]);
11183 if (error)
11184 DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
11185 switch (error) {
11186 case HA_ERR_END_OF_FILE:
11187 // restart scan from top
11188 if (++restart_count < 2)
11189 {
11190 if ((error= m_table->file->ha_rnd_init(1)))
11191 goto end;
11192 goto restart_ha_rnd_next;
11193 }
11194 break;
11195
11196 case HA_ERR_RECORD_DELETED:
11197 // fetch next
11198 goto restart_ha_rnd_next;
11199 case 0:
11200 // we're good, check if record matches
11201 break;
11202
11203 default:
11204 // exception
11205 goto end;
11206 }
11207 }
11208 while (restart_count < 2 && record_compare(m_table, &m_cols));
11209 }
11210
11211 end:
11212
11213 assert(error != HA_ERR_RECORD_DELETED);
11214
11215 /* either we report error or apply the changes */
11216 if (error && error != HA_ERR_RECORD_DELETED)
11217 {
11218 DBUG_PRINT("info", ("Failed to get next record"
11219 " (ha_rnd_next returns %d)",error));
11220 m_table->file->print_error(error, MYF(0));
11221 }
11222 else
11223 error= do_apply_row(rli);
11224
11225
11226 if (!error)
11227 error= close_record_scan();
11228 else
11229 /*
11230 we are already with errors. Keep the error code and
11231 try to close the scan anyway.
11232 */
11233 (void) close_record_scan();
11234
11235 if ((get_general_type_code() == binary_log::UPDATE_ROWS_EVENT) &&
11236 (saved_m_curr_row == m_curr_row)) // we need to unpack the AI
11237 {
11238 m_curr_row= m_curr_row_end;
11239 unpack_current_row(rli, &m_cols);
11240 }
11241
11242 table->default_column_bitmaps();
11243 DBUG_RETURN(error);
11244 }
11245
do_apply_event(Relay_log_info const * rli)11246 int Rows_log_event::do_apply_event(Relay_log_info const *rli)
11247 {
11248 DBUG_ENTER("Rows_log_event::do_apply_event(Relay_log_info*)");
11249 TABLE *table= NULL;
11250 int error= 0;
11251
11252 /*
11253 'thd' has been set by exec_relay_log_event(), just before calling
11254 do_apply_event(). We still check here to prevent future coding
11255 errors.
11256 */
11257 assert(rli->info_thd == thd);
11258
11259 /*
11260 If there is no locks taken, this is the first binrow event seen
11261 after the table map events. We should then lock all the tables
11262 used in the transaction and proceed with execution of the actual
11263 event.
11264 */
11265 if (!thd->lock)
11266 {
11267 /*
11268 Lock_tables() reads the contents of thd->lex, so they must be
11269 initialized.
11270
11271 We also call the mysql_reset_thd_for_next_command(), since this
11272 is the logical start of the next "statement". Note that this
11273 call might reset the value of current_stmt_binlog_format, so
11274 we need to do any changes to that value after this function.
11275 */
11276 lex_start(thd);
11277 mysql_reset_thd_for_next_command(thd);
11278
11279 enum_gtid_statement_status state= gtid_pre_statement_checks(thd);
11280 if (state == GTID_STATEMENT_EXECUTE)
11281 {
11282 if (gtid_pre_statement_post_implicit_commit_checks(thd))
11283 state= GTID_STATEMENT_CANCEL;
11284 }
11285
11286 if (state == GTID_STATEMENT_CANCEL)
11287 {
11288 uint error= thd->get_stmt_da()->mysql_errno();
11289 assert(error != 0);
11290 rli->report(ERROR_LEVEL, error,
11291 "Error executing row event: '%s'",
11292 thd->get_stmt_da()->message_text());
11293 thd->is_slave_error= 1;
11294 DBUG_RETURN(-1);
11295 }
11296 else if (state == GTID_STATEMENT_SKIP)
11297 goto end;
11298
11299 /*
11300 The current statement is just about to begin and
11301 has not yet modified anything. Note, all.modified is reset
11302 by mysql_reset_thd_for_next_command.
11303 */
11304 thd->get_transaction()->reset_unsafe_rollback_flags(Transaction_ctx::STMT);
11305 /*
11306 This is a row injection, so we flag the "statement" as
11307 such. Note that this code is called both when the slave does row
11308 injections and when the BINLOG statement is used to do row
11309 injections.
11310 */
11311 thd->lex->set_stmt_row_injection();
11312
11313 /*
11314 There are a few flags that are replicated with each row event.
11315 Make sure to set/clear them before executing the main body of
11316 the event.
11317 */
11318 if (get_flags(NO_FOREIGN_KEY_CHECKS_F))
11319 thd->variables.option_bits|= OPTION_NO_FOREIGN_KEY_CHECKS;
11320 else
11321 thd->variables.option_bits&= ~OPTION_NO_FOREIGN_KEY_CHECKS;
11322
11323 if (get_flags(RELAXED_UNIQUE_CHECKS_F))
11324 thd->variables.option_bits|= OPTION_RELAXED_UNIQUE_CHECKS;
11325 else
11326 thd->variables.option_bits&= ~OPTION_RELAXED_UNIQUE_CHECKS;
11327
11328 thd->binlog_row_event_extra_data = m_extra_row_data;
11329
11330 /* A small test to verify that objects have consistent types */
11331 assert(sizeof(thd->variables.option_bits) == sizeof(OPTION_RELAXED_UNIQUE_CHECKS));
11332 DBUG_EXECUTE_IF("rows_log_event_before_open_table",
11333 {
11334 const char action[] = "now SIGNAL before_open_table WAIT_FOR go_ahead_sql";
11335 assert(!debug_sync_set_action(thd, STRING_WITH_LEN(action)));
11336 };);
11337 if (open_and_lock_tables(thd, rli->tables_to_lock, 0))
11338 {
11339 if (thd->is_error())
11340 {
11341 uint actual_error= thd->get_stmt_da()->mysql_errno();
11342 if (ignored_error_code(actual_error))
11343 {
11344 if (log_warnings > 1)
11345 rli->report(WARNING_LEVEL, actual_error,
11346 "Error executing row event: '%s'",
11347 thd->get_stmt_da()->message_text());
11348 thd->get_stmt_da()->reset_condition_info(thd);
11349 clear_all_errors(thd, const_cast<Relay_log_info*>(rli));
11350 error= 0;
11351 goto end;
11352 }
11353 else
11354 {
11355 rli->report(ERROR_LEVEL, actual_error,
11356 "Error executing row event: '%s'",
11357 thd->get_stmt_da()->message_text());
11358 thd->is_slave_error= 1;
11359 }
11360 }
11361 DBUG_RETURN(1);
11362 }
11363
11364 /*
11365 When the open and locking succeeded, we check all tables to
11366 ensure that they still have the correct type.
11367 */
11368
11369 {
11370 DBUG_PRINT("debug", ("Checking compability of tables to lock - tables_to_lock: %p",
11371 rli->tables_to_lock));
11372
11373 /**
11374 When using RBR and MyISAM MERGE tables the base tables that make
11375 up the MERGE table can be appended to the list of tables to lock.
11376
11377 Thus, we just check compatibility for those that tables that have
11378 a correspondent table map event (ie, those that are actually going
11379 to be accessed while applying the event). That's why the loop stops
11380 at rli->tables_to_lock_count .
11381
11382 NOTE: The base tables are added here are removed when
11383 close_thread_tables is called.
11384 */
11385 TABLE_LIST *table_list_ptr= rli->tables_to_lock;
11386 for (uint i=0 ; table_list_ptr && (i < rli->tables_to_lock_count);
11387 table_list_ptr= table_list_ptr->next_global, i++)
11388 {
11389 /*
11390 Below if condition takes care of skipping base tables that
11391 make up the MERGE table (which are added by open_tables()
11392 call). They are added next to the merge table in the list.
11393 For eg: If RPL_TABLE_LIST is t3->t1->t2 (where t1 and t2
11394 are base tables for merge table 't3'), open_tables will modify
11395 the list by adding t1 and t2 again immediately after t3 in the
11396 list (*not at the end of the list*). New table_to_lock list will
11397 look like t3->t1'->t2'->t1->t2 (where t1' and t2' are TABLE_LIST
11398 objects added by open_tables() call). There is no flag(or logic) in
11399 open_tables() that can skip adding these base tables to the list.
11400 So the logic here should take care of skipping them.
11401
11402 tables_to_lock_count logic will take care of skipping base tables
11403 that are added at the end of the list.
11404 For eg: If RPL_TABLE_LIST is t1->t2->t3, open_tables will modify
11405 the list into t1->t2->t3->t1'->t2'. t1' and t2' will be skipped
11406 because tables_to_lock_count logic in this for loop.
11407 */
11408 if (table_list_ptr->parent_l)
11409 continue;
11410 /*
11411 We can use a down cast here since we know that every table added
11412 to the tables_to_lock is a RPL_TABLE_LIST (or child table which is
11413 skipped above).
11414 */
11415 RPL_TABLE_LIST *ptr= static_cast<RPL_TABLE_LIST*>(table_list_ptr);
11416 assert(ptr->m_tabledef_valid);
11417 TABLE *conv_table;
11418 if (!ptr->m_tabledef.compatible_with(thd, const_cast<Relay_log_info*>(rli),
11419 ptr->table, &conv_table))
11420 {
11421 DBUG_PRINT("debug", ("Table: %s.%s is not compatible with master",
11422 ptr->table->s->db.str,
11423 ptr->table->s->table_name.str));
11424 if (thd->is_slave_error)
11425 {
11426 const_cast<Relay_log_info*>(rli)->slave_close_thread_tables(thd);
11427 DBUG_RETURN(ERR_BAD_TABLE_DEF);
11428 }
11429 else
11430 {
11431 thd->get_stmt_da()->reset_condition_info(thd);
11432 clear_all_errors(thd, const_cast<Relay_log_info*>(rli));
11433 error= 0;
11434 goto end;
11435 }
11436 }
11437 DBUG_PRINT("debug", ("Table: %s.%s is compatible with master"
11438 " - conv_table: %p",
11439 ptr->table->s->db.str,
11440 ptr->table->s->table_name.str, conv_table));
11441 ptr->m_conv_table= conv_table;
11442 }
11443 }
11444
11445 /*
11446 ... and then we add all the tables to the table map and but keep
11447 them in the tables to lock list.
11448
11449 We also invalidate the query cache for all the tables, since
11450 they will now be changed.
11451
11452 TODO [/Matz]: Maybe the query cache should not be invalidated
11453 here? It might be that a table is not changed, even though it
11454 was locked for the statement. We do know that each
11455 Rows_log_event contain at least one row, so after processing one
11456 Rows_log_event, we can invalidate the query cache for the
11457 associated table.
11458 */
11459 TABLE_LIST *ptr= rli->tables_to_lock;
11460 for (uint i=0 ; ptr && (i < rli->tables_to_lock_count); ptr= ptr->next_global, i++)
11461 {
11462 /*
11463 Please see comment in above 'for' loop to know the reason
11464 for this if condition
11465 */
11466 if (ptr->parent_l)
11467 continue;
11468 const_cast<Relay_log_info*>(rli)->m_table_map.set_table(ptr->table_id, ptr->table);
11469 }
11470
11471 query_cache.invalidate_locked_for_write(rli->tables_to_lock);
11472 }
11473
11474 table=
11475 m_table= const_cast<Relay_log_info*>(rli)->m_table_map.get_table(m_table_id);
11476
11477 DBUG_PRINT("debug", ("m_table: 0x%lx, m_table_id: %llu", (ulong) m_table,
11478 m_table_id.id()));
11479
11480 /*
11481 A row event comprising of a P_S table
11482 - should not be replicated (i.e executed) by the slave SQL thread.
11483 - should not be executed by the client in the form BINLOG '...' stmts.
11484 */
11485 if (table && table->s->table_category == TABLE_CATEGORY_PERFORMANCE)
11486 table= NULL;
11487
11488 if (table)
11489 {
11490 /*
11491 table == NULL means that this table should not be replicated
11492 (this was set up by Table_map_log_event::do_apply_event()
11493 which tested replicate-* rules).
11494 */
11495
11496 /*
11497 It's not needed to set_time() but
11498 1) it continues the property that "Time" in SHOW PROCESSLIST shows how
11499 much slave is behind
11500 2) it will be needed when we allow replication from a table with no
11501 TIMESTAMP column to a table with one.
11502 So we call set_time(), like in SBR. Presently it changes nothing.
11503 */
11504 thd->set_time(&(common_header->when));
11505
11506 /*
11507 We don't consider index extensions in RBR, as doing so would cause
11508 replication failure with UPDATE/DELETE when replica server has a PK on
11509 extra columns and source does not.
11510 */
11511 Disable_index_extensions_switch_guard guard(thd);
11512
11513 thd->binlog_row_event_extra_data = m_extra_row_data;
11514
11515 /*
11516 Now we are in a statement and will stay in a statement until we
11517 see a STMT_END_F.
11518
11519 We set this flag here, before actually applying any rows, in
11520 case the SQL thread is stopped and we need to detect that we're
11521 inside a statement and halting abruptly might cause problems
11522 when restarting.
11523 */
11524 const_cast<Relay_log_info*>(rli)->set_flag(Relay_log_info::IN_STMT);
11525
11526 if ( m_width == table->s->fields && bitmap_is_set_all(&m_cols))
11527 set_flags(COMPLETE_ROWS_F);
11528
11529 /*
11530 Set tables write and read sets.
11531
11532 Read_set contains all slave columns (in case we are going to fetch
11533 a complete record from slave)
11534
11535 Write_set equals the m_cols bitmap sent from master but it can be
11536 longer if slave has extra columns.
11537 */
11538
11539 DBUG_PRINT_BITSET("debug", "Setting table's read_set from: %s", &m_cols);
11540
11541 /*
11542 Call mark_generated_columns() to set read_set/write_set bits of the
11543 virtual generated columns as required in order to get these computed.
11544 This is needed since all columns need to have a value in the before
11545 image for the record when doing the update (some storage engines will
11546 use this for maintaining of secondary indexes). This call is required
11547 even for DELETE events to set write_set bit in order to satisfy
11548 ASSERTs in Field_*::store functions.
11549
11550 binlog_prepare_row_image() function, which will be called from
11551 binlogging functions (binlog_update_row() and binlog_delete_row())
11552 will take care of removing these spurious fields required during
11553 execution but not needed for binlogging. In case of inserts, there
11554 are no spurious fields (all generated columns are required to be written
11555 into the binlog).
11556 */
11557
11558 bitmap_set_all(table->read_set);
11559 bitmap_set_all(table->write_set);
11560
11561 switch (get_general_type_code()) {
11562 case binary_log::DELETE_ROWS_EVENT:
11563 bitmap_intersect(table->read_set, &m_cols);
11564 bitmap_intersect(table->write_set, &m_cols);
11565 if (m_table->vfield)
11566 m_table->mark_generated_columns(false);
11567 break;
11568 case binary_log::UPDATE_ROWS_EVENT:
11569 bitmap_intersect(table->read_set, &m_cols);
11570 bitmap_intersect(table->write_set, &m_cols_ai);
11571 if (m_table->vfield)
11572 m_table->mark_generated_columns(true);
11573 break;
11574 case binary_log::WRITE_ROWS_EVENT:
11575 /* WRITE ROWS EVENTS store the bitmap in m_cols instead of m_cols_ai */
11576 bitmap_intersect(table->write_set, &m_cols);
11577 if (m_table->vfield)
11578 m_table->mark_generated_columns(false);
11579 break;
11580 default:
11581 assert(false);
11582 }
11583
11584 if (thd->slave_thread) // set the mode for slave
11585 this->rbr_exec_mode= slave_exec_mode_options;
11586 else //set the mode for user thread
11587 this->rbr_exec_mode= thd->variables.rbr_exec_mode_options;
11588
11589 // Do event specific preparations
11590 error= do_before_row_operations(rli);
11591
11592 /*
11593 Bug#56662 Assertion failed: next_insert_id == 0, file handler.cc
11594 Don't allow generation of auto_increment value when processing
11595 rows event by setting 'MODE_NO_AUTO_VALUE_ON_ZERO'. The exception
11596 to this rule happens when the auto_inc column exists on some
11597 extra columns on the slave. In that case, do not force
11598 MODE_NO_AUTO_VALUE_ON_ZERO.
11599 */
11600 sql_mode_t saved_sql_mode= thd->variables.sql_mode;
11601 if (!is_auto_inc_in_extra_columns())
11602 thd->variables.sql_mode= MODE_NO_AUTO_VALUE_ON_ZERO;
11603
11604 // row processing loop
11605
11606 /*
11607 set the initial time of this ROWS statement if it was not done
11608 before in some other ROWS event.
11609 */
11610 const_cast<Relay_log_info*>(rli)->set_row_stmt_start_timestamp();
11611
11612 const uchar *saved_m_curr_row= m_curr_row;
11613
11614 int (Rows_log_event::*do_apply_row_ptr)(Relay_log_info const *)= NULL;
11615
11616 /**
11617 Skip update rows events that don't have data for this slave's
11618 table.
11619 */
11620 if ((get_general_type_code() == binary_log::UPDATE_ROWS_EVENT) &&
11621 !is_any_column_signaled_for_table(table, &m_cols_ai))
11622 goto AFTER_MAIN_EXEC_ROW_LOOP;
11623
11624 /**
11625 If there are no columns marked in the read_set for this table,
11626 that means that we cannot lookup any row using the available BI
11627 in the binarr log. Thence, we immediatly raise an error:
11628 HA_ERR_END_OF_FILE.
11629 */
11630
11631 if ((m_rows_lookup_algorithm != ROW_LOOKUP_NOT_NEEDED) &&
11632 !is_any_column_signaled_for_table(table, &m_cols))
11633 {
11634 error= HA_ERR_END_OF_FILE;
11635 goto AFTER_MAIN_EXEC_ROW_LOOP;
11636 }
11637 switch (m_rows_lookup_algorithm)
11638 {
11639 case ROW_LOOKUP_HASH_SCAN:
11640 do_apply_row_ptr= &Rows_log_event::do_hash_scan_and_update;
11641 break;
11642
11643 case ROW_LOOKUP_INDEX_SCAN:
11644 do_apply_row_ptr= &Rows_log_event::do_index_scan_and_update;
11645 break;
11646
11647 case ROW_LOOKUP_TABLE_SCAN:
11648 do_apply_row_ptr= &Rows_log_event::do_table_scan_and_update;
11649 break;
11650
11651 case ROW_LOOKUP_NOT_NEEDED:
11652 assert(get_general_type_code() == binary_log::WRITE_ROWS_EVENT ||
11653 get_general_type_code() == binary_log::DELETE_ROWS_EVENT ||
11654 get_general_type_code() == binary_log::UPDATE_ROWS_EVENT);
11655
11656 /* No need to scan for rows, just apply it */
11657 do_apply_row_ptr= &Rows_log_event::do_apply_row;
11658 break;
11659
11660 default:
11661 assert(0);
11662 error= 1;
11663 goto AFTER_MAIN_EXEC_ROW_LOOP;
11664 break;
11665 }
11666
11667 do {
11668
11669 error= (this->*do_apply_row_ptr)(rli);
11670
11671 if (!error)
11672 thd->updated_row_count++;
11673
11674 if (handle_idempotent_and_ignored_errors(rli, &error))
11675 break;
11676
11677 /* this advances m_curr_row */
11678 do_post_row_operations(rli, error);
11679
11680 } while (!error && (m_curr_row != m_rows_end));
11681
11682 if (unlikely(opt_userstat))
11683 {
11684 thd->update_stats(false);
11685 #ifndef EMBEDDED_LIBRARY
11686 update_global_user_stats(thd, true, time(NULL));
11687 #endif
11688 }
11689
11690 AFTER_MAIN_EXEC_ROW_LOOP:
11691
11692 if (saved_m_curr_row != m_curr_row && !table->file->has_transactions())
11693 {
11694 /*
11695 Usually, the trans_commit_stmt() propagates unsafe_rollback_flags
11696 from statement to transaction level. However, we cannot rely on
11697 this when row format is in use as several events can be processed
11698 before calling this function. This happens because it is called
11699 only when the latest event generated by a statement is processed.
11700
11701 There are however upper level functions that execute per event
11702 and check transaction's status. So if the unsafe_rollback_flags
11703 are not propagated here, this can lead to errors.
11704
11705 For example, a transaction that updates non-transactional tables
11706 may be stopped in the middle thus leading to inconsistencies
11707 after a restart.
11708 */
11709 thd->get_transaction()->mark_modified_non_trans_table(
11710 Transaction_ctx::STMT);
11711 thd->get_transaction()->merge_unsafe_rollback_flags();
11712 }
11713
11714 /*
11715 Restore the sql_mode after the rows event is processed.
11716 */
11717 thd->variables.sql_mode= saved_sql_mode;
11718
11719 {/*
11720 The following failure injecion works in cooperation with tests
11721 setting @@global.debug= 'd,stop_slave_middle_group'.
11722 The sql thread receives the killed status and will proceed
11723 to shutdown trying to finish incomplete events group.
11724 */
11725 DBUG_EXECUTE_IF("stop_slave_middle_group",
11726 if (thd->get_transaction()->cannot_safely_rollback(
11727 Transaction_ctx::SESSION))
11728 const_cast<Relay_log_info*>(rli)->abort_slave= 1;);
11729 }
11730
11731 if ((error= do_after_row_operations(rli, error)) &&
11732 ignored_error_code(convert_handler_error(error, thd, table)))
11733 {
11734 slave_rows_error_report(INFORMATION_LEVEL, error, rli, thd, table,
11735 get_type_str(),
11736 const_cast<Relay_log_info*>(rli)->get_rpl_log_name(),
11737 (ulong) common_header->log_pos);
11738 thd->get_stmt_da()->reset_condition_info(thd);
11739 clear_all_errors(thd, const_cast<Relay_log_info*>(rli));
11740 error= 0;
11741 }
11742 } // if (table)
11743
11744 if (error)
11745 {
11746 slave_rows_error_report(ERROR_LEVEL, error, rli, thd, table,
11747 get_type_str(),
11748 const_cast<Relay_log_info*>(rli)->get_rpl_log_name(),
11749 (ulong) common_header->log_pos);
11750 /*
11751 @todo We should probably not call
11752 reset_current_stmt_binlog_format_row() from here.
11753
11754 Note: this applies to log_event_old.cc too.
11755 /Sven
11756 */
11757 thd->reset_current_stmt_binlog_format_row();
11758 thd->is_slave_error= 1;
11759 DBUG_RETURN(error);
11760 }
11761
11762 end:
11763 if (get_flags(STMT_END_F))
11764 {
11765 if((error= rows_event_stmt_cleanup(rli, thd)))
11766 {
11767 if (table)
11768 slave_rows_error_report(ERROR_LEVEL,
11769 thd->is_error() ? 0 : error,
11770 rli, thd, table,
11771 get_type_str(),
11772 const_cast<Relay_log_info*>(rli)->get_rpl_log_name(),
11773 (ulong) common_header->log_pos);
11774 else
11775 {
11776 rli->report(ERROR_LEVEL,
11777 thd->is_error() ? thd->get_stmt_da()->mysql_errno() : error,
11778 "Error in cleaning up after an event of type:%s; %s; the group"
11779 " log file/position: %s %lu", get_type_str(),
11780 thd->is_error() ? thd->get_stmt_da()->message_text() :
11781 "unexpected error",
11782 const_cast<Relay_log_info*>(rli)->get_rpl_log_name(),
11783 (ulong) common_header->log_pos);
11784 }
11785 }
11786 /* We are at end of the statement (STMT_END_F flag), lets clean
11787 the memory which was used from thd's mem_root now.
11788 This needs to be done only if we are here in SQL thread context.
11789 In other flow ( in case of a regular thread which can happen
11790 when the thread is applying BINLOG'...' row event) we should
11791 *not* try to free the memory here. It will be done latter
11792 in dispatch_command() after command execution is completed.
11793 */
11794 if (thd->slave_thread)
11795 free_root(thd->mem_root, MYF(MY_KEEP_PREALLOC));
11796 }
11797 DBUG_RETURN(error);
11798 }
11799
11800 Log_event::enum_skip_reason
do_shall_skip(Relay_log_info * rli)11801 Rows_log_event::do_shall_skip(Relay_log_info *rli)
11802 {
11803 /*
11804 If the slave skip counter is 1 and this event does not end a
11805 statement, then we should not start executing on the next event.
11806 Otherwise, we defer the decision to the normal skipping logic.
11807 */
11808 if (rli->slave_skip_counter == 1 && !get_flags(STMT_END_F))
11809 return Log_event::EVENT_SKIP_IGNORE;
11810 else
11811 return Log_event::do_shall_skip(rli);
11812 }
11813
11814 /**
11815 The function is called at Rows_log_event statement commit time,
11816 normally from Rows_log_event::do_update_pos() and possibly from
11817 Query_log_event::do_apply_event() of the COMMIT.
11818 The function commits the last statement for engines, binlog and
11819 releases resources have been allocated for the statement.
11820
11821 @retval 0 Ok.
11822 @retval non-zero Error at the commit.
11823 */
11824
rows_event_stmt_cleanup(Relay_log_info const * rli,THD * thd)11825 static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD * thd)
11826 {
11827 DBUG_EXECUTE_IF("simulate_rows_event_cleanup_failure",
11828 {
11829 my_error(ER_ERROR_DURING_COMMIT, MYF(0), 1);
11830 return (1);
11831 });
11832 int error;
11833 {
11834 /*
11835 This is the end of a statement or transaction, so close (and
11836 unlock) the tables we opened when processing the
11837 Table_map_log_event starting the statement.
11838
11839 OBSERVER. This will clear *all* mappings, not only those that
11840 are open for the table. There is not good handle for on-close
11841 actions for tables.
11842
11843 NOTE. Even if we have no table ('table' == 0) we still need to be
11844 here, so that we increase the group relay log position. If we didn't, we
11845 could have a group relay log position which lags behind "forever"
11846 (assume the last master's transaction is ignored by the slave because of
11847 replicate-ignore rules).
11848 */
11849 error= thd->binlog_flush_pending_rows_event(TRUE);
11850
11851 /*
11852 If this event is not in a transaction, the call below will, if some
11853 transactional storage engines are involved, commit the statement into
11854 them and flush the pending event to binlog.
11855 If this event is in a transaction, the call will do nothing, but a
11856 Xid_log_event will come next which will, if some transactional engines
11857 are involved, commit the transaction and flush the pending event to the
11858 binlog.
11859 If there was a deadlock the transaction should have been rolled back
11860 already. So there should be no need to rollback the transaction.
11861 */
11862 assert(! thd->transaction_rollback_request);
11863 error|= (error ? trans_rollback_stmt(thd) : trans_commit_stmt(thd));
11864
11865 /*
11866 Now what if this is not a transactional engine? we still need to
11867 flush the pending event to the binlog; we did it with
11868 thd->binlog_flush_pending_rows_event(). Note that we imitate
11869 what is done for real queries: a call to
11870 ha_autocommit_or_rollback() (sometimes only if involves a
11871 transactional engine), and a call to be sure to have the pending
11872 event flushed.
11873 */
11874
11875 /*
11876 @todo We should probably not call
11877 reset_current_stmt_binlog_format_row() from here.
11878
11879 Note: this applies to log_event_old.cc too
11880
11881 Btw, the previous comment about transactional engines does not
11882 seem related to anything that happens here.
11883 /Sven
11884 */
11885 thd->reset_current_stmt_binlog_format_row();
11886
11887 const_cast<Relay_log_info*>(rli)->cleanup_context(thd, 0);
11888
11889 /*
11890 Clean sql_command value
11891 */
11892 thd->lex->sql_command= SQLCOM_END;
11893
11894 }
11895 return error;
11896 }
11897
11898 /**
11899 The method either increments the relay log position or
11900 commits the current statement and increments the master group
11901 possition if the event is STMT_END_F flagged and
11902 the statement corresponds to the autocommit query (i.e replicated
11903 without wrapping in BEGIN/COMMIT)
11904
11905 @retval 0 Success
11906 @retval non-zero Error in the statement commit
11907 */
11908 int
do_update_pos(Relay_log_info * rli)11909 Rows_log_event::do_update_pos(Relay_log_info *rli)
11910 {
11911 DBUG_ENTER("Rows_log_event::do_update_pos");
11912 int error= 0;
11913
11914 DBUG_PRINT("info", ("flags: %s",
11915 get_flags(STMT_END_F) ? "STMT_END_F " : ""));
11916
11917 /* Worker does not execute binlog update position logics */
11918 assert(!is_mts_worker(rli->info_thd));
11919
11920 if (get_flags(STMT_END_F))
11921 {
11922 /*
11923 Indicate that a statement is finished.
11924 Step the group log position if we are not in a transaction,
11925 otherwise increase the event log position.
11926 */
11927 error= rli->stmt_done(common_header->log_pos);
11928 }
11929 else
11930 {
11931 rli->inc_event_relay_log_pos();
11932 }
11933
11934 DBUG_RETURN(error);
11935 }
11936
11937 #endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */
11938
11939 #ifndef MYSQL_CLIENT
write_data_header(IO_CACHE * file)11940 bool Rows_log_event::write_data_header(IO_CACHE *file)
11941 {
11942 uchar buf[Binary_log_event::ROWS_HEADER_LEN_V2]; // No need to init the buffer
11943 assert(m_table_id.is_valid());
11944 DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master",
11945 {
11946 int4store(buf + 0, (ulong) m_table_id.id());
11947 int2store(buf + 4, m_flags);
11948 return (wrapper_my_b_safe_write(file, buf, 6));
11949 });
11950 int6store(buf + ROWS_MAPID_OFFSET, m_table_id.id());
11951 int2store(buf + ROWS_FLAGS_OFFSET, m_flags);
11952 int rc = 0;
11953 if (likely(!log_bin_use_v1_row_events))
11954 {
11955 /*
11956 v2 event, with variable header portion.
11957 Determine length of variable header payload
11958 */
11959 uint16 vhlen= 2;
11960 uint16 vhpayloadlen= 0;
11961 uint16 extra_data_len= 0;
11962 if (m_extra_row_data)
11963 {
11964 extra_data_len= m_extra_row_data[EXTRA_ROW_INFO_LEN_OFFSET];
11965 vhpayloadlen= ROWS_V_TAG_LEN + extra_data_len;
11966 }
11967
11968 /* Var-size header len includes len itself */
11969 int2store(buf + ROWS_VHLEN_OFFSET, vhlen + vhpayloadlen);
11970 rc= wrapper_my_b_safe_write(file, buf, Binary_log_event::ROWS_HEADER_LEN_V2);
11971
11972 /* Write var-sized payload, if any */
11973 if ((vhpayloadlen > 0) &&
11974 (rc == 0))
11975 {
11976 /* Add tag and extra row info */
11977 uchar type_code= ROWS_V_EXTRAINFO_TAG;
11978 rc= wrapper_my_b_safe_write(file, &type_code, ROWS_V_TAG_LEN);
11979 if (rc==0)
11980 rc= wrapper_my_b_safe_write(file, m_extra_row_data, extra_data_len);
11981 }
11982 }
11983 else
11984 {
11985 rc= wrapper_my_b_safe_write(file, buf, Binary_log_event::ROWS_HEADER_LEN_V1);
11986 }
11987
11988 return (rc != 0);
11989 }
11990
write_data_body(IO_CACHE * file)11991 bool Rows_log_event::write_data_body(IO_CACHE*file)
11992 {
11993 /*
11994 Note that this should be the number of *bits*, not the number of
11995 bytes.
11996 */
11997 uchar sbuf[sizeof(m_width) + 1];
11998 my_ptrdiff_t const data_size= m_rows_cur - m_rows_buf;
11999 bool res= false;
12000 uchar *const sbuf_end= net_store_length(sbuf, (size_t) m_width);
12001 assert(static_cast<size_t>(sbuf_end - sbuf) <= sizeof(sbuf));
12002
12003 DBUG_DUMP("m_width", sbuf, (size_t) (sbuf_end - sbuf));
12004 res= res || wrapper_my_b_safe_write(file, sbuf, (size_t) (sbuf_end - sbuf));
12005
12006 DBUG_DUMP("m_cols", (uchar*) m_cols.bitmap, no_bytes_in_map(&m_cols));
12007 res= res || wrapper_my_b_safe_write(file, (uchar*) m_cols.bitmap,
12008 no_bytes_in_map(&m_cols));
12009 /*
12010 TODO[refactor write]: Remove the "down cast" here (and elsewhere).
12011 */
12012 if (get_general_type_code() == binary_log::UPDATE_ROWS_EVENT)
12013 {
12014 DBUG_DUMP("m_cols_ai", (uchar*) m_cols_ai.bitmap,
12015 no_bytes_in_map(&m_cols_ai));
12016 res= res || wrapper_my_b_safe_write(file, (uchar*) m_cols_ai.bitmap,
12017 no_bytes_in_map(&m_cols_ai));
12018 }
12019 DBUG_DUMP("rows", m_rows_buf, data_size);
12020 res= res || wrapper_my_b_safe_write(file, m_rows_buf, (size_t) data_size);
12021
12022 return res;
12023
12024 }
12025 #endif
12026
12027 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
pack_info(Protocol * protocol)12028 int Rows_log_event::pack_info(Protocol *protocol)
12029 {
12030 char buf[256];
12031 char const *const flagstr=
12032 get_flags(STMT_END_F) ? " flags: STMT_END_F" : "";
12033 size_t bytes= my_snprintf(buf, sizeof(buf),
12034 "table_id: %llu%s", m_table_id.id(), flagstr);
12035 protocol->store(buf, bytes, &my_charset_bin);
12036 return 0;
12037 }
12038 #endif
12039
12040 #ifdef MYSQL_CLIENT
print_helper(FILE * file,PRINT_EVENT_INFO * print_event_info,char const * const name)12041 void Rows_log_event::print_helper(FILE *file,
12042 PRINT_EVENT_INFO *print_event_info,
12043 char const *const name)
12044 {
12045 IO_CACHE *const head= &print_event_info->head_cache;
12046 IO_CACHE *const body= &print_event_info->body_cache;
12047 if (!print_event_info->short_form)
12048 {
12049 bool const last_stmt_event= get_flags(STMT_END_F);
12050 print_header(head, print_event_info, !last_stmt_event);
12051 my_b_printf(head, "\t%s: table id %llu%s\n",
12052 name, m_table_id.id(),
12053 last_stmt_event ? " flags: STMT_END_F" : "");
12054 print_base64(body, print_event_info, !last_stmt_event);
12055 }
12056 }
12057 #endif
12058
12059 /**************************************************************************
12060 Table_map_log_event member functions and support functions
12061 **************************************************************************/
12062
12063 /**
12064 @page How replication of field metadata works.
12065
12066 When a table map is created, the master first calls
12067 Table_map_log_event::save_field_metadata() which calculates how many
12068 values will be in the field metadata. Only those fields that require the
12069 extra data are added. The method also loops through all of the fields in
12070 the table calling the method Field::save_field_metadata() which returns the
12071 values for the field that will be saved in the metadata and replicated to
12072 the slave. Once all fields have been processed, the table map is written to
12073 the binlog adding the size of the field metadata and the field metadata to
12074 the end of the body of the table map.
12075
12076 When a table map is read on the slave, the field metadata is read from the
12077 table map and passed to the table_def class constructor which saves the
12078 field metadata from the table map into an array based on the type of the
12079 field. Field metadata values not present (those fields that do not use extra
12080 data) in the table map are initialized as zero (0). The array size is the
12081 same as the columns for the table on the slave.
12082
12083 Additionally, values saved for field metadata on the master are saved as a
12084 string of bytes (uchar) in the binlog. A field may require 1 or more bytes
12085 to store the information. In cases where values require multiple bytes
12086 (e.g. values > 255), the endian-safe methods are used to properly encode
12087 the values on the master and decode them on the slave. When the field
12088 metadata values are captured on the slave, they are stored in an array of
12089 type uint16. This allows the least number of casts to prevent casting bugs
12090 when the field metadata is used in comparisons of field attributes. When
12091 the field metadata is used for calculating addresses in pointer math, the
12092 type used is uint32.
12093 */
12094
12095 #if !defined(MYSQL_CLIENT)
12096 /**
12097 Save the field metadata based on the real_type of the field.
12098 The metadata saved depends on the type of the field. Some fields
12099 store a single byte for pack_length() while others store two bytes
12100 for field_length (max length).
12101
12102 @retval 0 Ok.
12103
12104 @todo
12105 We may want to consider changing the encoding of the information.
12106 Currently, the code attempts to minimize the number of bytes written to
12107 the tablemap. There are at least two other alternatives; 1) using
12108 net_store_length() to store the data allowing it to choose the number of
12109 bytes that are appropriate thereby making the code much easier to
12110 maintain (only 1 place to change the encoding), or 2) use a fixed number
12111 of bytes for each field. The problem with option 1 is that net_store_length()
12112 will use one byte if the value < 251, but 3 bytes if it is > 250. Thus,
12113 for fields like CHAR which can be no larger than 255 characters, the method
12114 will use 3 bytes when the value is > 250. Further, every value that is
12115 encoded using 2 parts (e.g., pack_length, field_length) will be numerically
12116 > 250 therefore will use 3 bytes for eah value. The problem with option 2
12117 is less wasteful for space but does waste 1 byte for every field that does
12118 not encode 2 parts.
12119 */
save_field_metadata()12120 int Table_map_log_event::save_field_metadata()
12121 {
12122 DBUG_ENTER("Table_map_log_event::save_field_metadata");
12123 int index= 0;
12124 for (unsigned int i= 0; i < m_table->s->fields ; i++)
12125 {
12126 DBUG_PRINT("debug", ("field_type: %d", m_coltype[i]));
12127 index+= m_table->s->field[i]->save_field_metadata(&m_field_metadata[index]);
12128 }
12129 DBUG_RETURN(index);
12130 }
12131 #endif /* !defined(MYSQL_CLIENT) */
12132
12133 /*
12134 Constructor used to build an event for writing to the binary log.
12135 Mats says tbl->s lives longer than this event so it's ok to copy pointers
12136 (tbl->s->db etc) and not pointer content.
12137 */
12138 #if !defined(MYSQL_CLIENT)
Table_map_log_event(THD * thd_arg,TABLE * tbl,const Table_id & tid,bool using_trans)12139 Table_map_log_event::Table_map_log_event(THD *thd_arg, TABLE *tbl,
12140 const Table_id& tid,
12141 bool using_trans)
12142 : binary_log::Table_map_event(tid, tbl->s->fields, (tbl->s->db.str),
12143 ((tbl->s->db.str) ? tbl->s->db.length : 0),
12144 (tbl->s->table_name.str),
12145 (tbl->s->table_name.length)),
12146 Log_event(thd_arg, 0,
12147 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
12148 Log_event::EVENT_STMT_CACHE,
12149 Log_event::EVENT_NORMAL_LOGGING,
12150 header(), footer())
12151 {
12152 common_header->type_code= binary_log::TABLE_MAP_EVENT;
12153 m_table= tbl;
12154 m_flags= TM_BIT_LEN_EXACT_F;
12155
12156 uchar cbuf[sizeof(m_colcnt) + 1];
12157 uchar *cbuf_end;
12158 assert(m_table_id.is_valid());
12159 /*
12160 In TABLE_SHARE, "db" and "table_name" are 0-terminated (see this comment in
12161 table.cc / alloc_table_share():
12162 Use the fact the key is db/0/table_name/0
12163 As we rely on this let's assert it.
12164 */
12165 assert((tbl->s->db.str == 0) ||
12166 (tbl->s->db.str[tbl->s->db.length] == 0));
12167 assert(tbl->s->table_name.str[tbl->s->table_name.length] == 0);
12168
12169
12170 m_data_size= Binary_log_event::TABLE_MAP_HEADER_LEN;
12171 DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master", m_data_size= 6;);
12172 m_data_size+= m_dblen + 2; // Include length and terminating \0
12173 m_data_size+= m_tbllen + 2; // Include length and terminating \0
12174 cbuf_end= net_store_length(cbuf, (size_t) m_colcnt);
12175 assert(static_cast<size_t>(cbuf_end - cbuf) <= sizeof(cbuf));
12176 m_data_size+= (cbuf_end - cbuf) + m_colcnt; // COLCNT and column types
12177
12178 m_coltype= (uchar *)my_malloc(key_memory_log_event,
12179 m_colcnt, MYF(MY_WME));
12180
12181 assert(m_colcnt == m_table->s->fields);
12182 for (unsigned int i= 0; i < m_table->s->fields; ++i)
12183 m_coltype[i]= m_table->field[i]->binlog_type();
12184
12185
12186 /*
12187 Calculate a bitmap for the results of maybe_null() for all columns.
12188 The bitmap is used to determine when there is a column from the master
12189 that is not on the slave and is null and thus not in the row data during
12190 replication.
12191 */
12192 uint num_null_bytes= (m_table->s->fields + 7) / 8;
12193 m_data_size+= num_null_bytes;
12194 /*
12195 m_null_bits is a pointer indicating which columns can have a null value
12196 in a particular table.
12197 */
12198 m_null_bits= (uchar *)my_malloc(key_memory_log_event,
12199 num_null_bytes, MYF(MY_WME));
12200
12201 m_field_metadata= (uchar*)my_malloc(key_memory_log_event,
12202 (m_colcnt * 2), MYF(MY_WME));
12203 memset(m_field_metadata, 0, (m_colcnt * 2));
12204
12205 if (m_null_bits != NULL && m_field_metadata != NULL && m_coltype != NULL)
12206 is_valid_param= true;
12207 /*
12208 Create an array for the field metadata and store it.
12209 */
12210 m_field_metadata_size= save_field_metadata();
12211 assert(m_field_metadata_size <= (m_colcnt * 2));
12212
12213 /*
12214 Now set the size of the data to the size of the field metadata array
12215 plus one or three bytes (see pack.c:net_store_length) for number of
12216 elements in the field metadata array.
12217 */
12218 if (m_field_metadata_size < 251)
12219 m_data_size+= m_field_metadata_size + 1;
12220 else
12221 m_data_size+= m_field_metadata_size + 3;
12222
12223 memset(m_null_bits, 0, num_null_bytes);
12224 for (unsigned int i= 0 ; i < m_table->s->fields ; ++i)
12225 if (m_table->field[i]->maybe_null())
12226 m_null_bits[(i / 8)]+= 1 << (i % 8);
12227 /*
12228 Marking event to require sequential execution in MTS
12229 if the query might have updated FK-referenced db.
12230 Unlike Query_log_event where this fact is encoded through
12231 the accessed db list in the Table_map case m_flags is exploited.
12232 */
12233 uchar dbs= thd_arg->get_binlog_accessed_db_names() ?
12234 thd_arg->get_binlog_accessed_db_names()->elements : 0;
12235 if (dbs == 1)
12236 {
12237 char *db_name= thd_arg->get_binlog_accessed_db_names()->head();
12238 if (!strcmp(db_name, ""))
12239 m_flags |= TM_REFERRED_FK_DB_F;
12240 }
12241 }
12242 #endif /* !defined(MYSQL_CLIENT) */
12243
12244 /*
12245 Constructor used by slave to read the event from the binary log.
12246 */
12247 #if defined(HAVE_REPLICATION)
Table_map_log_event(const char * buf,uint event_len,const Format_description_event * description_event)12248 Table_map_log_event::Table_map_log_event(const char *buf, uint event_len,
12249 const Format_description_event
12250 *description_event)
12251
12252 : binary_log::Table_map_event(buf, event_len, description_event),
12253 Log_event(header(), footer())
12254 #ifndef MYSQL_CLIENT
12255 ,m_table(NULL)
12256 #endif
12257 {
12258 DBUG_ENTER("Table_map_log_event::Table_map_log_event(const char*,uint,...)");
12259 if (m_null_bits != NULL && m_field_metadata != NULL && m_coltype != NULL)
12260 is_valid_param= true;
12261 assert(header()->type_code == binary_log::TABLE_MAP_EVENT);
12262 DBUG_VOID_RETURN;
12263 }
12264 #endif
12265
~Table_map_log_event()12266 Table_map_log_event::~Table_map_log_event()
12267 {
12268 if(m_null_bits)
12269 {
12270 my_free(m_null_bits);
12271 m_null_bits= NULL;
12272 }
12273 if(m_field_metadata)
12274 {
12275 my_free(m_field_metadata);
12276 m_field_metadata= NULL;
12277 }
12278 }
12279
12280 /*
12281 Return value is an error code, one of:
12282
12283 -1 Failure to open table [from open_tables()]
12284 0 Success
12285 1 No room for more tables [from set_table()]
12286 2 Out of memory [from set_table()]
12287 3 Wrong table definition
12288 4 Daisy-chaining RBR with SBR not possible
12289 */
12290
12291 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
12292
12293 enum enum_tbl_map_status
12294 {
12295 /* no duplicate identifier found */
12296 OK_TO_PROCESS= 0,
12297
12298 /* this table map must be filtered out */
12299 FILTERED_OUT= 1,
12300
12301 /* identifier mapping table with different properties */
12302 SAME_ID_MAPPING_DIFFERENT_TABLE= 2,
12303
12304 /* a duplicate identifier was found mapping the same table */
12305 SAME_ID_MAPPING_SAME_TABLE= 3,
12306
12307 /*
12308 this table must be filtered out but found an active XA transaction. XA
12309 transactions shouldn't be used with replication filters, until disabling
12310 the XA read only optimization is a supported feature.
12311 */
12312 FILTERED_WITH_XA_ACTIVE = 4
12313 };
12314
12315 /*
12316 Checks if this table map event should be processed or not. First
12317 it checks the filtering rules, and then looks for duplicate identifiers
12318 in the existing list of rli->tables_to_lock.
12319
12320 It checks that there hasn't been any corruption by verifying that there
12321 are no duplicate entries with different properties.
12322
12323 In some cases, some binary logs could get corrupted, showing several
12324 tables mapped to the same table_id, 0 (see: BUG#56226). Thus we do this
12325 early sanity check for such cases and avoid that the server crashes
12326 later.
12327
12328 In some corner cases, the master logs duplicate table map events, i.e.,
12329 same id, same database name, same table name (see: BUG#37137). This is
12330 different from the above as it's the same table that is mapped again
12331 to the same identifier. Thus we cannot just check for same ids and
12332 assume that the event is corrupted we need to check every property.
12333
12334 NOTE: in the event that BUG#37137 ever gets fixed, this extra check
12335 will still be valid because we would need to support old binary
12336 logs anyway.
12337
12338 @param rli The relay log info reference.
12339 @param table_list A list element containing the table to check against.
12340 @return OK_TO_PROCESS
12341 if there was no identifier already in rli->tables_to_lock
12342
12343 FILTERED_OUT
12344 if the event is filtered according to the filtering rules
12345
12346 SAME_ID_MAPPING_DIFFERENT_TABLE
12347 if the same identifier already maps a different table in
12348 rli->tables_to_lock
12349
12350 SAME_ID_MAPPING_SAME_TABLE
12351 if the same identifier already maps the same table in
12352 rli->tables_to_lock.
12353 */
12354 static enum_tbl_map_status
check_table_map(Relay_log_info const * rli,RPL_TABLE_LIST * table_list)12355 check_table_map(Relay_log_info const *rli, RPL_TABLE_LIST *table_list)
12356 {
12357 DBUG_ENTER("check_table_map");
12358 enum_tbl_map_status res= OK_TO_PROCESS;
12359
12360 if (rli->info_thd->slave_thread /* filtering is for slave only */ &&
12361 (!rpl_filter->db_ok(table_list->db) ||
12362 (rpl_filter->is_on() && !rpl_filter->tables_ok("", table_list))))
12363 if (rli->info_thd->get_transaction()->xid_state()->has_state(
12364 XID_STATE::XA_ACTIVE))
12365 res = FILTERED_WITH_XA_ACTIVE;
12366 else
12367 res = FILTERED_OUT;
12368 else
12369 {
12370 RPL_TABLE_LIST *ptr= static_cast<RPL_TABLE_LIST*>(rli->tables_to_lock);
12371 for(uint i=0 ; ptr && (i< rli->tables_to_lock_count);
12372 ptr= static_cast<RPL_TABLE_LIST*>(ptr->next_local), i++)
12373 {
12374 if (ptr->table_id == table_list->table_id)
12375 {
12376
12377 if (strcmp(ptr->db, table_list->db) ||
12378 strcmp(ptr->alias, table_list->table_name) ||
12379 ptr->lock_type != TL_WRITE) // the ::do_apply_event always sets TL_WRITE
12380 res= SAME_ID_MAPPING_DIFFERENT_TABLE;
12381 else
12382 res= SAME_ID_MAPPING_SAME_TABLE;
12383
12384 break;
12385 }
12386 }
12387 }
12388
12389 DBUG_PRINT("debug", ("check of table map ended up with: %u", res));
12390
12391 DBUG_RETURN(res);
12392 }
12393
do_apply_event(Relay_log_info const * rli)12394 int Table_map_log_event::do_apply_event(Relay_log_info const *rli)
12395 {
12396 RPL_TABLE_LIST *table_list;
12397 char *db_mem, *tname_mem, *ptr;
12398 size_t dummy_len;
12399 void *memory;
12400 DBUG_ENTER("Table_map_log_event::do_apply_event(Relay_log_info*)");
12401 assert(rli->info_thd == thd);
12402
12403 /* Step the query id to mark what columns that are actually used. */
12404 thd->set_query_id(next_query_id());
12405
12406 if (!(memory= my_multi_malloc(key_memory_log_event,
12407 MYF(MY_WME),
12408 &table_list, sizeof(RPL_TABLE_LIST),
12409 &db_mem, (uint) NAME_LEN + 1,
12410 &tname_mem, (uint) NAME_LEN + 1,
12411 NullS)))
12412 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
12413
12414 my_stpcpy(db_mem, m_dbnam.c_str());
12415 my_stpcpy(tname_mem, m_tblnam.c_str());
12416
12417 if (lower_case_table_names)
12418 {
12419 my_casedn_str(system_charset_info, db_mem);
12420 my_casedn_str(system_charset_info, tname_mem);
12421 }
12422
12423 /* rewrite rules changed the database */
12424 if (((ptr= (char*) rpl_filter->get_rewrite_db(db_mem, &dummy_len)) != db_mem))
12425 my_stpcpy(db_mem, ptr);
12426
12427 table_list->init_one_table(db_mem, strlen(db_mem),
12428 tname_mem, strlen(tname_mem),
12429 tname_mem, TL_WRITE);
12430
12431 table_list->table_id=
12432 DBUG_EVALUATE_IF("inject_tblmap_same_id_maps_diff_table", 0, m_table_id.id());
12433 table_list->updating= 1;
12434 table_list->required_type= FRMTYPE_TABLE;
12435 DBUG_PRINT("debug", ("table: %s is mapped to %llu", table_list->table_name,
12436 table_list->table_id.id()));
12437
12438 enum_tbl_map_status tblmap_status= check_table_map(rli, table_list);
12439 if (tblmap_status == OK_TO_PROCESS)
12440 {
12441 assert(thd->lex->query_tables != table_list);
12442
12443 /*
12444 Use placement new to construct the table_def instance in the
12445 memory allocated for it inside table_list.
12446
12447 The memory allocated by the table_def structure (i.e., not the
12448 memory allocated *for* the table_def structure) is released
12449 inside Relay_log_info::clear_tables_to_lock() by calling the
12450 table_def destructor explicitly.
12451 */
12452 new (&table_list->m_tabledef)
12453 table_def(m_coltype, m_colcnt,
12454 m_field_metadata, m_field_metadata_size,
12455 m_null_bits, m_flags);
12456
12457 table_list->m_tabledef_valid= TRUE;
12458 table_list->m_conv_table= NULL;
12459 table_list->open_type= OT_BASE_ONLY;
12460
12461 /*
12462 We record in the slave's information that the table should be
12463 locked by linking the table into the list of tables to lock.
12464 */
12465 table_list->next_global= table_list->next_local= rli->tables_to_lock;
12466 const_cast<Relay_log_info*>(rli)->tables_to_lock= table_list;
12467 const_cast<Relay_log_info*>(rli)->tables_to_lock_count++;
12468 /* 'memory' is freed in clear_tables_to_lock */
12469 }
12470 else // FILTERED_OUT, SAME_ID_MAPPING_*
12471 {
12472 if (tblmap_status == FILTERED_WITH_XA_ACTIVE)
12473 {
12474 if (thd->slave_thread)
12475 rli->report(ERROR_LEVEL, ER_XA_REPLICATION_FILTERS,
12476 "%s", ER_THD(thd, ER_XA_REPLICATION_FILTERS));
12477 else
12478 /*
12479 For the cases in which a 'BINLOG' statement is set to
12480 execute in a user session
12481 */
12482 my_printf_error(ER_XA_REPLICATION_FILTERS,
12483 "%s", MYF(0), ER_THD(thd, ER_XA_REPLICATION_FILTERS));
12484 }
12485 /*
12486 If mapped already but with different properties, we raise an
12487 error.
12488 If mapped already but with same properties we skip the event.
12489 If filtered out we skip the event.
12490
12491 In all three cases, we need to free the memory previously
12492 allocated.
12493 */
12494 else if (tblmap_status == SAME_ID_MAPPING_DIFFERENT_TABLE)
12495 {
12496 /*
12497 Something bad has happened. We need to stop the slave as strange things
12498 could happen if we proceed: slave crash, wrong table being updated, ...
12499 As a consequence we push an error in this case.
12500 */
12501
12502 char buf[256];
12503
12504 my_snprintf(buf, sizeof(buf),
12505 "Found table map event mapping table id %llu which "
12506 "was already mapped but with different settings.",
12507 table_list->table_id.id());
12508
12509 if (thd->slave_thread)
12510 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
12511 ER(ER_SLAVE_FATAL_ERROR), buf);
12512 else
12513 /*
12514 For the cases in which a 'BINLOG' statement is set to
12515 execute in a user session
12516 */
12517 my_printf_error(ER_SLAVE_FATAL_ERROR, ER(ER_SLAVE_FATAL_ERROR),
12518 MYF(0), buf);
12519 }
12520
12521 my_free(memory);
12522 }
12523
12524 DBUG_RETURN(tblmap_status == SAME_ID_MAPPING_DIFFERENT_TABLE);
12525 }
12526
12527 Log_event::enum_skip_reason
do_shall_skip(Relay_log_info * rli)12528 Table_map_log_event::do_shall_skip(Relay_log_info *rli)
12529 {
12530 /*
12531 If the slave skip counter is 1, then we should not start executing
12532 on the next event.
12533 */
12534 return continue_group(rli);
12535 }
12536
do_update_pos(Relay_log_info * rli)12537 int Table_map_log_event::do_update_pos(Relay_log_info *rli)
12538 {
12539 rli->inc_event_relay_log_pos();
12540 return 0;
12541 }
12542
12543 #endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */
12544
12545 #ifndef MYSQL_CLIENT
write_data_header(IO_CACHE * file)12546 bool Table_map_log_event::write_data_header(IO_CACHE *file)
12547 {
12548 assert(m_table_id.is_valid());
12549 uchar buf[Binary_log_event::TABLE_MAP_HEADER_LEN];
12550 DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master",
12551 {
12552 int4store(buf + 0, static_cast<uint32>(m_table_id.id()));
12553 int2store(buf + 4, m_flags);
12554 return (wrapper_my_b_safe_write(file, buf, 6));
12555 });
12556 int6store(buf + TM_MAPID_OFFSET, m_table_id.id());
12557 int2store(buf + TM_FLAGS_OFFSET, m_flags);
12558 return (wrapper_my_b_safe_write(file, buf, Binary_log_event::TABLE_MAP_HEADER_LEN));
12559 }
12560
write_data_body(IO_CACHE * file)12561 bool Table_map_log_event::write_data_body(IO_CACHE *file)
12562 {
12563 assert(!m_dbnam.empty());
12564 assert(!m_tblnam.empty());
12565 /* We use only one byte per length for storage in event: */
12566 assert(m_dblen <= 128);
12567 assert(m_tbllen <= 128);
12568
12569 uchar const dbuf[]= { (uchar) m_dblen };
12570 uchar const tbuf[]= { (uchar) m_tbllen };
12571
12572 uchar cbuf[sizeof(m_colcnt) + 1];
12573 uchar *const cbuf_end= net_store_length(cbuf, (size_t) m_colcnt);
12574 assert(static_cast<size_t>(cbuf_end - cbuf) <= sizeof(cbuf));
12575
12576 /*
12577 Store the size of the field metadata.
12578 */
12579 uchar mbuf[sizeof(m_field_metadata_size)];
12580 uchar *const mbuf_end= net_store_length(mbuf, m_field_metadata_size);
12581
12582 return (wrapper_my_b_safe_write(file, dbuf, sizeof(dbuf)) ||
12583 wrapper_my_b_safe_write(file,
12584 (const uchar*)m_dbnam.c_str(),
12585 m_dblen+1) ||
12586 wrapper_my_b_safe_write(file, tbuf, sizeof(tbuf)) ||
12587 wrapper_my_b_safe_write(file,
12588 (const uchar*)m_tblnam.c_str(),
12589 m_tbllen+1) ||
12590 wrapper_my_b_safe_write(file, cbuf, (size_t) (cbuf_end - cbuf)) ||
12591 wrapper_my_b_safe_write(file, m_coltype, m_colcnt) ||
12592 wrapper_my_b_safe_write(file, mbuf, (size_t) (mbuf_end - mbuf)) ||
12593 wrapper_my_b_safe_write(file,
12594 m_field_metadata, m_field_metadata_size),
12595 wrapper_my_b_safe_write(file, m_null_bits, (m_colcnt + 7) / 8));
12596 }
12597 #endif
12598
12599 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
12600
12601 /*
12602 Print some useful information for the SHOW BINARY LOG information
12603 field.
12604 */
12605
12606 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
pack_info(Protocol * protocol)12607 int Table_map_log_event::pack_info(Protocol *protocol)
12608 {
12609 char buf[256];
12610 size_t bytes= my_snprintf(buf, sizeof(buf),
12611 "table_id: %llu (%s.%s)",
12612 m_table_id.id(), m_dbnam.c_str(), m_tblnam.c_str());
12613 protocol->store(buf, bytes, &my_charset_bin);
12614 return 0;
12615 }
12616 #endif
12617
12618
12619 #endif
12620
12621
12622 #ifdef MYSQL_CLIENT
print(FILE *,PRINT_EVENT_INFO * print_event_info)12623 void Table_map_log_event::print(FILE *, PRINT_EVENT_INFO *print_event_info)
12624 {
12625 if (!print_event_info->short_form)
12626 {
12627 print_header(&print_event_info->head_cache, print_event_info, TRUE);
12628 my_b_printf(&print_event_info->head_cache,
12629 "\tTable_map: `%s`.`%s` mapped to number %llu\n",
12630 m_dbnam.c_str(), m_tblnam.c_str(), m_table_id.id());
12631 print_base64(&print_event_info->body_cache, print_event_info, TRUE);
12632 }
12633 }
12634 #endif
12635
12636 /**************************************************************************
12637 Write_rows_log_event member functions
12638 **************************************************************************/
12639
12640 /*
12641 Constructor used to build an event for writing to the binary log.
12642 */
12643 #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)12644 Write_rows_log_event::Write_rows_log_event(THD *thd_arg, TABLE *tbl_arg,
12645 const Table_id& tid_arg,
12646 bool is_transactional,
12647 const uchar* extra_row_info)
12648 : binary_log::Rows_event(m_type),
12649 Rows_log_event(thd_arg, tbl_arg, tid_arg, tbl_arg->write_set, is_transactional,
12650 log_bin_use_v1_row_events?
12651 binary_log::WRITE_ROWS_EVENT_V1:
12652 binary_log::WRITE_ROWS_EVENT,
12653 extra_row_info)
12654 {
12655 common_header->type_code= m_type;
12656 }
12657 #endif
12658
12659 /*
12660 Constructor used by slave to read the event from the binary log.
12661 */
12662 #ifdef HAVE_REPLICATION
Write_rows_log_event(const char * buf,uint event_len,const Format_description_event * description_event)12663 Write_rows_log_event::Write_rows_log_event(const char *buf, uint event_len,
12664 const Format_description_event
12665 *description_event)
12666 : binary_log::Rows_event(buf, event_len, description_event),
12667 Rows_log_event(buf, event_len, description_event),
12668 binary_log::Write_rows_event(buf, event_len, description_event)
12669 {
12670 assert(header()->type_code == m_type);
12671 }
12672 #endif
12673
12674 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
12675 int
do_before_row_operations(const Slave_reporting_capability * const)12676 Write_rows_log_event::do_before_row_operations(const Slave_reporting_capability *const)
12677 {
12678 int error= 0;
12679
12680 m_table->file->rpl_before_write_rows();
12681
12682 /*
12683 Increment the global status insert count variable
12684 */
12685 if (get_flags(STMT_END_F))
12686 thd->status_var.com_stat[SQLCOM_INSERT]++;
12687
12688 /*
12689 Let storage engines treat this event as an INSERT command.
12690
12691 Set 'sql_command' as SQLCOM_INSERT after the tables are locked.
12692 When locking the tables, it should be SQLCOM_END.
12693 THD::decide_logging_format which is called from "lock tables"
12694 assumes that row_events will have 'sql_command' as SQLCOM_END.
12695 */
12696 thd->lex->sql_command= SQLCOM_INSERT;
12697
12698 /**
12699 todo: to introduce a property for the event (handler?) which forces
12700 applying the event in the replace (idempotent) fashion.
12701 */
12702 if ((rbr_exec_mode == RBR_EXEC_MODE_IDEMPOTENT) ||
12703 (m_table->s->db_type()->db_type == DB_TYPE_NDBCLUSTER))
12704 {
12705 /*
12706 We are using REPLACE semantics and not INSERT IGNORE semantics
12707 when writing rows, that is: new rows replace old rows. We need to
12708 inform the storage engine that it should use this behaviour.
12709 */
12710
12711 /* Tell the storage engine that we are using REPLACE semantics. */
12712 thd->lex->duplicates= DUP_REPLACE;
12713
12714 /*
12715 Pretend we're executing a REPLACE command: this is needed for
12716 InnoDB and NDB Cluster since they are not (properly) checking the
12717 lex->duplicates flag.
12718 */
12719 thd->lex->sql_command= SQLCOM_REPLACE;
12720 /*
12721 Do not raise the error flag in case of hitting to an unique attribute
12722 */
12723 m_table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
12724 /*
12725 NDB specific: update from ndb master wrapped as Write_rows
12726 so that the event should be applied to replace slave's row
12727 */
12728 m_table->file->extra(HA_EXTRA_WRITE_CAN_REPLACE);
12729 /*
12730 NDB specific: if update from ndb master wrapped as Write_rows
12731 does not find the row it's assumed idempotent binlog applying
12732 is taking place; don't raise the error.
12733 */
12734 m_table->file->extra(HA_EXTRA_IGNORE_NO_KEY);
12735 /*
12736 TODO: the cluster team (Tomas?) says that it's better if the engine knows
12737 how many rows are going to be inserted, then it can allocate needed memory
12738 from the start.
12739 */
12740 }
12741
12742
12743 /* Honor next number column if present */
12744 m_table->next_number_field= m_table->found_next_number_field;
12745 /*
12746 * Fixed Bug#45999, In RBR, Store engine of Slave auto-generates new
12747 * sequence numbers for auto_increment fields if the values of them are 0.
12748 * If generateing a sequence number is decided by the values of
12749 * table->auto_increment_field_not_null and SQL_MODE(if includes
12750 * MODE_NO_AUTO_VALUE_ON_ZERO) in update_auto_increment function.
12751 * SQL_MODE of slave sql thread is always consistency with master's.
12752 * In RBR, auto_increment fields never are NULL, except if the auto_inc
12753 * column exists only on the slave side (i.e., in an extra column
12754 * on the slave's table).
12755 */
12756 if (!is_auto_inc_in_extra_columns())
12757 m_table->auto_increment_field_not_null= TRUE;
12758 else
12759 {
12760 /*
12761 Here we have checked that there is an extra field
12762 on this server's table that has an auto_inc column.
12763
12764 Mark that the auto_increment field is null and mark
12765 the read and write set bits.
12766
12767 (There can only be one AUTO_INC column, it is always
12768 indexed and it cannot have a DEFAULT value).
12769 */
12770 m_table->auto_increment_field_not_null= FALSE;
12771 m_table->mark_auto_increment_column();
12772 }
12773
12774 /**
12775 Sets it to ROW_LOOKUP_NOT_NEEDED.
12776 */
12777 decide_row_lookup_algorithm_and_key();
12778 assert(m_rows_lookup_algorithm==ROW_LOOKUP_NOT_NEEDED);
12779
12780 return error;
12781 }
12782
12783 int
do_after_row_operations(const Slave_reporting_capability * const,int error)12784 Write_rows_log_event::do_after_row_operations(const Slave_reporting_capability *const,
12785 int error)
12786 {
12787 int local_error= 0;
12788
12789 /**
12790 Clear the write_set bit for auto_inc field that only
12791 existed on the destination table as an extra column.
12792 */
12793 if (is_auto_inc_in_extra_columns())
12794 {
12795 bitmap_clear_bit(m_table->write_set, m_table->next_number_field->field_index);
12796 bitmap_clear_bit( m_table->read_set, m_table->next_number_field->field_index);
12797
12798 if (get_flags(STMT_END_F))
12799 m_table->file->ha_release_auto_increment();
12800 }
12801 m_table->next_number_field=0;
12802 m_table->auto_increment_field_not_null= FALSE;
12803 if ((rbr_exec_mode == RBR_EXEC_MODE_IDEMPOTENT) ||
12804 m_table->s->db_type()->db_type == DB_TYPE_NDBCLUSTER)
12805 {
12806 m_table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
12807 m_table->file->extra(HA_EXTRA_WRITE_CANNOT_REPLACE);
12808 /*
12809 resetting the extra with
12810 table->file->extra(HA_EXTRA_NO_IGNORE_NO_KEY);
12811 fires bug#27077
12812 explanation: file->reset() performs this duty
12813 ultimately. Still todo: fix
12814 */
12815 }
12816 if ((local_error= m_table->file->ha_end_bulk_insert()))
12817 {
12818 m_table->file->print_error(local_error, MYF(0));
12819 }
12820
12821 m_rows_lookup_algorithm= ROW_LOOKUP_UNDEFINED;
12822 m_table->file->rpl_after_write_rows();
12823
12824 return error? error : local_error;
12825 }
12826
12827 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
12828
12829 /*
12830 Check if there are more UNIQUE keys after the given key.
12831 */
12832 static int
last_uniq_key(TABLE * table,uint keyno)12833 last_uniq_key(TABLE *table, uint keyno)
12834 {
12835 while (++keyno < table->s->keys)
12836 if (table->key_info[keyno].flags & HA_NOSAME)
12837 return 0;
12838 return 1;
12839 }
12840
12841 /**
12842 Check if an error is a duplicate key error.
12843
12844 This function is used to check if an error code is one of the
12845 duplicate key error, i.e., and error code for which it is sensible
12846 to do a <code>get_dup_key()</code> to retrieve the duplicate key.
12847
12848 @param errcode The error code to check.
12849
12850 @return <code>true</code> if the error code is such that
12851 <code>get_dup_key()</code> will return true, <code>false</code>
12852 otherwise.
12853 */
12854 bool
is_duplicate_key_error(int errcode)12855 is_duplicate_key_error(int errcode)
12856 {
12857 switch (errcode)
12858 {
12859 case HA_ERR_FOUND_DUPP_KEY:
12860 case HA_ERR_FOUND_DUPP_UNIQUE:
12861 return true;
12862 }
12863 return false;
12864 }
12865
12866 /**
12867 Write the current row into event's table.
12868
12869 The row is located in the row buffer, pointed by @c m_curr_row member.
12870 Number of columns of the row is stored in @c m_width member (it can be
12871 different from the number of columns in the table to which we insert).
12872 Bitmap @c m_cols indicates which columns are present in the row. It is assumed
12873 that event's table is already open and pointed by @c m_table.
12874
12875 If the same record already exists in the table it can be either overwritten
12876 or an error is reported depending on the value of @c overwrite flag
12877 (error reporting not yet implemented). Note that the matching record can be
12878 different from the row we insert if we use primary keys to identify records in
12879 the table.
12880
12881 The row to be inserted can contain values only for selected columns. The
12882 missing columns are filled with default values using @c prepare_record()
12883 function. If a matching record is found in the table and @c overwritte is
12884 true, the missing columns are taken from it.
12885
12886 @param rli Relay log info (needed for row unpacking).
12887 @param overwrite
12888 Shall we overwrite if the row already exists or signal
12889 error (currently ignored).
12890
12891 @returns Error code on failure, 0 on success.
12892
12893 This method, if successful, sets @c m_curr_row_end pointer to point at the
12894 next row in the rows buffer. This is done when unpacking the row to be
12895 inserted.
12896
12897 @note If a matching record is found, it is either updated using
12898 @c ha_update_row() or first deleted and then new record written.
12899 */
12900
12901 int
write_row(const Relay_log_info * const rli,const bool overwrite)12902 Write_rows_log_event::write_row(const Relay_log_info *const rli,
12903 const bool overwrite)
12904 {
12905 DBUG_ENTER("write_row");
12906 assert(m_table != NULL && thd != NULL);
12907
12908 TABLE *table= m_table; // pointer to event's table
12909 int error;
12910 int keynum= 0;
12911 char* key= NULL;
12912
12913 prepare_record(table, &m_cols,
12914 table->file->ht->db_type != DB_TYPE_NDBCLUSTER);
12915
12916 /* unpack row into table->record[0] */
12917 if ((error= unpack_current_row(rli, &m_cols)))
12918 DBUG_RETURN(error);
12919
12920 /*
12921 When m_curr_row == m_curr_row_end, it means a row that contains nothing,
12922 so all the pointers shall be pointing to the same address, or else
12923 we have corrupt data and shall throw the error.
12924 */
12925 DBUG_PRINT("debug",("m_rows_buf= %p, m_rows_cur= %p, m_rows_end= %p",
12926 m_rows_buf, m_rows_cur, m_rows_end));
12927 DBUG_PRINT("debug",("m_curr_row= %p, m_curr_row_end= %p",
12928 m_curr_row, m_curr_row_end));
12929 if (m_curr_row == m_curr_row_end &&
12930 !((m_rows_buf == m_rows_cur) && (m_rows_cur == m_rows_end)))
12931 {
12932 my_error(ER_SLAVE_CORRUPT_EVENT, MYF(0));
12933 DBUG_RETURN(ER_SLAVE_CORRUPT_EVENT);
12934 }
12935
12936 if (m_curr_row == m_rows_buf)
12937 {
12938 /* this is the first row to be inserted, we estimate the rows with
12939 the size of the first row and use that value to initialize
12940 storage engine for bulk insertion */
12941 assert(!(m_curr_row > m_curr_row_end));
12942 ulong estimated_rows= 0;
12943 if (m_curr_row < m_curr_row_end)
12944 estimated_rows= (m_rows_end - m_curr_row) / (m_curr_row_end - m_curr_row);
12945 else if (m_curr_row == m_curr_row_end)
12946 estimated_rows= 1;
12947
12948 m_table->file->ha_start_bulk_insert(estimated_rows);
12949 }
12950
12951 /*
12952 Explicitly set the auto_inc to null to make sure that
12953 it gets an auto_generated value.
12954 */
12955 if (is_auto_inc_in_extra_columns())
12956 m_table->next_number_field->set_null();
12957
12958 #ifndef NDEBUG
12959 DBUG_DUMP("record[0]", table->record[0], table->s->reclength);
12960 DBUG_PRINT_BITSET("debug", "write_set = %s", table->write_set);
12961 DBUG_PRINT_BITSET("debug", "read_set = %s", table->read_set);
12962 #endif
12963
12964 /*
12965 Try to write record. If a corresponding record already exists in the table,
12966 we try to change it using ha_update_row() if possible. Otherwise we delete
12967 it and repeat the whole process again.
12968
12969 TODO: Add safety measures against infinite looping.
12970 */
12971
12972 m_table->mark_columns_per_binlog_row_image();
12973
12974 while ((error= table->file->ha_write_row(table->record[0])))
12975 {
12976 if (error == HA_ERR_LOCK_DEADLOCK ||
12977 error == HA_ERR_LOCK_WAIT_TIMEOUT ||
12978 (keynum= table->file->get_dup_key(error)) < 0 ||
12979 !overwrite)
12980 {
12981 DBUG_PRINT("info",("get_dup_key returns %d)", keynum));
12982 /*
12983 Deadlock, waiting for lock or just an error from the handler
12984 such as HA_ERR_FOUND_DUPP_KEY when overwrite is false.
12985 Retrieval of the duplicate key number may fail
12986 - either because the error was not "duplicate key" error
12987 - or because the information which key is not available
12988 */
12989 table->file->print_error(error, MYF(0));
12990 goto error;
12991 }
12992 /*
12993 key index value is either valid in the range [0-MAX_KEY) or
12994 has value MAX_KEY as a marker for the case when no information
12995 about key can be found. In the last case we have to require
12996 that storage engine has the flag HA_DUPLICATE_POS turned on.
12997 If this invariant is false then assert will crash
12998 the server built in debug mode. For the server that was built
12999 without DEBUG we have additional check for the value of key index
13000 in the code below in order to report about error in any case.
13001 */
13002 assert(keynum != MAX_KEY ||
13003 (keynum == MAX_KEY &&
13004 (table->file->ha_table_flags() & HA_DUPLICATE_POS)));
13005 /*
13006 We need to retrieve the old row into record[1] to be able to
13007 either update or delete the offending record. We either:
13008
13009 - use ha_rnd_pos() with a row-id (available as dupp_row) to the
13010 offending row, if that is possible (MyISAM and Blackhole), or else
13011
13012 - use ha_index_read_idx_map() with the key that is duplicated, to
13013 retrieve the offending row.
13014 */
13015 if (table->file->ha_table_flags() & HA_DUPLICATE_POS)
13016 {
13017 DBUG_PRINT("info",("Locating offending record using ha_rnd_pos()"));
13018
13019 if (table->file->inited && (error= table->file->ha_index_end()))
13020 {
13021 table->file->print_error(error, MYF(0));
13022 goto error;
13023 }
13024 if ((error= table->file->ha_rnd_init(FALSE)))
13025 {
13026 table->file->print_error(error, MYF(0));
13027 goto error;
13028 }
13029
13030 error= table->file->ha_rnd_pos(table->record[1], table->file->dup_ref);
13031
13032 table->file->ha_rnd_end();
13033 if (error)
13034 {
13035 DBUG_PRINT("info",("ha_rnd_pos() returns error %d",error));
13036 if (error == HA_ERR_RECORD_DELETED)
13037 error= HA_ERR_KEY_NOT_FOUND;
13038 table->file->print_error(error, MYF(0));
13039 goto error;
13040 }
13041 }
13042 else
13043 {
13044 DBUG_PRINT("info",("Locating offending record using index_read_idx()"));
13045
13046 if (table->file->extra(HA_EXTRA_FLUSH_CACHE))
13047 {
13048 DBUG_PRINT("info",("Error when setting HA_EXTRA_FLUSH_CACHE"));
13049 error= my_errno();
13050 goto error;
13051 }
13052
13053 if (key == NULL)
13054 {
13055 key= static_cast<char*>(my_alloca(table->s->max_unique_length));
13056 if (key == NULL)
13057 {
13058 DBUG_PRINT("info",("Can't allocate key buffer"));
13059 error= ENOMEM;
13060 goto error;
13061 }
13062 }
13063
13064 if ((uint)keynum < MAX_KEY)
13065 {
13066 key_copy((uchar*)key, table->record[0], table->key_info + keynum,
13067 0);
13068 error= table->file->ha_index_read_idx_map(table->record[1], keynum,
13069 (const uchar*)key,
13070 HA_WHOLE_KEY,
13071 HA_READ_KEY_EXACT);
13072 }
13073 else
13074 /*
13075 For the server built in non-debug mode returns error if
13076 handler::get_dup_key() returned MAX_KEY as the value of key index.
13077 */
13078 error= HA_ERR_FOUND_DUPP_KEY;
13079
13080 if (error)
13081 {
13082 DBUG_PRINT("info",("ha_index_read_idx_map() returns %s", HA_ERR(error)));
13083 if (error == HA_ERR_RECORD_DELETED)
13084 error= HA_ERR_KEY_NOT_FOUND;
13085 table->file->print_error(error, MYF(0));
13086 goto error;
13087 }
13088 }
13089
13090 /*
13091 Now, record[1] should contain the offending row. That
13092 will enable us to update it or, alternatively, delete it (so
13093 that we can insert the new row afterwards).
13094 */
13095
13096 /*
13097 If row is incomplete we will use the record found to fill
13098 missing columns.
13099 */
13100 if (!get_flags(COMPLETE_ROWS_F))
13101 {
13102 restore_record(table,record[1]);
13103 error= unpack_current_row(rli, &m_cols);
13104 }
13105
13106 #ifndef NDEBUG
13107 DBUG_PRINT("debug",("preparing for update: before and after image"));
13108 DBUG_DUMP("record[1] (before)", table->record[1], table->s->reclength);
13109 DBUG_DUMP("record[0] (after)", table->record[0], table->s->reclength);
13110 #endif
13111
13112 /*
13113 REPLACE is defined as either INSERT or DELETE + INSERT. If
13114 possible, we can replace it with an UPDATE, but that will not
13115 work on InnoDB if FOREIGN KEY checks are necessary.
13116
13117 I (Matz) am not sure of the reason for the last_uniq_key()
13118 check as, but I'm guessing that it's something along the
13119 following lines.
13120
13121 Suppose that we got the duplicate key to be a key that is not
13122 the last unique key for the table and we perform an update:
13123 then there might be another key for which the unique check will
13124 fail, so we're better off just deleting the row and inserting
13125 the correct row.
13126 */
13127 if (last_uniq_key(table, keynum) &&
13128 !table->file->referenced_by_foreign_key())
13129 {
13130 DBUG_PRINT("info",("Updating row using ha_update_row()"));
13131 error=table->file->ha_update_row(table->record[1],
13132 table->record[0]);
13133 switch (error) {
13134
13135 case HA_ERR_RECORD_IS_THE_SAME:
13136 DBUG_PRINT("info",("ignoring HA_ERR_RECORD_IS_THE_SAME error from"
13137 " ha_update_row()"));
13138 error= 0;
13139
13140 case 0:
13141 break;
13142
13143 default:
13144 DBUG_PRINT("info",("ha_update_row() returns error %d",error));
13145 table->file->print_error(error, MYF(0));
13146 }
13147
13148 goto error;
13149 }
13150 else
13151 {
13152 DBUG_PRINT("info",("Deleting offending row and trying to write new one again"));
13153 if ((error= table->file->ha_delete_row(table->record[1])))
13154 {
13155 DBUG_PRINT("info",("ha_delete_row() returns error %d",error));
13156 table->file->print_error(error, MYF(0));
13157 goto error;
13158 }
13159 /* Will retry ha_write_row() with the offending row removed. */
13160 }
13161 }
13162
13163 error:
13164 m_table->default_column_bitmaps();
13165 DBUG_RETURN(error);
13166 }
13167
13168 #endif
13169
13170 int
do_exec_row(const Relay_log_info * const rli)13171 Write_rows_log_event::do_exec_row(const Relay_log_info *const rli)
13172 {
13173 assert(m_table != NULL);
13174 int error= write_row(rli, rbr_exec_mode == RBR_EXEC_MODE_IDEMPOTENT);
13175
13176 if (error && !thd->is_error())
13177 {
13178 assert(0);
13179 my_error(ER_UNKNOWN_ERROR, MYF(0));
13180 }
13181
13182 return error;
13183 }
13184
13185 #endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */
13186
13187 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)13188 void Write_rows_log_event::print(FILE *file, PRINT_EVENT_INFO* print_event_info)
13189 {
13190 DBUG_EXECUTE_IF("simulate_cache_read_error",
13191 {DBUG_SET("+d,simulate_my_b_fill_error");});
13192 Rows_log_event::print_helper(file, print_event_info, "Write_rows");
13193 }
13194 #endif
13195
13196 /**************************************************************************
13197 Delete_rows_log_event member functions
13198 **************************************************************************/
13199
13200 /*
13201 Constructor used to build an event for writing to the binary log.
13202 */
13203
13204 #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)13205 Delete_rows_log_event::Delete_rows_log_event(THD *thd_arg, TABLE *tbl_arg,
13206 const Table_id& tid,
13207 bool is_transactional,
13208 const uchar* extra_row_info)
13209 : binary_log::Rows_event(m_type),
13210 Rows_log_event(thd_arg, tbl_arg, tid, tbl_arg->read_set, is_transactional,
13211 log_bin_use_v1_row_events?
13212 binary_log::DELETE_ROWS_EVENT_V1:
13213 binary_log::DELETE_ROWS_EVENT,
13214 extra_row_info),
13215 binary_log::Delete_rows_event()
13216 {
13217 common_header->type_code= m_type;
13218 }
13219 #endif /* #if !defined(MYSQL_CLIENT) */
13220
13221 /*
13222 Constructor used by slave to read the event from the binary log.
13223 */
13224 #ifdef HAVE_REPLICATION
Delete_rows_log_event(const char * buf,uint event_len,const Format_description_event * description_event)13225 Delete_rows_log_event::Delete_rows_log_event(const char *buf, uint event_len,
13226 const Format_description_event
13227 *description_event)
13228 : binary_log::Rows_event(buf, event_len, description_event),
13229 Rows_log_event(buf, event_len, description_event),
13230 binary_log::Delete_rows_event(buf, event_len, description_event)
13231 {
13232 assert(header()->type_code == m_type);
13233 }
13234 #endif
13235
13236 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
13237
13238 int
do_before_row_operations(const Slave_reporting_capability * const)13239 Delete_rows_log_event::do_before_row_operations(const Slave_reporting_capability *const)
13240 {
13241 int error= 0;
13242 DBUG_ENTER("Delete_rows_log_event::do_before_row_operations");
13243 m_table->file->rpl_before_delete_rows();
13244 /*
13245 Increment the global status delete count variable
13246 */
13247 if (get_flags(STMT_END_F))
13248 thd->status_var.com_stat[SQLCOM_DELETE]++;
13249
13250 /*
13251 Let storage engines treat this event as a DELETE command.
13252
13253 Set 'sql_command' as SQLCOM_UPDATE after the tables are locked.
13254 When locking the tables, it should be SQLCOM_END.
13255 THD::decide_logging_format which is called from "lock tables"
13256 assumes that row_events will have 'sql_command' as SQLCOM_END.
13257 */
13258 thd->lex->sql_command= SQLCOM_DELETE;
13259
13260 error= row_operations_scan_and_key_setup();
13261 DBUG_RETURN(error);
13262
13263 }
13264
13265 int
do_after_row_operations(const Slave_reporting_capability * const,int error)13266 Delete_rows_log_event::do_after_row_operations(const Slave_reporting_capability *const,
13267 int error)
13268 {
13269 DBUG_ENTER("Delete_rows_log_event::do_after_row_operations");
13270 error= row_operations_scan_and_key_teardown(error);
13271 m_table->file->rpl_after_delete_rows();
13272 DBUG_RETURN(error);
13273 }
13274
do_exec_row(const Relay_log_info * const rli)13275 int Delete_rows_log_event::do_exec_row(const Relay_log_info *const rli)
13276 {
13277 int error;
13278 assert(m_table != NULL);
13279 if (m_rows_lookup_algorithm == ROW_LOOKUP_NOT_NEEDED) {
13280 error= unpack_current_row(rli, &m_cols);
13281 if (error)
13282 return error;
13283 }
13284 /* m_table->record[0] contains the BI */
13285 m_table->mark_columns_per_binlog_row_image();
13286 error= m_table->file->ha_delete_row(m_table->record[0]);
13287 m_table->default_column_bitmaps();
13288 return error;
13289 }
13290
13291 #endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */
13292
13293 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)13294 void Delete_rows_log_event::print(FILE *file,
13295 PRINT_EVENT_INFO* print_event_info)
13296 {
13297 Rows_log_event::print_helper(file, print_event_info, "Delete_rows");
13298 }
13299 #endif
13300
13301
13302 /**************************************************************************
13303 Update_rows_log_event member functions
13304 **************************************************************************/
13305
13306 /*
13307 Constructor used to build an event for writing to the binary log.
13308 */
13309 #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)13310 Update_rows_log_event::Update_rows_log_event(THD *thd_arg, TABLE *tbl_arg,
13311 const Table_id& tid,
13312 bool is_transactional,
13313 const uchar* extra_row_info)
13314 : binary_log::Rows_event(m_type),
13315 Rows_log_event(thd_arg, tbl_arg, tid, tbl_arg->read_set, is_transactional,
13316 log_bin_use_v1_row_events?
13317 binary_log::UPDATE_ROWS_EVENT_V1:
13318 binary_log::UPDATE_ROWS_EVENT,
13319 extra_row_info)
13320 {
13321 common_header->type_code= m_type;
13322 init(tbl_arg->write_set);
13323 if (Rows_log_event::is_valid() && m_cols_ai.bitmap)
13324 is_valid_param= true;
13325 }
13326
init(MY_BITMAP const * cols)13327 void Update_rows_log_event::init(MY_BITMAP const *cols)
13328 {
13329 /* if bitmap_init fails, caught in is_valid() */
13330 if (likely(!bitmap_init(&m_cols_ai,
13331 m_width <= sizeof(m_bitbuf_ai)*8 ? m_bitbuf_ai : NULL,
13332 m_width,
13333 false)))
13334 {
13335 /* Cols can be zero if this is a dummy binrows event */
13336 if (likely(cols != NULL))
13337 {
13338 memcpy(m_cols_ai.bitmap, cols->bitmap, no_bytes_in_map(cols));
13339 create_last_word_mask(&m_cols_ai);
13340 }
13341 }
13342 }
13343 #endif /* !defined(MYSQL_CLIENT) */
13344
13345
~Update_rows_log_event()13346 Update_rows_log_event::~Update_rows_log_event()
13347 {
13348 if (m_cols_ai.bitmap) {
13349 if (m_cols_ai.bitmap == m_bitbuf_ai) // no my_malloc happened
13350 m_cols_ai.bitmap= 0; // so no my_free in bitmap_free
13351 bitmap_free(&m_cols_ai); // To pair with bitmap_init().
13352 }
13353 }
13354
13355
13356 /*
13357 Constructor used by slave to read the event from the binary log.
13358 */
13359 #ifdef HAVE_REPLICATION
Update_rows_log_event(const char * buf,uint event_len,const Format_description_event * description_event)13360 Update_rows_log_event::Update_rows_log_event(const char *buf, uint event_len,
13361 const Format_description_event
13362 *description_event)
13363 : binary_log::Rows_event(buf, event_len, description_event),
13364 Rows_log_event(buf, event_len, description_event),
13365 binary_log::Update_rows_event(buf, event_len, description_event)
13366 {
13367 if (Rows_log_event::is_valid() && m_cols_ai.bitmap)
13368 is_valid_param= true;
13369 assert(header()->type_code== m_type);
13370 }
13371 #endif
13372
13373 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
13374
13375 int
do_before_row_operations(const Slave_reporting_capability * const)13376 Update_rows_log_event::do_before_row_operations(const Slave_reporting_capability *const)
13377 {
13378 int error= 0;
13379 DBUG_ENTER("Update_rows_log_event::do_before_row_operations");
13380 m_table->file->rpl_before_update_rows();
13381 /*
13382 Increment the global status update count variable
13383 */
13384 if (get_flags(STMT_END_F))
13385 thd->status_var.com_stat[SQLCOM_UPDATE]++;
13386
13387 /*
13388 Let storage engines treat this event as an UPDATE command.
13389
13390 Set 'sql_command' as SQLCOM_UPDATE after the tables are locked.
13391 When locking the tables, it should be SQLCOM_END.
13392 THD::decide_logging_format which is called from "lock tables"
13393 assumes that row_events will have 'sql_command' as SQLCOM_END.
13394 */
13395 thd->lex->sql_command= SQLCOM_UPDATE;
13396
13397 error= row_operations_scan_and_key_setup();
13398 DBUG_RETURN(error);
13399
13400 }
13401
13402 int
do_after_row_operations(const Slave_reporting_capability * const,int error)13403 Update_rows_log_event::do_after_row_operations(const Slave_reporting_capability *const,
13404 int error)
13405 {
13406 DBUG_ENTER("Update_rows_log_event::do_after_row_operations");
13407 error= row_operations_scan_and_key_teardown(error);
13408 m_table->file->rpl_after_update_rows();
13409 DBUG_RETURN(error);
13410 }
13411
13412 int
do_exec_row(const Relay_log_info * const rli)13413 Update_rows_log_event::do_exec_row(const Relay_log_info *const rli)
13414 {
13415 assert(m_table != NULL);
13416 int error= 0;
13417
13418 if (m_rows_lookup_algorithm == ROW_LOOKUP_NOT_NEEDED) {
13419 error= unpack_current_row(rli, &m_cols);
13420 if (error)
13421 return error;
13422 }
13423
13424 /*
13425 This is the situation after locating BI:
13426
13427 ===|=== before image ====|=== after image ===|===
13428 ^ ^
13429 m_curr_row m_curr_row_end
13430
13431 BI found in the table is stored in record[0]. We copy it to record[1]
13432 and unpack AI to record[0].
13433 */
13434
13435 store_record(m_table,record[1]);
13436
13437 m_curr_row= m_curr_row_end;
13438 /* this also updates m_curr_row_end */
13439 if ((error= unpack_current_row(rli, &m_cols_ai)))
13440 return error;
13441
13442 /*
13443 Now we have the right row to update. The old row (the one we're
13444 looking for) is in record[1] and the new row is in record[0].
13445 */
13446 DBUG_PRINT("info",("Updating row in table"));
13447 DBUG_DUMP("old record", m_table->record[1], m_table->s->reclength);
13448 DBUG_DUMP("new values", m_table->record[0], m_table->s->reclength);
13449
13450 m_table->mark_columns_per_binlog_row_image();
13451 error= m_table->file->ha_update_row(m_table->record[1], m_table->record[0]);
13452 if (error == HA_ERR_RECORD_IS_THE_SAME)
13453 error= 0;
13454 m_table->default_column_bitmaps();
13455
13456 return error;
13457 }
13458
13459 #endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */
13460
13461 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)13462 void Update_rows_log_event::print(FILE *file,
13463 PRINT_EVENT_INFO* print_event_info)
13464 {
13465 Rows_log_event::print_helper(file, print_event_info, "Update_rows");
13466 }
13467 #endif
13468
13469
13470 Incident_log_event::
Incident_log_event(const char * buf,uint event_len,const Format_description_event * description_event)13471 Incident_log_event(const char *buf, uint event_len,
13472 const Format_description_event *description_event)
13473 : binary_log::Incident_event(buf, event_len, description_event),
13474 Log_event(header(), footer())
13475 {
13476 DBUG_ENTER("Incident_log_event::Incident_log_event");
13477 if (incident > INCIDENT_NONE && incident < INCIDENT_COUNT)
13478 is_valid_param= true;
13479 DBUG_VOID_RETURN;
13480 }
13481
13482
~Incident_log_event()13483 Incident_log_event::~Incident_log_event()
13484 {
13485 if (message)
13486 bapi_free(message);
13487 }
13488
13489
13490 const char *
description() const13491 Incident_log_event::description() const
13492 {
13493 static const char *const description[]= {
13494 "NOTHING", // Not used
13495 "LOST_EVENTS"
13496 };
13497
13498 DBUG_PRINT("info", ("incident: %d", incident));
13499
13500 return description[incident];
13501 }
13502
13503
13504 #ifndef MYSQL_CLIENT
pack_info(Protocol * protocol)13505 int Incident_log_event::pack_info(Protocol *protocol)
13506 {
13507 char buf[256];
13508 size_t bytes;
13509 if (message_length > 0)
13510 bytes= my_snprintf(buf, sizeof(buf), "#%d (%s)",
13511 incident, description());
13512 else
13513 bytes= my_snprintf(buf, sizeof(buf), "#%d (%s): %s",
13514 incident, description(), message);
13515 protocol->store(buf, bytes, &my_charset_bin);
13516 return 0;
13517 }
13518 #endif
13519
13520
13521 #ifdef MYSQL_CLIENT
13522 void
print(FILE * file,PRINT_EVENT_INFO * print_event_info)13523 Incident_log_event::print(FILE *file,
13524 PRINT_EVENT_INFO *print_event_info)
13525 {
13526 if (print_event_info->short_form)
13527 return;
13528
13529 print_header(&print_event_info->head_cache, print_event_info, FALSE);
13530 my_b_printf(&print_event_info->head_cache,
13531 "\n# Incident: %s\nRELOAD DATABASE; # Shall generate syntax error\n",
13532 description());
13533 }
13534 #endif
13535
13536 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
13537 int
do_apply_event(Relay_log_info const * rli)13538 Incident_log_event::do_apply_event(Relay_log_info const *rli)
13539 {
13540 DBUG_ENTER("Incident_log_event::do_apply_event");
13541
13542 /*
13543 It is not necessary to do GTID related check if the error
13544 'ER_SLAVE_INCIDENT' is ignored.
13545 */
13546 if (ignored_error_code(ER_SLAVE_INCIDENT))
13547 {
13548 DBUG_PRINT("info", ("Ignoring Incident"));
13549 mysql_bin_log.gtid_end_transaction(thd);
13550 DBUG_RETURN(0);
13551 }
13552
13553 enum_gtid_statement_status state= gtid_pre_statement_checks(thd);
13554 if (state == GTID_STATEMENT_EXECUTE)
13555 {
13556 if (gtid_pre_statement_post_implicit_commit_checks(thd))
13557 state= GTID_STATEMENT_CANCEL;
13558 }
13559
13560 if (state == GTID_STATEMENT_CANCEL)
13561 {
13562 uint error= thd->get_stmt_da()->mysql_errno();
13563 assert(error != 0);
13564 rli->report(ERROR_LEVEL, error,
13565 "Error executing incident event: '%s'",
13566 thd->get_stmt_da()->message_text());
13567 thd->is_slave_error= 1;
13568 DBUG_RETURN(-1);
13569 }
13570 else if (state == GTID_STATEMENT_SKIP)
13571 {
13572 /*
13573 Make slave skip the Incident event through general commands of GTID
13574 i.e. 'set gtid_next=<GTID>; begin; commit;'.
13575 */
13576 DBUG_RETURN(0);
13577 }
13578
13579 rli->report(ERROR_LEVEL, ER_SLAVE_INCIDENT,
13580 ER(ER_SLAVE_INCIDENT),
13581 description(),
13582 message_length > 0 ? message : "<none>");
13583 DBUG_RETURN(1);
13584 }
13585 #endif
13586
13587 bool
write_data_header(IO_CACHE * file)13588 Incident_log_event::write_data_header(IO_CACHE *file)
13589 {
13590 DBUG_ENTER("Incident_log_event::write_data_header");
13591 DBUG_PRINT("enter", ("incident: %d", incident));
13592 uchar buf[sizeof(int16)];
13593 int2store(buf, (int16) incident);
13594 #ifndef MYSQL_CLIENT
13595 DBUG_RETURN(wrapper_my_b_safe_write(file, buf, sizeof(buf)));
13596 #else
13597 DBUG_RETURN(my_b_safe_write(file, buf, sizeof(buf)));
13598 #endif
13599 }
13600
13601 bool
write_data_body(IO_CACHE * file)13602 Incident_log_event::write_data_body(IO_CACHE *file)
13603 {
13604 uchar tmp[1];
13605 DBUG_ENTER("Incident_log_event::write_data_body");
13606 tmp[0]= (uchar) message_length;
13607 crc= checksum_crc32(crc, (uchar*) tmp, 1);
13608 if (message_length > 0)
13609 {
13610 crc= checksum_crc32(crc, (uchar*) message, message_length);
13611 // todo: report a bug on write_str accepts uint but treats it as uchar
13612 }
13613 DBUG_RETURN(write_str_at_most_255_bytes(file, message, (uint) message_length, &event_encrypter));
13614 }
13615
13616
Ignorable_log_event(const char * buf,const Format_description_event * descr_event)13617 Ignorable_log_event::Ignorable_log_event(const char *buf,
13618 const Format_description_event *descr_event)
13619 : binary_log::Ignorable_event(buf, descr_event),
13620 Log_event(header(), footer())
13621 {
13622 DBUG_ENTER("Ignorable_log_event::Ignorable_log_event");
13623
13624 is_valid_param= true;
13625 DBUG_VOID_RETURN;
13626 }
13627
~Ignorable_log_event()13628 Ignorable_log_event::~Ignorable_log_event()
13629 {
13630 }
13631
13632 #ifndef MYSQL_CLIENT
13633 /* Pack info for its unrecognized ignorable event */
pack_info(Protocol * protocol)13634 int Ignorable_log_event::pack_info(Protocol *protocol)
13635 {
13636 char buf[256];
13637 size_t bytes;
13638 bytes= my_snprintf(buf, sizeof(buf), "# Unrecognized ignorable event");
13639 protocol->store(buf, bytes, &my_charset_bin);
13640 return 0;
13641 }
13642 #endif
13643
13644 #ifdef MYSQL_CLIENT
13645 /* Print for its unrecognized ignorable event */
13646 void
print(FILE * file,PRINT_EVENT_INFO * print_event_info)13647 Ignorable_log_event::print(FILE *file,
13648 PRINT_EVENT_INFO *print_event_info)
13649 {
13650 if (print_event_info->short_form)
13651 return;
13652
13653 print_header(&print_event_info->head_cache, print_event_info, FALSE);
13654 my_b_printf(&print_event_info->head_cache, "\tIgnorable\n");
13655 my_b_printf(&print_event_info->head_cache,
13656 "# Unrecognized ignorable event\n");
13657 }
13658 #endif
13659
13660
Rows_query_log_event(const char * buf,uint event_len,const Format_description_event * descr_event)13661 Rows_query_log_event::Rows_query_log_event(const char *buf, uint event_len,
13662 const Format_description_event
13663 *descr_event)
13664 : binary_log::Ignorable_event(buf, descr_event),
13665 Ignorable_log_event(buf, descr_event),
13666 binary_log::Rows_query_event(buf, event_len, descr_event)
13667 {
13668 is_valid_param= (m_rows_query != NULL);
13669 }
13670
13671 #ifndef MYSQL_CLIENT
pack_info(Protocol * protocol)13672 int Rows_query_log_event::pack_info(Protocol *protocol)
13673 {
13674 char *buf;
13675 size_t bytes;
13676 size_t len= sizeof("# ") + strlen(m_rows_query);
13677 if (!(buf= (char*) my_malloc(key_memory_log_event,
13678 len, MYF(MY_WME))))
13679 return 1;
13680 bytes= my_snprintf(buf, len, "# %s", m_rows_query);
13681 protocol->store(buf, bytes, &my_charset_bin);
13682 my_free(buf);
13683 return 0;
13684 }
13685 #endif
13686
13687 #ifdef MYSQL_CLIENT
13688 void
print(FILE * file,PRINT_EVENT_INFO * print_event_info)13689 Rows_query_log_event::print(FILE *file,
13690 PRINT_EVENT_INFO *print_event_info)
13691 {
13692 if (!print_event_info->short_form && print_event_info->verbose > 1)
13693 {
13694 IO_CACHE *const head= &print_event_info->head_cache;
13695 IO_CACHE *const body= &print_event_info->body_cache;
13696 char *token= NULL, *saveptr= NULL;
13697 char *rows_query_copy= NULL;
13698 if (!(rows_query_copy= my_strdup(key_memory_log_event,
13699 m_rows_query, MYF(MY_WME))))
13700 return;
13701
13702 print_header(head, print_event_info, FALSE);
13703 my_b_printf(head, "\tRows_query\n");
13704 /*
13705 Prefix every line of a multi-line query with '#' to prevent the
13706 statement from being executed when binary log will be processed
13707 using 'mysqlbinlog --verbose --verbose'.
13708 */
13709 for (token= my_strtok_r(rows_query_copy, "\n", &saveptr); token;
13710 token= my_strtok_r(NULL, "\n", &saveptr))
13711 my_b_printf(head, "# %s\n", token);
13712 my_free(rows_query_copy);
13713 print_base64(body, print_event_info, true);
13714 }
13715 }
13716 #endif
13717
13718 bool
write_data_body(IO_CACHE * file)13719 Rows_query_log_event::write_data_body(IO_CACHE *file)
13720 {
13721 DBUG_ENTER("Rows_query_log_event::write_data_body");
13722 /*
13723 m_rows_query length will be stored using only one byte, but on read
13724 that length will be ignored and the complete query will be read.
13725 */
13726 DBUG_RETURN(write_str_at_most_255_bytes(file, m_rows_query,
13727 strlen(m_rows_query), &event_encrypter));
13728 }
13729
13730 #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION)
do_apply_event(Relay_log_info const * rli)13731 int Rows_query_log_event::do_apply_event(Relay_log_info const *rli)
13732 {
13733 DBUG_ENTER("Rows_query_log_event::do_apply_event");
13734 assert(rli->info_thd == thd);
13735 /* Set query for writing Rows_query log event into binlog later.*/
13736 thd->set_query(m_rows_query, strlen(m_rows_query));
13737 thd->set_query_for_display(m_rows_query, strlen(m_rows_query));
13738
13739 assert(rli->rows_query_ev == NULL);
13740
13741 const_cast<Relay_log_info*>(rli)->rows_query_ev= this;
13742 /* Tell worker not to free the event */
13743 worker= NULL;
13744 DBUG_EXECUTE_IF("error_on_rows_query_event_apply", { DBUG_RETURN(1); };);
13745 DBUG_RETURN(0);
13746 }
13747 #endif
13748
13749
13750 const char *Gtid_log_event::SET_STRING_PREFIX= "SET @@SESSION.GTID_NEXT= '";
13751
13752
Gtid_log_event(const char * buffer,uint event_len,const Format_description_event * description_event)13753 Gtid_log_event::Gtid_log_event(const char *buffer, uint event_len,
13754 const Format_description_event *description_event)
13755 : binary_log::Gtid_event(buffer, event_len, description_event),
13756 Log_event(header(), footer())
13757 {
13758 DBUG_ENTER("Gtid_log_event::Gtid_log_event(const char *,"
13759 " uint, const Format_description_log_event *");
13760
13761 #ifndef NDEBUG
13762 uint8_t const common_header_len= description_event->common_header_len;
13763 uint8 const post_header_len=
13764 buffer[EVENT_TYPE_OFFSET] == binary_log::ANONYMOUS_GTID_LOG_EVENT ?
13765 description_event->post_header_len[binary_log::ANONYMOUS_GTID_LOG_EVENT - 1] :
13766 description_event->post_header_len[binary_log::GTID_LOG_EVENT - 1];
13767 DBUG_PRINT("info",
13768 ("event_len: %u; common_header_len: %d; post_header_len: %d",
13769 event_len, common_header_len, post_header_len));
13770 #endif
13771
13772 is_valid_param= true;
13773 spec.type= get_type_code() == binary_log::ANONYMOUS_GTID_LOG_EVENT ?
13774 ANONYMOUS_GROUP : GTID_GROUP;
13775 sid.copy_from((uchar *)Uuid_parent_struct.bytes);
13776 spec.gtid.sidno= gtid_info_struct.rpl_gtid_sidno;
13777 //GNO sanity check
13778 if (spec.type == GTID_GROUP) {
13779 if (gtid_info_struct.rpl_gtid_gno <= 0 || gtid_info_struct.rpl_gtid_gno >= GNO_END)
13780 goto err;
13781 } else { //ANONYMOUS_GTID_LOG_EVENT
13782 if (gtid_info_struct.rpl_gtid_gno != 0)
13783 goto err;
13784 }
13785 spec.gtid.gno= gtid_info_struct.rpl_gtid_gno;
13786
13787 DBUG_VOID_RETURN;
13788
13789 err:
13790 is_valid_param= false;
13791 DBUG_VOID_RETURN;
13792 }
13793
13794 #ifndef MYSQL_CLIENT
Gtid_log_event(THD * thd_arg,bool using_trans,int64 last_committed_arg,int64 sequence_number_arg,bool may_have_sbr_stmts_arg)13795 Gtid_log_event::Gtid_log_event(THD* thd_arg, bool using_trans,
13796 int64 last_committed_arg,
13797 int64 sequence_number_arg,
13798 bool may_have_sbr_stmts_arg)
13799 : binary_log::Gtid_event(last_committed_arg, sequence_number_arg,
13800 may_have_sbr_stmts_arg),
13801 Log_event(thd_arg, thd_arg->variables.gtid_next.type == ANONYMOUS_GROUP ?
13802 LOG_EVENT_IGNORABLE_F : 0,
13803 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
13804 Log_event::EVENT_STMT_CACHE, Log_event::EVENT_NORMAL_LOGGING,
13805 header(), footer())
13806 {
13807 DBUG_ENTER("Gtid_log_event::Gtid_log_event(THD *)");
13808 if (thd->owned_gtid.sidno > 0)
13809 {
13810 spec.set(thd->owned_gtid);
13811 sid= thd->owned_sid;
13812 }
13813 else
13814 {
13815 assert(thd->owned_gtid.sidno == THD::OWNED_SIDNO_ANONYMOUS);
13816 spec.set_anonymous();
13817 spec.gtid.clear();
13818 sid.clear();
13819 }
13820
13821 Log_event_type event_type= (spec.type == ANONYMOUS_GROUP ?
13822 binary_log::ANONYMOUS_GTID_LOG_EVENT :
13823 binary_log::GTID_LOG_EVENT);
13824 common_header->type_code= event_type;
13825
13826 #ifndef NDEBUG
13827 char buf[MAX_SET_STRING_LENGTH + 1];
13828 to_string(buf);
13829 DBUG_PRINT("info", ("%s", buf));
13830 #endif
13831 is_valid_param= true;
13832 DBUG_VOID_RETURN;
13833 }
13834
Gtid_log_event(uint32 server_id_arg,bool using_trans,int64 last_committed_arg,int64 sequence_number_arg,bool may_have_sbr_stmts_arg,const Gtid_specification spec_arg)13835 Gtid_log_event::Gtid_log_event(uint32 server_id_arg, bool using_trans,
13836 int64 last_committed_arg,
13837 int64 sequence_number_arg,
13838 bool may_have_sbr_stmts_arg,
13839 const Gtid_specification spec_arg)
13840 : binary_log::Gtid_event(last_committed_arg, sequence_number_arg,
13841 may_have_sbr_stmts_arg),
13842 Log_event(header(), footer(),
13843 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
13844 Log_event::EVENT_STMT_CACHE, Log_event::EVENT_NORMAL_LOGGING)
13845 {
13846 DBUG_ENTER("Gtid_log_event::Gtid_log_event(uint32, bool, int64, int64, const Gtid_specification)");
13847 server_id= server_id_arg;
13848 common_header->unmasked_server_id= server_id_arg;
13849 is_valid_param= true;
13850
13851 if (spec_arg.type == GTID_GROUP)
13852 {
13853 assert(spec_arg.gtid.sidno > 0);
13854 assert(spec_arg.gtid.gno > 0);
13855 assert(spec_arg.gtid.gno < GNO_END);
13856 if (spec_arg.gtid.gno <= 0 || spec_arg.gtid.gno >= GNO_END)
13857 is_valid_param= false;
13858 spec.set(spec_arg.gtid);
13859 global_sid_lock->rdlock();
13860 sid= global_sid_map->sidno_to_sid(spec_arg.gtid.sidno);
13861 global_sid_lock->unlock();
13862 }
13863 else
13864 {
13865 assert(spec_arg.type == ANONYMOUS_GROUP);
13866 spec.set_anonymous();
13867 spec.gtid.clear();
13868 sid.clear();
13869 common_header->flags|= LOG_EVENT_IGNORABLE_F;
13870 }
13871
13872 Log_event_type event_type= (spec.type == ANONYMOUS_GROUP ?
13873 binary_log::ANONYMOUS_GTID_LOG_EVENT :
13874 binary_log::GTID_LOG_EVENT);
13875 common_header->type_code= event_type;
13876
13877 #ifndef NDEBUG
13878 char buf[MAX_SET_STRING_LENGTH + 1];
13879 to_string(buf);
13880 DBUG_PRINT("info", ("%s", buf));
13881 #endif
13882 DBUG_VOID_RETURN;
13883 }
13884 #endif
13885
13886 #ifndef MYSQL_CLIENT
pack_info(Protocol * protocol)13887 int Gtid_log_event::pack_info(Protocol *protocol)
13888 {
13889 char buffer[MAX_SET_STRING_LENGTH + 1];
13890 size_t len= to_string(buffer);
13891 protocol->store(buffer, len, &my_charset_bin);
13892 return 0;
13893 }
13894 #endif
13895
to_string(char * buf) const13896 size_t Gtid_log_event::to_string(char *buf) const
13897 {
13898 char *p= buf;
13899 assert(strlen(SET_STRING_PREFIX) == SET_STRING_PREFIX_LENGTH);
13900 strcpy(p, SET_STRING_PREFIX);
13901 p+= SET_STRING_PREFIX_LENGTH;
13902 p+= spec.to_string(&sid, p);
13903 *p++= '\'';
13904 *p= '\0';
13905 return p - buf;
13906 }
13907
13908 #ifdef MYSQL_CLIENT
13909 void
print(FILE * file,PRINT_EVENT_INFO * print_event_info)13910 Gtid_log_event::print(FILE *file, PRINT_EVENT_INFO *print_event_info)
13911 {
13912 char buffer[MAX_SET_STRING_LENGTH + 1];
13913 IO_CACHE *const head= &print_event_info->head_cache;
13914 if (!print_event_info->short_form)
13915 {
13916 print_header(head, print_event_info, FALSE);
13917 my_b_printf(head, "\t%s\tlast_committed=%llu\tsequence_number=%llu\t"
13918 "rbr_only=%s\n",
13919 get_type_code() == binary_log::GTID_LOG_EVENT ?
13920 "GTID" : "Anonymous_GTID",
13921 last_committed, sequence_number,
13922 may_have_sbr_stmts ? "no" : "yes");
13923 }
13924
13925 /*
13926 The applier thread can always use "READ COMMITTED" isolation for
13927 transactions containing only RBR events (Table_map + Rows).
13928
13929 This would prevent some deadlock issues because InnoDB doesn't
13930 acquire GAP locks in "READ COMMITTED" isolation level since
13931 MySQL 5.7.18.
13932 */
13933 if (!may_have_sbr_stmts)
13934 {
13935 my_b_printf(head,
13936 "/*!50718 SET TRANSACTION ISOLATION LEVEL "
13937 "READ COMMITTED*/%s\n",
13938 print_event_info->delimiter);
13939 }
13940
13941 to_string(buffer);
13942 my_b_printf(head, "%s%s\n", buffer, print_event_info->delimiter);
13943 }
13944 #endif
13945
13946 #ifdef MYSQL_SERVER
write_data_header_to_memory(uchar * buffer)13947 uint32 Gtid_log_event::write_data_header_to_memory(uchar *buffer)
13948 {
13949 DBUG_ENTER("Gtid_log_event::write_data_header_to_memory");
13950 uchar *ptr_buffer= buffer;
13951
13952 /* Encode the GTID flags */
13953 uchar gtid_flags= 0;
13954 gtid_flags|= may_have_sbr_stmts ?
13955 binary_log::Gtid_event::FLAG_MAY_HAVE_SBR : 0;
13956 *ptr_buffer= gtid_flags;
13957 ptr_buffer+= ENCODED_FLAG_LENGTH;
13958
13959 #ifndef NDEBUG
13960 char buf[binary_log::Uuid::TEXT_LENGTH + 1];
13961 sid.to_string(buf);
13962 DBUG_PRINT("info", ("sid=%s sidno=%d gno=%lld",
13963 buf, spec.gtid.sidno, spec.gtid.gno));
13964 #endif
13965
13966 sid.copy_to(ptr_buffer);
13967 ptr_buffer+= ENCODED_SID_LENGTH;
13968
13969 #ifndef NDEBUG
13970 if (DBUG_EVALUATE_IF("send_invalid_gno_to_replica", true, false))
13971 int8store(ptr_buffer, GNO_END);
13972 else
13973 #endif
13974 int8store(ptr_buffer, spec.gtid.gno);
13975 ptr_buffer+= ENCODED_GNO_LENGTH;
13976
13977 *ptr_buffer= LOGICAL_TIMESTAMP_TYPECODE;
13978 ptr_buffer+= LOGICAL_TIMESTAMP_TYPECODE_LENGTH;
13979
13980 assert((sequence_number == 0 && last_committed == 0) ||
13981 (sequence_number > last_committed));
13982 DBUG_EXECUTE_IF("set_commit_parent_100",
13983 { last_committed= max<int64>(sequence_number > 1 ? 1 : 0,
13984 sequence_number - 100); });
13985 DBUG_EXECUTE_IF("set_commit_parent_150",
13986 { last_committed= max<int64>(sequence_number > 1 ? 1 : 0,
13987 sequence_number - 150); });
13988 DBUG_EXECUTE_IF("feign_commit_parent", { last_committed= sequence_number; });
13989 int8store(ptr_buffer, last_committed);
13990 int8store(ptr_buffer + 8, sequence_number);
13991 ptr_buffer+= LOGICAL_TIMESTAMP_LENGTH;
13992
13993 assert(ptr_buffer == (buffer + POST_HEADER_LENGTH));
13994
13995 DBUG_RETURN(POST_HEADER_LENGTH);
13996 }
13997
write_data_header(IO_CACHE * file)13998 bool Gtid_log_event::write_data_header(IO_CACHE *file)
13999 {
14000 DBUG_ENTER("Gtid_log_event::write_data_header");
14001 uchar buffer[POST_HEADER_LENGTH];
14002 write_data_header_to_memory(buffer);
14003 DBUG_RETURN(wrapper_my_b_safe_write(file, (uchar *) buffer,
14004 POST_HEADER_LENGTH));
14005 }
14006
14007 #endif // MYSQL_SERVER
14008
14009 #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION)
do_apply_event(Relay_log_info const * rli)14010 int Gtid_log_event::do_apply_event(Relay_log_info const *rli)
14011 {
14012 DBUG_ENTER("Gtid_log_event::do_apply_event");
14013 assert(rli->info_thd == thd);
14014
14015 /*
14016 In rare cases it is possible that we already own a GTID (either
14017 ANONYMOUS or GTID_GROUP). This can happen if a transaction was truncated
14018 in the middle in the relay log and then next relay log begins with a
14019 Gtid_log_events without closing the transaction context from the previous
14020 relay log. In this case the only sensible thing to do is to discard the
14021 truncated transaction and move on.
14022
14023 Note that when the applier is "GTID skipping" a transactions it
14024 owns nothing, but its gtid_next->type == GTID_GROUP.
14025 */
14026 const Gtid_specification *gtid_next= &thd->variables.gtid_next;
14027 if (!thd->owned_gtid.is_empty() ||
14028 (thd->owned_gtid.is_empty() && gtid_next->type == GTID_GROUP))
14029 {
14030 /*
14031 Slave will execute this code if a previous Gtid_log_event was applied
14032 but the GTID wasn't consumed yet (the transaction was not committed,
14033 nor rolled back, nor skipped).
14034 On a client session we cannot do consecutive SET GTID_NEXT without
14035 a COMMIT or a ROLLBACK in the middle.
14036 Applying this event without rolling back the current transaction may
14037 lead to problems, as a "BEGIN" event following this GTID will
14038 implicitly commit the "partial transaction" and will consume the
14039 GTID. If this "partial transaction" was left in the relay log by the
14040 IO thread restarting in the middle of a transaction, you could have
14041 the partial transaction being logged with the GTID on the slave,
14042 causing data corruption on replication.
14043 */
14044 if (thd->server_status & SERVER_STATUS_IN_TRANS)
14045 {
14046 /* This is not an error (XA is safe), just an information */
14047 rli->report(INFORMATION_LEVEL, 0,
14048 "Rolling back unfinished transaction (no COMMIT "
14049 "or ROLLBACK in relay log). A probable cause is partial "
14050 "transaction left on relay log because of restarting IO "
14051 "thread with auto-positioning protocol.");
14052 const_cast<Relay_log_info*>(rli)->cleanup_context(thd, 1);
14053 }
14054 gtid_state->update_on_rollback(thd);
14055 }
14056
14057 global_sid_lock->rdlock();
14058
14059 // make sure that sid has been converted to sidno
14060 if (spec.type == GTID_GROUP)
14061 {
14062 if (get_sidno(false) < 0)
14063 {
14064 global_sid_lock->unlock();
14065 DBUG_RETURN(1); // out of memory
14066 }
14067 }
14068
14069 // set_gtid_next releases global_sid_lock
14070 if (set_gtid_next(thd, spec))
14071 // This can happen e.g. if gtid_mode is incompatible with spec.
14072 DBUG_RETURN(1);
14073
14074 thd->set_currently_executing_gtid_for_slave_thread();
14075
14076 /*
14077 If the current transaction contains no changes logged with SBR
14078 we can assume this transaction as a pure row based replicated one.
14079
14080 Based on this assumption, we can set current transaction tx_isolation to
14081 READ COMMITTED in order to avoid concurrent transactions to be blocked by
14082 InnoDB gap locks.
14083
14084 The session tx_isolation will be restored:
14085 - When the transaction finishes with QUERY(COMMIT|ROLLBACK),
14086 as the MySQL server does for ordinary user sessions;
14087 - When applying a Xid_log_event, after committing the transaction;
14088 - When applying a XA_prepare_log_event, after preparing the transaction;
14089 - When the applier needs to abort a transaction execution.
14090
14091 Notice that when a transaction is being "gtid skipped", its statements are
14092 not actually executed (see mysql_execute_command()). So, the call to the
14093 function that would restore the tx_isolation after finishing the transaction
14094 may not happen.
14095 */
14096 if (DBUG_EVALUATE_IF("force_trx_as_rbr_only", true,
14097 !may_have_sbr_stmts &&
14098 thd->tx_isolation > ISO_READ_COMMITTED &&
14099 gtid_pre_statement_checks(thd) != GTID_STATEMENT_SKIP))
14100 {
14101 assert(thd->get_transaction()->is_empty(Transaction_ctx::STMT));
14102 assert(thd->get_transaction()->is_empty(Transaction_ctx::SESSION));
14103 assert(!thd->lock);
14104 DBUG_PRINT("info", ("setting tx_isolation to READ COMMITTED"));
14105 set_tx_isolation(thd, ISO_READ_COMMITTED, true/*one_shot*/);
14106 }
14107
14108 DBUG_RETURN(0);
14109 }
14110
do_update_pos(Relay_log_info * rli)14111 int Gtid_log_event::do_update_pos(Relay_log_info *rli)
14112 {
14113 /*
14114 This event does not increment group positions. This means
14115 that if there is a failure after it has been processed,
14116 it will be automatically re-executed.
14117 */
14118 rli->inc_event_relay_log_pos();
14119 DBUG_EXECUTE_IF("crash_after_update_pos_gtid",
14120 sql_print_information("Crashing crash_after_update_pos_gtid.");
14121 DBUG_SUICIDE(););
14122 return 0;
14123 }
14124
do_shall_skip(Relay_log_info * rli)14125 Log_event::enum_skip_reason Gtid_log_event::do_shall_skip(Relay_log_info *rli)
14126 {
14127 return Log_event::continue_group(rli);
14128 }
14129 #endif
14130
14131 Previous_gtids_log_event::
Previous_gtids_log_event(const char * buf,uint event_len,const Format_description_event * description_event)14132 Previous_gtids_log_event(const char *buf, uint event_len,
14133 const Format_description_event *description_event)
14134 : binary_log::Previous_gtids_event(buf, event_len, description_event),
14135 Log_event(header(), footer())
14136 {
14137 DBUG_ENTER("Previous_gtids_log_event::Previous_gtids_log_event");
14138 if (buf != NULL)
14139 is_valid_param= true;
14140 DBUG_VOID_RETURN;
14141 }
14142
14143 #ifndef MYSQL_CLIENT
Previous_gtids_log_event(const Gtid_set * set)14144 Previous_gtids_log_event::Previous_gtids_log_event(const Gtid_set *set)
14145 : binary_log::Previous_gtids_event(),
14146 Log_event(header(), footer(),
14147 Log_event::EVENT_NO_CACHE,
14148 Log_event::EVENT_IMMEDIATE_LOGGING)
14149 {
14150 DBUG_ENTER("Previous_gtids_log_event::Previous_gtids_log_event(THD *, const Gtid_set *)");
14151 common_header->type_code= binary_log::PREVIOUS_GTIDS_LOG_EVENT;
14152 common_header->flags|= LOG_EVENT_IGNORABLE_F;
14153 global_sid_lock->assert_some_lock();
14154 buf_size= set->get_encoded_length();
14155 uchar *buffer= (uchar *) my_malloc(key_memory_log_event,
14156 buf_size, MYF(MY_WME));
14157 if (buffer != NULL)
14158 {
14159 set->encode(buffer);
14160 register_temp_buf((char *)buffer);
14161 }
14162 buf= buffer;
14163 // if buf is empty, is_valid will be false
14164 if(buf != 0)
14165 is_valid_param= true;
14166 DBUG_VOID_RETURN;
14167 }
14168 #endif
14169
14170 #ifndef MYSQL_CLIENT
pack_info(Protocol * protocol)14171 int Previous_gtids_log_event::pack_info(Protocol *protocol)
14172 {
14173 size_t length= 0;
14174 char *str= get_str(&length, &Gtid_set::default_string_format);
14175 if (str == NULL)
14176 return 1;
14177 protocol->store(str, length, &my_charset_bin);
14178 my_free(str);
14179 return 0;
14180 }
14181 #endif
14182
14183 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)14184 void Previous_gtids_log_event::print(FILE *file,
14185 PRINT_EVENT_INFO *print_event_info)
14186 {
14187 IO_CACHE *const head= &print_event_info->head_cache;
14188 char *str= get_str(NULL, &Gtid_set::commented_string_format);
14189 if (str != NULL)
14190 {
14191 if (!print_event_info->short_form)
14192 {
14193 print_header(head, print_event_info, FALSE);
14194 my_b_printf(head, "\tPrevious-GTIDs\n");
14195 }
14196 my_b_printf(head, "%s\n", str);
14197 my_free(str);
14198 }
14199 }
14200 #endif
14201
add_to_set(Gtid_set * target) const14202 int Previous_gtids_log_event::add_to_set(Gtid_set *target) const
14203 {
14204 DBUG_ENTER("Previous_gtids_log_event::add_to_set(Gtid_set *)");
14205 size_t end_pos= 0;
14206 size_t add_size= DBUG_EVALUATE_IF("gtid_has_extra_data", 10, 0);
14207 /* Silently ignore additional unknown data at the end of the encoding */
14208 PROPAGATE_REPORTED_ERROR_INT(target->add_gtid_encoding(buf,
14209 buf_size + add_size,
14210 &end_pos));
14211 assert(end_pos <= buf_size);
14212 DBUG_RETURN(0);
14213 }
14214
get_str(size_t * length_p,const Gtid_set::String_format * string_format) const14215 char *Previous_gtids_log_event::get_str(
14216 size_t *length_p, const Gtid_set::String_format *string_format) const
14217 {
14218 DBUG_ENTER("Previous_gtids_log_event::get_str(size_t *, const Gtid_set::String_format *)");
14219 Sid_map sid_map(NULL);
14220 Gtid_set set(&sid_map, NULL);
14221 DBUG_PRINT("info", ("temp_buf=%p buf=%p", temp_buf, buf));
14222 if (set.add_gtid_encoding(buf, buf_size) != RETURN_STATUS_OK)
14223 DBUG_RETURN(NULL);
14224 set.dbug_print("set");
14225 size_t length= set.get_string_length(string_format);
14226 DBUG_PRINT("info", ("string length= %lu", (ulong) length));
14227 char* str= (char *)my_malloc(key_memory_log_event,
14228 length + 1, MYF(MY_WME));
14229 if (str != NULL)
14230 {
14231 set.to_string(str, false/*need_lock*/, string_format);
14232 if (length_p != NULL)
14233 *length_p= length;
14234 }
14235 DBUG_RETURN(str);
14236 }
14237
14238 #ifndef MYSQL_CLIENT
write_data_body(IO_CACHE * file)14239 bool Previous_gtids_log_event::write_data_body(IO_CACHE *file)
14240 {
14241 DBUG_ENTER("Previous_gtids_log_event::write_data_body");
14242 DBUG_PRINT("info", ("size=%d", static_cast<int>(buf_size)));
14243 bool ret= wrapper_my_b_safe_write(file, buf, buf_size);
14244 DBUG_RETURN(ret);
14245 }
14246 #endif
14247
14248 #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION)
do_update_pos(Relay_log_info * rli)14249 int Previous_gtids_log_event::do_update_pos(Relay_log_info *rli)
14250 {
14251 rli->inc_event_relay_log_pos();
14252 return 0;
14253 }
14254 #endif
14255
14256
14257 /**************************************************************************
14258 Transaction_context_log_event methods
14259 **************************************************************************/
14260 #ifndef MYSQL_CLIENT
14261 Transaction_context_log_event::
Transaction_context_log_event(const char * server_uuid_arg,bool using_trans,my_thread_id thread_id_arg,bool is_gtid_specified_arg)14262 Transaction_context_log_event(const char *server_uuid_arg,
14263 bool using_trans,
14264 my_thread_id thread_id_arg,
14265 bool is_gtid_specified_arg)
14266 : binary_log::Transaction_context_event(thread_id_arg,
14267 is_gtid_specified_arg),
14268 Log_event(header(), footer(),
14269 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE :
14270 Log_event::EVENT_STMT_CACHE, Log_event::EVENT_NORMAL_LOGGING)
14271 {
14272 DBUG_ENTER("Transaction_context_log_event::Transaction_context_log_event(THD *, const char *, ulonglong)");
14273 common_header->flags|= LOG_EVENT_IGNORABLE_F;
14274 server_uuid= NULL;
14275 sid_map= new Sid_map(NULL);
14276 snapshot_version= new Gtid_set(sid_map);
14277
14278 /*
14279 Copy global_sid_map to a local copy to avoid the acquisition
14280 of the global_sid_lock for operations on top of this snapshot
14281 version.
14282 The Sid_map and Gtid_executed must be read under the protection
14283 of MYSQL_BIN_LOG.LOCK_commit to avoid race conditions between
14284 ordered commits in the storage engine and gtid_state update.
14285 */
14286 if (mysql_bin_log.get_gtid_executed(sid_map, snapshot_version))
14287 goto err;
14288
14289 server_uuid= my_strdup(key_memory_log_event, server_uuid_arg, MYF(MY_WME));
14290 if (server_uuid == NULL)
14291 goto err;
14292
14293 // These two fields are only populated on event decoding.
14294 // Encoding is done directly from snapshot_version field.
14295 encoded_snapshot_version= NULL;
14296 encoded_snapshot_version_length= 0;
14297
14298 // Debug sync point for SQL threads.
14299 DBUG_EXECUTE_IF("debug.wait_after_set_snapshot_version_on_transaction_context_log_event",
14300 {
14301 const char act[]=
14302 "now wait_for "
14303 "signal.resume_after_set_snapshot_version_on_transaction_context_log_event";
14304 assert(opt_debug_sync_timeout > 0);
14305 assert(!debug_sync_set_action(current_thd,
14306 STRING_WITH_LEN(act)));
14307 };);
14308
14309 is_valid_param= true;
14310 DBUG_VOID_RETURN;
14311
14312 err:
14313 is_valid_param= false;
14314 DBUG_VOID_RETURN;
14315 }
14316 #endif
14317
14318 Transaction_context_log_event::
Transaction_context_log_event(const char * buffer,uint event_len,const Format_description_event * descr_event)14319 Transaction_context_log_event(const char *buffer, uint event_len,
14320 const Format_description_event *descr_event)
14321 : binary_log::Transaction_context_event(buffer, event_len, descr_event),
14322 Log_event(header(), footer())
14323 {
14324 DBUG_ENTER("Transaction_context_log_event::Transaction_context_log_event (const char *, uint, const Format_description_event*)");
14325 common_header->flags|= LOG_EVENT_IGNORABLE_F;
14326
14327 sid_map= new Sid_map(NULL);
14328 snapshot_version= new Gtid_set(sid_map);
14329
14330 if (server_uuid == NULL || encoded_snapshot_version == NULL)
14331 goto err;
14332
14333 is_valid_param= true;
14334 DBUG_VOID_RETURN;
14335
14336 err:
14337 is_valid_param= false;
14338 DBUG_VOID_RETURN;
14339 }
14340
~Transaction_context_log_event()14341 Transaction_context_log_event::~Transaction_context_log_event()
14342 {
14343 DBUG_ENTER("Transaction_context_log_event::~Transaction_context_log_event");
14344 if (server_uuid)
14345 my_free((void*)server_uuid);
14346 server_uuid= NULL;
14347 if (encoded_snapshot_version)
14348 my_free((void*) encoded_snapshot_version);
14349 encoded_snapshot_version= NULL;
14350 delete snapshot_version;
14351 delete sid_map;
14352 DBUG_VOID_RETURN;
14353 }
14354
to_string(char * buf,ulong len) const14355 size_t Transaction_context_log_event::to_string(char *buf, ulong len) const
14356 {
14357 DBUG_ENTER("Transaction_context_log_event::to_string");
14358 DBUG_RETURN(my_snprintf(buf, len,
14359 "server_uuid=%s\tthread_id=%lu",
14360 server_uuid, thread_id));
14361 }
14362
14363 #ifndef MYSQL_CLIENT
pack_info(Protocol * protocol)14364 int Transaction_context_log_event::pack_info(Protocol *protocol)
14365 {
14366 DBUG_ENTER("Transaction_context_log_event::pack_info");
14367 char buf[256];
14368 size_t bytes= to_string(buf, 256);
14369 protocol->store(buf, bytes, &my_charset_bin);
14370 DBUG_RETURN(0);
14371 }
14372 #endif
14373
14374 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)14375 void Transaction_context_log_event::print(FILE *file,
14376 PRINT_EVENT_INFO *print_event_info)
14377 {
14378 DBUG_ENTER("Transaction_context_log_event::print");
14379 char buf[256];
14380 IO_CACHE *const head= &print_event_info->head_cache;
14381
14382 if (!print_event_info->short_form)
14383 {
14384 to_string(buf, 256);
14385 print_header(head, print_event_info, FALSE);
14386 my_b_printf(head, "Transaction_context: %s\n", buf);
14387 }
14388 DBUG_VOID_RETURN;
14389 }
14390 #endif
14391
14392 #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION)
do_update_pos(Relay_log_info * rli)14393 int Transaction_context_log_event::do_update_pos(Relay_log_info *rli)
14394 {
14395 DBUG_ENTER("Transaction_context_log_event::do_update_pos");
14396 rli->inc_event_relay_log_pos();
14397 DBUG_RETURN(0);
14398 }
14399 #endif
14400
get_data_size()14401 size_t Transaction_context_log_event::get_data_size()
14402 {
14403 DBUG_ENTER("Transaction_context_log_event::get_data_size");
14404
14405 size_t size= Binary_log_event::TRANSACTION_CONTEXT_HEADER_LEN;
14406 size += strlen(server_uuid);
14407 size += get_snapshot_version_size();
14408 size += get_data_set_size(&write_set);
14409 size += get_data_set_size(&read_set);
14410
14411 DBUG_RETURN(size);
14412 }
14413
14414 #ifndef MYSQL_CLIENT
write_data_header(IO_CACHE * file)14415 bool Transaction_context_log_event::write_data_header(IO_CACHE* file)
14416 {
14417 DBUG_ENTER("Transaction_context_log_event::write_data_header");
14418 char buf[Binary_log_event::TRANSACTION_CONTEXT_HEADER_LEN];
14419
14420 buf[ENCODED_SERVER_UUID_LEN_OFFSET] = (char) strlen(server_uuid);
14421 int4store(buf + ENCODED_THREAD_ID_OFFSET, thread_id);
14422 buf[ENCODED_GTID_SPECIFIED_OFFSET] = gtid_specified;
14423 int4store(buf + ENCODED_SNAPSHOT_VERSION_LEN_OFFSET, get_snapshot_version_size());
14424 int4store(buf + ENCODED_WRITE_SET_ITEMS_OFFSET, write_set.size());
14425 int4store(buf + ENCODED_READ_SET_ITEMS_OFFSET, read_set.size());
14426 DBUG_RETURN(wrapper_my_b_safe_write(file, (const uchar *) buf,
14427 Binary_log_event::TRANSACTION_CONTEXT_HEADER_LEN));
14428 }
14429
write_data_body(IO_CACHE * file)14430 bool Transaction_context_log_event::write_data_body(IO_CACHE* file)
14431 {
14432 DBUG_ENTER("Transaction_context_log_event::write_data_body");
14433
14434 if (wrapper_my_b_safe_write(file,
14435 (const uchar*) server_uuid,
14436 strlen(server_uuid)) ||
14437 write_snapshot_version(file) ||
14438 write_data_set(file, &write_set) ||
14439 write_data_set(file, &read_set))
14440 DBUG_RETURN(true);
14441
14442 DBUG_RETURN(false);
14443 }
14444
write_snapshot_version(IO_CACHE * file)14445 bool Transaction_context_log_event::write_snapshot_version(IO_CACHE* file)
14446 {
14447 DBUG_ENTER("Transaction_context_log_event::write_snapshot_version");
14448 bool result= false;
14449
14450 uint32 len= get_snapshot_version_size();
14451 uchar *buffer= (uchar *) my_malloc(key_memory_log_event,
14452 len, MYF(MY_WME));
14453 if (buffer == NULL)
14454 DBUG_RETURN(true);
14455
14456 snapshot_version->encode(buffer);
14457 if (wrapper_my_b_safe_write(file, buffer, len))
14458 result= true;
14459
14460 my_free(buffer);
14461 DBUG_RETURN(result);
14462 }
14463
write_data_set(IO_CACHE * file,std::list<const char * > * set)14464 bool Transaction_context_log_event::write_data_set(IO_CACHE* file,
14465 std::list<const char*> *set)
14466 {
14467 DBUG_ENTER("Transaction_context_log_event::write_data_set");
14468 for (std::list<const char*>::iterator it=set->begin();
14469 it != set->end();
14470 ++it)
14471 {
14472 char buf[ENCODED_READ_WRITE_SET_ITEM_LEN];
14473 const char* hash= *it;
14474 uint16 len= strlen(hash);
14475
14476 int2store(buf, len);
14477 if (wrapper_my_b_safe_write(file,
14478 (const uchar*) buf,
14479 ENCODED_READ_WRITE_SET_ITEM_LEN) ||
14480 wrapper_my_b_safe_write(file, (const uchar*) hash, len))
14481 DBUG_RETURN(true);
14482 }
14483
14484 DBUG_RETURN(false);
14485 }
14486 #endif
14487
read_snapshot_version()14488 bool Transaction_context_log_event::read_snapshot_version()
14489 {
14490 DBUG_ENTER("Transaction_context_log_event::read_snapshot_version");
14491 assert(snapshot_version->is_empty());
14492
14493 global_sid_lock->wrlock();
14494 enum_return_status return_status= global_sid_map->copy(sid_map);
14495 global_sid_lock->unlock();
14496 if (return_status != RETURN_STATUS_OK)
14497 DBUG_RETURN(true);
14498
14499 DBUG_RETURN(snapshot_version->add_gtid_encoding(encoded_snapshot_version,
14500 encoded_snapshot_version_length)
14501 != RETURN_STATUS_OK);
14502 }
14503
get_snapshot_version_size()14504 size_t Transaction_context_log_event::get_snapshot_version_size()
14505 {
14506 DBUG_ENTER("Transaction_context_log_event::get_snapshot_version_size");
14507 size_t result= snapshot_version->get_encoded_length();
14508 DBUG_RETURN(result);
14509 }
14510
get_data_set_size(std::list<const char * > * set)14511 int Transaction_context_log_event::get_data_set_size(std::list<const char*> *set)
14512 {
14513 DBUG_ENTER("Transaction_context_log_event::get_data_set_size");
14514 int size= 0;
14515
14516 for (std::list<const char*>::iterator it=set->begin();
14517 it != set->end();
14518 ++it)
14519 size += ENCODED_READ_WRITE_SET_ITEM_LEN + strlen(*it);
14520
14521 DBUG_RETURN(size);
14522 }
14523
add_write_set(const char * hash)14524 void Transaction_context_log_event::add_write_set(const char *hash)
14525 {
14526 DBUG_ENTER("Transaction_context_log_event::add_write_set");
14527 write_set.push_back(hash);
14528 DBUG_VOID_RETURN;
14529 }
14530
add_read_set(const char * hash)14531 void Transaction_context_log_event::add_read_set(const char *hash)
14532 {
14533 DBUG_ENTER("Transaction_context_log_event::add_read_set");
14534 read_set.push_back(hash);
14535 DBUG_VOID_RETURN;
14536 }
14537
14538 /**************************************************************************
14539 View_change_log_event methods
14540 **************************************************************************/
14541
14542 #ifndef MYSQL_CLIENT
View_change_log_event(char * raw_view_id)14543 View_change_log_event::View_change_log_event(char* raw_view_id)
14544 : binary_log::View_change_event(raw_view_id),
14545 Log_event(header(), footer(), Log_event::EVENT_TRANSACTIONAL_CACHE,
14546 Log_event::EVENT_NORMAL_LOGGING)
14547 {
14548 DBUG_ENTER("View_change_log_event::View_change_log_event(char*)");
14549 common_header->flags|= LOG_EVENT_IGNORABLE_F;
14550
14551 if (strlen(view_id) != 0)
14552 is_valid_param= true;
14553
14554 DBUG_VOID_RETURN;
14555 }
14556 #endif
14557
14558 View_change_log_event::
View_change_log_event(const char * buffer,uint event_len,const Format_description_event * descr_event)14559 View_change_log_event(const char *buffer,
14560 uint event_len,
14561 const Format_description_event *descr_event)
14562 : binary_log::View_change_event(buffer, event_len, descr_event),
14563 Log_event(header(), footer())
14564 {
14565 DBUG_ENTER("View_change_log_event::View_change_log_event(const char *,"
14566 " uint, const Format_description_event*)");
14567 common_header->flags|= LOG_EVENT_IGNORABLE_F;
14568
14569 if (strlen(view_id) != 0)
14570 is_valid_param= true;
14571
14572 //Change the cache/logging types to allow writing to the binary log cache
14573 event_cache_type= EVENT_TRANSACTIONAL_CACHE;
14574 event_logging_type= EVENT_NORMAL_LOGGING;
14575
14576 DBUG_VOID_RETURN;
14577 }
14578
~View_change_log_event()14579 View_change_log_event::~View_change_log_event()
14580 {
14581 DBUG_ENTER("View_change_log_event::~View_change_log_event");
14582 certification_info.clear();
14583 DBUG_VOID_RETURN;
14584 }
14585
get_data_size()14586 size_t View_change_log_event::get_data_size()
14587 {
14588 DBUG_ENTER("View_change_log_event::get_data_size");
14589
14590 size_t size= Binary_log_event::VIEW_CHANGE_HEADER_LEN;
14591 size+= get_size_data_map(&certification_info);
14592
14593 DBUG_RETURN(size);
14594 }
14595
14596 size_t
get_size_data_map(std::map<std::string,std::string> * map)14597 View_change_log_event::get_size_data_map(std::map<std::string, std::string> *map)
14598 {
14599 DBUG_ENTER("View_change_log_event::get_size_data_map");
14600 size_t size= 0;
14601
14602 std::map<std::string, std::string>::iterator iter;
14603 size+= (ENCODED_CERT_INFO_KEY_SIZE_LEN +
14604 ENCODED_CERT_INFO_VALUE_LEN) * map->size();
14605 for (iter= map->begin(); iter!= map->end(); iter++)
14606 size+= iter->first.length() + iter->second.length();
14607
14608 DBUG_RETURN(size);
14609 }
14610
to_string(char * buf,ulong len) const14611 size_t View_change_log_event::to_string(char *buf, ulong len) const
14612 {
14613 DBUG_ENTER("View_change_log_event::to_string");
14614 DBUG_RETURN(my_snprintf(buf, len, "view_id=%s", view_id));
14615 }
14616
14617 #ifndef MYSQL_CLIENT
pack_info(Protocol * protocol)14618 int View_change_log_event::pack_info(Protocol *protocol)
14619 {
14620 DBUG_ENTER("View_change_log_event::pack_info");
14621 char buf[256];
14622 size_t bytes= to_string(buf, 256);
14623 protocol->store(buf, bytes, &my_charset_bin);
14624 DBUG_RETURN(0);
14625 }
14626 #endif
14627
14628 #ifdef MYSQL_CLIENT
print(FILE * file,PRINT_EVENT_INFO * print_event_info)14629 void View_change_log_event::print(FILE *file,
14630 PRINT_EVENT_INFO *print_event_info)
14631 {
14632 DBUG_ENTER("View_change_log_event::print");
14633 char buf[256];
14634 IO_CACHE *const head= &print_event_info->head_cache;
14635
14636 if (!print_event_info->short_form)
14637 {
14638 to_string(buf, 256);
14639 print_header(head, print_event_info, FALSE);
14640 my_b_printf(head, "View_change_log_event: %s\n", buf);
14641 }
14642 DBUG_VOID_RETURN;
14643 }
14644 #endif
14645
14646 #if defined(MYSQL_SERVER) && defined(HAVE_REPLICATION)
14647
do_apply_event(Relay_log_info const * rli)14648 int View_change_log_event::do_apply_event(Relay_log_info const *rli)
14649 {
14650 enum_gtid_statement_status state= gtid_pre_statement_checks(thd);
14651 if (state == GTID_STATEMENT_SKIP)
14652 return 0;
14653
14654 if (state == GTID_STATEMENT_CANCEL ||
14655 (state == GTID_STATEMENT_EXECUTE &&
14656 gtid_pre_statement_post_implicit_commit_checks(thd)))
14657 {
14658 uint error= thd->get_stmt_da()->mysql_errno();
14659 assert(error != 0);
14660 rli->report(ERROR_LEVEL, error,
14661 "Error executing View Change event: '%s'",
14662 thd->get_stmt_da()->message_text());
14663 thd->is_slave_error= 1;
14664 return -1;
14665 }
14666
14667 if (!opt_bin_log)
14668 {
14669 return 0;
14670 }
14671
14672 int error= mysql_bin_log.write_event(this);
14673 if (error)
14674 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR, ER(ER_SLAVE_FATAL_ERROR),
14675 "Could not write the VIEW CHANGE event in the binary log.");
14676
14677 return (error);
14678 }
14679
do_update_pos(Relay_log_info * rli)14680 int View_change_log_event::do_update_pos(Relay_log_info *rli)
14681 {
14682 DBUG_ENTER("View_change_log_event::do_update_pos");
14683 rli->inc_event_relay_log_pos();
14684 DBUG_RETURN(0);
14685 }
14686 #endif
14687
14688 #ifndef MYSQL_CLIENT
write_data_header(IO_CACHE * file)14689 bool View_change_log_event::write_data_header(IO_CACHE* file){
14690 DBUG_ENTER("View_change_log_event::write_data_header");
14691 char buf[Binary_log_event::VIEW_CHANGE_HEADER_LEN];
14692
14693 memcpy(buf, view_id, ENCODED_VIEW_ID_MAX_LEN);
14694 int8store(buf + ENCODED_SEQ_NUMBER_OFFSET, seq_number);
14695 int4store(buf + ENCODED_CERT_INFO_SIZE_OFFSET, certification_info.size());
14696 DBUG_RETURN(wrapper_my_b_safe_write(file,(const uchar *) buf,
14697 Binary_log_event::VIEW_CHANGE_HEADER_LEN));
14698 }
14699
write_data_body(IO_CACHE * file)14700 bool View_change_log_event::write_data_body(IO_CACHE* file){
14701 DBUG_ENTER("Transaction_context_log_event::write_data_body");
14702
14703 if (write_data_map(file, &certification_info))
14704 DBUG_RETURN(true);
14705
14706 DBUG_RETURN(false);
14707 }
14708
write_data_map(IO_CACHE * file,std::map<std::string,std::string> * map)14709 bool View_change_log_event::write_data_map(IO_CACHE* file,
14710 std::map<std::string, std::string> *map)
14711 {
14712 DBUG_ENTER("View_change_log_event::write_data_set");
14713 bool result= false;
14714
14715 std::map<std::string, std::string>::iterator iter;
14716 for (iter= map->begin(); iter!= map->end(); iter++)
14717 {
14718 uchar buf_key_len[ENCODED_CERT_INFO_KEY_SIZE_LEN];
14719 uint16 key_len= iter->first.length();
14720 int2store(buf_key_len, key_len);
14721
14722 const char *key= iter->first.c_str();
14723
14724 uchar buf_value_len[ENCODED_CERT_INFO_VALUE_LEN];
14725 uint32 value_len= iter->second.length();
14726 int4store(buf_value_len, value_len);
14727
14728 const char *value= iter->second.c_str();
14729
14730 if (wrapper_my_b_safe_write(file, buf_key_len,
14731 ENCODED_CERT_INFO_KEY_SIZE_LEN) ||
14732 wrapper_my_b_safe_write(file, (const uchar*) key, key_len) ||
14733 wrapper_my_b_safe_write(file, buf_value_len,
14734 ENCODED_CERT_INFO_VALUE_LEN) ||
14735 wrapper_my_b_safe_write(file, (const uchar*) value, value_len))
14736 DBUG_RETURN(result);
14737 }
14738
14739 DBUG_RETURN(false);
14740 }
14741
14742 #endif
14743
14744 /*
14745 Updates the certification info map.
14746 */
set_certification_info(std::map<std::string,std::string> * info,size_t * event_size)14747 void View_change_log_event::set_certification_info(
14748 std::map<std::string, std::string> *info, size_t *event_size) {
14749 DBUG_ENTER("View_change_log_event::set_certification_database_snapshot");
14750 certification_info.clear();
14751
14752 *event_size = Binary_log_event::VIEW_CHANGE_HEADER_LEN;
14753 std::map<std::string, std::string>::iterator it;
14754 for(it= info->begin(); it != info->end(); ++it)
14755 {
14756 std::string key= it->first;
14757 std::string value= it->second;
14758 certification_info[key]= value;
14759 *event_size += it->first.length() + it->second.length();
14760 }
14761 *event_size +=
14762 (ENCODED_CERT_INFO_KEY_SIZE_LEN + ENCODED_CERT_INFO_VALUE_LEN) *
14763 certification_info.size();
14764
14765 DBUG_VOID_RETURN;
14766 }
14767
14768
14769 #ifdef MYSQL_CLIENT
14770 /**
14771 The default values for these variables should be values that are
14772 *incorrect*, i.e., values that cannot occur in an event. This way,
14773 they will always be printed for the first event.
14774 */
st_print_event_info()14775 st_print_event_info::st_print_event_info()
14776 :flags2_inited(0), sql_mode_inited(0), sql_mode(0),
14777 auto_increment_increment(0),auto_increment_offset(0), charset_inited(0),
14778 lc_time_names_number(~0),
14779 charset_database_number(ILLEGAL_CHARSET_INFO_NUMBER),
14780 thread_id(0), thread_id_printed(false),
14781 base64_output_mode(BASE64_OUTPUT_UNSPEC), printed_fd_event(FALSE),
14782 have_unflushed_events(false), skipped_event_in_transaction(false)
14783 {
14784 /*
14785 Currently we only use static PRINT_EVENT_INFO objects, so zeroed at
14786 program's startup, but these explicit memset() is for the day someone
14787 creates dynamic instances.
14788 */
14789 memset(db, 0, sizeof(db));
14790 memset(charset, 0, sizeof(charset));
14791 memset(time_zone_str, 0, sizeof(time_zone_str));
14792 delimiter[0]= ';';
14793 delimiter[1]= 0;
14794 myf const flags = MYF(MY_WME | MY_NABP);
14795 open_cached_file(&head_cache, NULL, NULL, 0, flags);
14796 open_cached_file(&body_cache, NULL, NULL, 0, flags);
14797 open_cached_file(&footer_cache, NULL, NULL, 0, flags);
14798 }
14799 #endif
14800
14801
14802 #if defined(HAVE_REPLICATION) && !defined(MYSQL_CLIENT)
Heartbeat_log_event(const char * buf,uint event_len,const Format_description_event * description_event)14803 Heartbeat_log_event::Heartbeat_log_event(const char* buf, uint event_len,
14804 const Format_description_event*
14805 description_event)
14806 : binary_log::Heartbeat_event(buf, event_len, description_event),
14807 Log_event(header(), footer())
14808 {
14809 if ((log_ident != NULL && header()->log_pos >= BIN_LOG_HEADER_SIZE))
14810 is_valid_param= true;
14811 }
14812 #endif
14813
14814 #ifdef MYSQL_SERVER
14815 /*
14816 This is a utility function that adds a quoted identifier into the a buffer.
14817 This also escapes any existance of the quote string inside the identifier.
14818
14819 SYNOPSIS
14820 my_strmov_quoted_identifier
14821 thd thread handler
14822 buffer target buffer
14823 identifier the identifier to be quoted
14824 length length of the identifier
14825 */
my_strmov_quoted_identifier(THD * thd,char * buffer,const char * identifier,size_t length)14826 size_t my_strmov_quoted_identifier(THD* thd, char *buffer,
14827 const char* identifier,
14828 size_t length)
14829 {
14830 int q= thd ? get_quote_char_for_identifier(thd, identifier, length) : '`';
14831 return my_strmov_quoted_identifier_helper(q, buffer, identifier, length);
14832 }
14833 #else
my_strmov_quoted_identifier(char * buffer,const char * identifier)14834 size_t my_strmov_quoted_identifier(char *buffer, const char* identifier)
14835 {
14836 int q= '`';
14837 return my_strmov_quoted_identifier_helper(q, buffer, identifier, 0);
14838 }
14839
14840 #endif
14841
my_strmov_quoted_identifier_helper(int q,char * buffer,const char * identifier,size_t length)14842 size_t my_strmov_quoted_identifier_helper(int q, char *buffer,
14843 const char* identifier,
14844 size_t length)
14845 {
14846 size_t written= 0;
14847 char quote_char;
14848 size_t id_length= (length) ? length : strlen(identifier);
14849
14850 if (q == EOF)
14851 {
14852 (void) strncpy(buffer, identifier, id_length);
14853 return id_length;
14854 }
14855 quote_char= (char) q;
14856 *buffer++= quote_char;
14857 written++;
14858 while (id_length--)
14859 {
14860 if (*identifier == quote_char)
14861 {
14862 *buffer++= quote_char;
14863 written++;
14864 }
14865 *buffer++= *identifier++;
14866 written++;
14867 }
14868 *buffer++= quote_char;
14869 return ++written;
14870 }
14871
14872