1 /*
2 Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.
3
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License, version 2.0,
6 as published by the Free Software Foundation.
7
8 This program is also distributed with certain software (including
9 but not limited to OpenSSL) that is licensed under separate terms,
10 as designated in a particular file or component or in included license
11 documentation. The authors of MySQL hereby grant you an additional
12 permission to link the program and your derivative works with the
13 separately licensed software that they have included with MySQL.
14
15 This program is distributed in the hope that it will be useful,
16 but WITHOUT ANY WARRANTY; without even the implied warranty of
17 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 GNU General Public License, version 2.0, for more details.
19
20 You should have received a copy of the GNU General Public License
21 along with this program; if not, write to the Free Software
22 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
23
24 #define LOG_SUBSYSTEM_TAG "Repl"
25
26 #include "sql/log_event.h"
27
28 #include "my_config.h"
29
30 #include <assert.h>
31 #include <stdio.h>
32 #include <stdlib.h>
33 #ifdef HAVE_SYS_TIME_H
34 #include <sys/time.h>
35 #endif
36 #include <algorithm>
37 #include <map>
38 #include <memory>
39 #include <string>
40 #include <utility>
41
42 #include "base64.h"
43 #include "decimal.h"
44 #include "libbinlogevents/export/binary_log_funcs.h" // my_timestamp_binary_length
45 #include "libbinlogevents/include/debug_vars.h"
46 #include "libbinlogevents/include/table_id.h"
47 #include "libbinlogevents/include/wrapper_functions.h"
48 #include "m_ctype.h"
49 #include "my_bitmap.h"
50 #include "my_byteorder.h"
51 #include "my_compiler.h"
52 #include "my_dbug.h"
53 #include "my_io.h"
54 #include "my_loglevel.h"
55 #include "my_macros.h"
56 #include "my_systime.h"
57 #include "my_table_map.h"
58 #include "my_time.h" // MAX_DATE_STRING_REP_LENGTH
59 #include "mysql.h" // MYSQL_OPT_MAX_ALLOWED_PACKET
60 #include "mysql/components/services/log_builtins.h"
61 #include "mysql/components/services/log_shared.h"
62 #include "mysql/components/services/psi_statement_bits.h"
63 #include "mysql/psi/mysql_mutex.h"
64 #include "mysql/udf_registration_types.h"
65 #include "mysql_time.h"
66 #include "psi_memory_key.h"
67 #include "query_options.h"
68 #include "sql/auth/auth_acls.h"
69 #include "sql/binlog_reader.h"
70 #include "sql/my_decimal.h" // my_decimal
71 #include "sql/rpl_handler.h" // RUN_HOOK
72 #include "sql/rpl_tblmap.h"
73 #include "sql/system_variables.h"
74 #include "sql/tc_log.h"
75 #include "sql_const.h"
76 #include "sql_string.h"
77 #include "template_utils.h"
78
79 #ifndef MYSQL_SERVER
80 #include "client/mysqlbinlog.h"
81 #include "sql/json_binary.h"
82 #include "sql/json_diff.h" // enum_json_diff_operation
83 #include "sql/json_dom.h" // Json_wrapper
84 #endif
85
86 #ifdef MYSQL_SERVER
87
88 #include <errno.h>
89 #include <fcntl.h>
90 #include <cstdint>
91 #include <new>
92
93 #include "libbinlogevents/include/binary_log.h" // binary_log
94 #include "my_base.h"
95 #include "my_command.h"
96 #include "my_dir.h" // my_dir
97 #include "my_sqlcommand.h"
98 #include "mysql/plugin.h"
99 #include "mysql/psi/mysql_cond.h"
100 #include "mysql/psi/mysql_file.h"
101 #include "mysql/psi/mysql_stage.h"
102 #include "mysql/psi/mysql_statement.h"
103 #include "mysql/psi/mysql_transaction.h"
104 #include "mysql/psi/psi_statement.h"
105 #include "mysqld_error.h"
106 #include "prealloced_array.h"
107 #include "sql/auth/auth_common.h"
108 #include "sql/auth/sql_security_ctx.h"
109 #include "sql/basic_ostream.h"
110 #include "sql/binlog.h"
111 #include "sql/current_thd.h"
112 #include "sql/dd/types/abstract_table.h" // dd::enum_table_type
113 #include "sql/debug_sync.h" // debug_sync_set_action
114 #include "sql/derror.h" // ER_THD
115 #include "sql/enum_query_type.h"
116 #include "sql/field.h"
117 #include "sql/handler.h"
118 #include "sql/item.h"
119 #include "sql/item_func.h" // Item_func_set_user_var
120 #include "sql/key.h"
121 #include "sql/log.h" // Log_throttle
122 #include "sql/mdl.h"
123 #include "sql/mysqld.h" // lower_case_table_names server_uuid ...
124 #include "sql/protocol.h"
125 #include "sql/rpl_msr.h" // channel_map
126 #include "sql/rpl_mts_submode.h" // Mts_submode
127 #include "sql/rpl_reporting.h"
128 #include "sql/rpl_rli.h" // Relay_log_info
129 #include "sql/rpl_rli_pdb.h" // Slave_job_group
130 #include "sql/rpl_slave.h" // use_slave_mask
131 #include "sql/sp_head.h" // sp_name
132 #include "sql/sql_base.h" // close_thread_tables
133 #include "sql/sql_bitmap.h"
134 #include "sql/sql_class.h"
135 #include "sql/sql_cmd.h"
136 #include "sql/sql_data_change.h"
137 #include "sql/sql_db.h" // load_db_opt_by_name
138 #include "sql/sql_digest_stream.h"
139 #include "sql/sql_error.h"
140 #include "sql/sql_exchange.h" // sql_exchange
141 #include "sql/sql_lex.h"
142 #include "sql/sql_list.h" // I_List
143 #include "sql/sql_load.h" // Sql_cmd_load_table
144 #include "sql/sql_locale.h" // my_locale_by_number
145 #include "sql/sql_parse.h" // mysql_test_parse_for_slave
146 #include "sql/sql_plugin.h" // plugin_foreach
147 #include "sql/sql_show.h" // append_identifier
148 #include "sql/sql_tablespace.h" // Sql_cmd_tablespace
149 #include "sql/table.h"
150 #include "sql/transaction.h" // trans_rollback_stmt
151 #include "sql/transaction_info.h"
152 #include "sql/tztime.h" // Time_zone
153 #include "thr_lock.h"
154 #define window_size Log_throttle::LOG_THROTTLE_WINDOW_SIZE
155 Error_log_throttle slave_ignored_err_throttle(
156 window_size, INFORMATION_LEVEL, ER_SERVER_SLAVE_IGNORED_TABLE, "Repl",
157 "Error log throttle: %lu time(s) Error_code: 1237"
158 " \"Slave SQL thread ignored the query because of"
159 " replicate-*-table rules\" got suppressed.");
160 #endif /* MYSQL_SERVER */
161
162 #include "libbinlogevents/include/codecs/binary.h"
163 #include "libbinlogevents/include/codecs/factory.h"
164 #include "libbinlogevents/include/compression/iterator.h"
165 #include "sql/rpl_gtid.h"
166 #include "sql/rpl_record.h" // enum_row_image_type, Bit_reader
167 #include "sql/rpl_utility.h"
168 #include "sql/xa_aux.h"
169
170 struct mysql_mutex_t;
171
172 PSI_memory_key key_memory_log_event;
173 PSI_memory_key key_memory_Incident_log_event_message;
174 PSI_memory_key key_memory_Rows_query_log_event_rows_query;
175
176 using std::max;
177 using std::min;
178
179 /**
180 BINLOG_CHECKSUM variable.
181 */
182 const char *binlog_checksum_type_names[] = {"NONE", "CRC32", NullS};
183
184 unsigned int binlog_checksum_type_length[] = {sizeof("NONE") - 1,
185 sizeof("CRC32") - 1, 0};
186
187 TYPELIB binlog_checksum_typelib = {
188 array_elements(binlog_checksum_type_names) - 1, "",
189 binlog_checksum_type_names, binlog_checksum_type_length};
190
191 #define log_cs &my_charset_latin1
192
193 /*
194 Size of buffer for printing a double in format %.<PREC>g
195
196 optional '-' + optional zero + '.' + PREC digits + 'e' + sign +
197 exponent digits + '\0'
198 */
199 #define FMT_G_BUFSIZE(PREC) (3 + (PREC) + 5 + 1)
200
201 #if defined(MYSQL_SERVER)
202 static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD *thd);
203
HA_ERR(int i)204 static const char *HA_ERR(int i) {
205 /*
206 This function should only be called in case of an error
207 was detected
208 */
209 DBUG_ASSERT(i != 0);
210 switch (i) {
211 case HA_ERR_KEY_NOT_FOUND:
212 return "HA_ERR_KEY_NOT_FOUND";
213 case HA_ERR_FOUND_DUPP_KEY:
214 return "HA_ERR_FOUND_DUPP_KEY";
215 case HA_ERR_RECORD_CHANGED:
216 return "HA_ERR_RECORD_CHANGED";
217 case HA_ERR_WRONG_INDEX:
218 return "HA_ERR_WRONG_INDEX";
219 case HA_ERR_CRASHED:
220 return "HA_ERR_CRASHED";
221 case HA_ERR_WRONG_IN_RECORD:
222 return "HA_ERR_WRONG_IN_RECORD";
223 case HA_ERR_OUT_OF_MEM:
224 return "HA_ERR_OUT_OF_MEM";
225 case HA_ERR_NOT_A_TABLE:
226 return "HA_ERR_NOT_A_TABLE";
227 case HA_ERR_WRONG_COMMAND:
228 return "HA_ERR_WRONG_COMMAND";
229 case HA_ERR_OLD_FILE:
230 return "HA_ERR_OLD_FILE";
231 case HA_ERR_NO_ACTIVE_RECORD:
232 return "HA_ERR_NO_ACTIVE_RECORD";
233 case HA_ERR_RECORD_DELETED:
234 return "HA_ERR_RECORD_DELETED";
235 case HA_ERR_RECORD_FILE_FULL:
236 return "HA_ERR_RECORD_FILE_FULL";
237 case HA_ERR_INDEX_FILE_FULL:
238 return "HA_ERR_INDEX_FILE_FULL";
239 case HA_ERR_END_OF_FILE:
240 return "HA_ERR_END_OF_FILE";
241 case HA_ERR_UNSUPPORTED:
242 return "HA_ERR_UNSUPPORTED";
243 case HA_ERR_TOO_BIG_ROW:
244 return "HA_ERR_TOO_BIG_ROW";
245 case HA_WRONG_CREATE_OPTION:
246 return "HA_WRONG_CREATE_OPTION";
247 case HA_ERR_FOUND_DUPP_UNIQUE:
248 return "HA_ERR_FOUND_DUPP_UNIQUE";
249 case HA_ERR_UNKNOWN_CHARSET:
250 return "HA_ERR_UNKNOWN_CHARSET";
251 case HA_ERR_WRONG_MRG_TABLE_DEF:
252 return "HA_ERR_WRONG_MRG_TABLE_DEF";
253 case HA_ERR_CRASHED_ON_REPAIR:
254 return "HA_ERR_CRASHED_ON_REPAIR";
255 case HA_ERR_CRASHED_ON_USAGE:
256 return "HA_ERR_CRASHED_ON_USAGE";
257 case HA_ERR_LOCK_WAIT_TIMEOUT:
258 return "HA_ERR_LOCK_WAIT_TIMEOUT";
259 case HA_ERR_LOCK_TABLE_FULL:
260 return "HA_ERR_LOCK_TABLE_FULL";
261 case HA_ERR_READ_ONLY_TRANSACTION:
262 return "HA_ERR_READ_ONLY_TRANSACTION";
263 case HA_ERR_LOCK_DEADLOCK:
264 return "HA_ERR_LOCK_DEADLOCK";
265 case HA_ERR_CANNOT_ADD_FOREIGN:
266 return "HA_ERR_CANNOT_ADD_FOREIGN";
267 case HA_ERR_NO_REFERENCED_ROW:
268 return "HA_ERR_NO_REFERENCED_ROW";
269 case HA_ERR_ROW_IS_REFERENCED:
270 return "HA_ERR_ROW_IS_REFERENCED";
271 case HA_ERR_NO_SAVEPOINT:
272 return "HA_ERR_NO_SAVEPOINT";
273 case HA_ERR_NON_UNIQUE_BLOCK_SIZE:
274 return "HA_ERR_NON_UNIQUE_BLOCK_SIZE";
275 case HA_ERR_NO_SUCH_TABLE:
276 return "HA_ERR_NO_SUCH_TABLE";
277 case HA_ERR_TABLE_EXIST:
278 return "HA_ERR_TABLE_EXIST";
279 case HA_ERR_NO_CONNECTION:
280 return "HA_ERR_NO_CONNECTION";
281 case HA_ERR_NULL_IN_SPATIAL:
282 return "HA_ERR_NULL_IN_SPATIAL";
283 case HA_ERR_TABLE_DEF_CHANGED:
284 return "HA_ERR_TABLE_DEF_CHANGED";
285 case HA_ERR_NO_PARTITION_FOUND:
286 return "HA_ERR_NO_PARTITION_FOUND";
287 case HA_ERR_RBR_LOGGING_FAILED:
288 return "HA_ERR_RBR_LOGGING_FAILED";
289 case HA_ERR_DROP_INDEX_FK:
290 return "HA_ERR_DROP_INDEX_FK";
291 case HA_ERR_FOREIGN_DUPLICATE_KEY:
292 return "HA_ERR_FOREIGN_DUPLICATE_KEY";
293 case HA_ERR_TABLE_NEEDS_UPGRADE:
294 return "HA_ERR_TABLE_NEEDS_UPGRADE";
295 case HA_ERR_TABLE_READONLY:
296 return "HA_ERR_TABLE_READONLY";
297 case HA_ERR_AUTOINC_READ_FAILED:
298 return "HA_ERR_AUTOINC_READ_FAILED";
299 case HA_ERR_AUTOINC_ERANGE:
300 return "HA_ERR_AUTOINC_ERANGE";
301 case HA_ERR_GENERIC:
302 return "HA_ERR_GENERIC";
303 case HA_ERR_RECORD_IS_THE_SAME:
304 return "HA_ERR_RECORD_IS_THE_SAME";
305 case HA_ERR_LOGGING_IMPOSSIBLE:
306 return "HA_ERR_LOGGING_IMPOSSIBLE";
307 case HA_ERR_CORRUPT_EVENT:
308 return "HA_ERR_CORRUPT_EVENT";
309 case HA_ERR_ROWS_EVENT_APPLY:
310 return "HA_ERR_ROWS_EVENT_APPLY";
311 case HA_ERR_FK_DEPTH_EXCEEDED:
312 return "HA_ERR_FK_DEPTH_EXCEEDED";
313 case HA_ERR_INNODB_READ_ONLY:
314 return "HA_ERR_INNODB_READ_ONLY";
315 case HA_ERR_COMPUTE_FAILED:
316 return "HA_ERR_COMPUTE_FAILED";
317 case HA_ERR_NO_WAIT_LOCK:
318 return "HA_ERR_NO_WAIT_LOCK";
319 }
320 return "No Error!";
321 }
322
323 /**
324 Error reporting facility for Rows_log_event::do_apply_event
325
326 @param level error, warning or info
327 @param ha_error HA_ERR_ code
328 @param rli pointer to the active Relay_log_info instance
329 @param thd pointer to the slave thread's thd
330 @param table pointer to the event's table object
331 @param type the type of the event
332 @param log_name the master binlog file name
333 @param pos the master binlog file pos (the next after the event)
334
335 */
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)336 static void inline slave_rows_error_report(enum loglevel level, int ha_error,
337 Relay_log_info const *rli, THD *thd,
338 TABLE *table, const char *type,
339 const char *log_name, ulong pos) {
340 const char *handler_error = (ha_error ? HA_ERR(ha_error) : nullptr);
341 bool is_group_replication_applier_channel =
342 channel_map.is_group_replication_channel_name(
343 (const_cast<Relay_log_info *>(rli))->get_channel(), true);
344 char buff[MAX_SLAVE_ERRMSG], *slider;
345 const char *buff_end = buff + sizeof(buff);
346 size_t len;
347 Diagnostics_area::Sql_condition_iterator it =
348 thd->get_stmt_da()->sql_conditions();
349 const Sql_condition *err;
350 buff[0] = 0;
351
352 for (err = it++, slider = buff; err && slider < buff_end - 1;
353 slider += len, err = it++) {
354 len = snprintf(slider, buff_end - slider, " %s, Error_code: %d;",
355 err->message_text(), err->mysql_errno());
356 }
357 if (is_group_replication_applier_channel) {
358 if (ha_error != 0) {
359 rli->report(level,
360 thd->is_error() ? thd->get_stmt_da()->mysql_errno()
361 : ER_UNKNOWN_ERROR,
362 "Could not execute %s event on table %s.%s;"
363 "%s handler error %s",
364 type, table->s->db.str, table->s->table_name.str, buff,
365 handler_error == nullptr ? "<unknown>" : handler_error);
366 } else {
367 rli->report(level,
368 thd->is_error() ? thd->get_stmt_da()->mysql_errno()
369 : ER_UNKNOWN_ERROR,
370 "Could not execute %s event on table %s.%s;"
371 "%s",
372 type, table->s->db.str, table->s->table_name.str, buff);
373 }
374 } else {
375 if (ha_error != 0) {
376 rli->report(level,
377 thd->is_error() ? thd->get_stmt_da()->mysql_errno()
378 : ER_UNKNOWN_ERROR,
379 "Could not execute %s event on table %s.%s;"
380 "%s handler error %s; "
381 "the event's master log %s, end_log_pos %lu",
382 type, table->s->db.str, table->s->table_name.str, buff,
383 handler_error == nullptr ? "<unknown>" : handler_error,
384 log_name, pos);
385 } else {
386 rli->report(level,
387 thd->is_error() ? thd->get_stmt_da()->mysql_errno()
388 : ER_UNKNOWN_ERROR,
389 "Could not execute %s event on table %s.%s;"
390 "%s the event's master log %s, end_log_pos %lu",
391 type, table->s->db.str, table->s->table_name.str, buff,
392 log_name, pos);
393 }
394 }
395 }
396
397 /**
398 Set the rewritten database, or current database if it should not be
399 rewritten, into THD.
400
401 @param thd THD handle
402 @param db database name
403 @param db_len the length of database name
404
405 @retval true if the passed db is rewritten.
406 @retval false if the passed db is not rewritten.
407 */
set_thd_db(THD * thd,const char * db,size_t db_len)408 static bool set_thd_db(THD *thd, const char *db, size_t db_len) {
409 bool need_increase_counter = false;
410 char lcase_db_buf[NAME_LEN + 1];
411 LEX_CSTRING new_db;
412 new_db.length = db_len;
413 if (lower_case_table_names) {
414 my_stpcpy(lcase_db_buf, db);
415 my_casedn_str(system_charset_info, lcase_db_buf);
416 new_db.str = lcase_db_buf;
417 } else
418 new_db.str = db;
419
420 /* This function is called by a slave thread. */
421 DBUG_ASSERT(thd->rli_slave);
422
423 Rpl_filter *rpl_filter = thd->rli_slave->rpl_filter;
424 new_db.str = rpl_filter->get_rewrite_db(new_db.str, &new_db.length);
425
426 if (lower_case_table_names) {
427 /* lcase_db_buf != new_db.str means that lcase_db_buf is rewritten. */
428 if (strcmp(lcase_db_buf, new_db.str)) need_increase_counter = true;
429 } else {
430 /* db != new_db.str means that db is rewritten. */
431 if (strcmp(db, new_db.str)) need_increase_counter = true;
432 }
433
434 thd->set_db(new_db);
435
436 return need_increase_counter;
437 }
438
439 #endif
440
441 /*
442 pretty_print_str()
443 */
444
445 #ifndef MYSQL_SERVER
pretty_print_str(IO_CACHE * cache,const char * str,size_t len,bool identifier)446 static inline void pretty_print_str(IO_CACHE *cache, const char *str,
447 size_t len, bool identifier) {
448 const char *end = str + len;
449 my_b_printf(cache, identifier ? "`" : "\'");
450 while (str < end) {
451 char c;
452 switch ((c = *str++)) {
453 case '\n':
454 my_b_printf(cache, "\\n");
455 break;
456 case '\r':
457 my_b_printf(cache, "\\r");
458 break;
459 case '\\':
460 my_b_printf(cache, "\\\\");
461 break;
462 case '\b':
463 my_b_printf(cache, "\\b");
464 break;
465 case '\t':
466 my_b_printf(cache, "\\t");
467 break;
468 case '\'':
469 my_b_printf(cache, "\\'");
470 break;
471 case 0:
472 my_b_printf(cache, "\\0");
473 break;
474 case '`':
475 if (identifier)
476 my_b_printf(cache, "``");
477 else
478 my_b_printf(cache, "`");
479 break;
480 default:
481 my_b_printf(cache, "%c", c);
482 break;
483 }
484 }
485 my_b_printf(cache, identifier ? "`" : "\'");
486 }
487
488 /**
489 Print src as an string enclosed with "'"
490
491 @param[out] cache IO_CACHE where the string will be printed.
492 @param[in] str the string will be printed.
493 @param[in] len length of the string.
494 */
pretty_print_str(IO_CACHE * cache,const char * str,size_t len)495 static inline void pretty_print_str(IO_CACHE *cache, const char *str,
496 size_t len) {
497 pretty_print_str(cache, str, len, false);
498 }
499
500 /**
501 Print src as an identifier enclosed with "`"
502
503 @param[out] cache IO_CACHE where the identifier will be printed.
504 @param[in] str the string will be printed.
505 @param[in] len length of the string.
506 */
pretty_print_identifier(IO_CACHE * cache,const char * str,size_t len)507 static inline void pretty_print_identifier(IO_CACHE *cache, const char *str,
508 size_t len) {
509 pretty_print_str(cache, str, len, true);
510 }
511
512 #endif /* !MYSQL_SERVER */
513
514 #if defined(MYSQL_SERVER)
515
clear_all_errors(THD * thd,Relay_log_info * rli)516 static void clear_all_errors(THD *thd, Relay_log_info *rli) {
517 thd->is_slave_error = false;
518 thd->clear_error();
519 rli->clear_error();
520 if (rli->workers_array_initialized) {
521 for (size_t i = 0; i < rli->get_worker_count(); i++) {
522 rli->get_worker(i)->clear_error();
523 }
524 }
525 }
526
idempotent_error_code(int err_code)527 inline int idempotent_error_code(int err_code) {
528 int ret = 0;
529
530 switch (err_code) {
531 case 0:
532 ret = 1;
533 break;
534 /*
535 The following list of "idempotent" errors
536 means that an error from the list might happen
537 because of idempotent (more than once)
538 applying of a binlog file.
539 Notice, that binlog has a ddl operation its
540 second applying may cause
541
542 case HA_ERR_TABLE_DEF_CHANGED:
543 case HA_ERR_CANNOT_ADD_FOREIGN:
544
545 which are not included into to the list.
546
547 Note that HA_ERR_RECORD_DELETED is not in the list since
548 do_exec_row() should not return that error code.
549 */
550 case HA_ERR_RECORD_CHANGED:
551 case HA_ERR_KEY_NOT_FOUND:
552 case HA_ERR_END_OF_FILE:
553 case HA_ERR_FOUND_DUPP_KEY:
554 case HA_ERR_FOUND_DUPP_UNIQUE:
555 case HA_ERR_FOREIGN_DUPLICATE_KEY:
556 case HA_ERR_NO_REFERENCED_ROW:
557 case HA_ERR_ROW_IS_REFERENCED:
558 ret = 1;
559 break;
560 default:
561 ret = 0;
562 break;
563 }
564 return (ret);
565 }
566
567 /**
568 Ignore error code specified on command line.
569 */
570
ignored_error_code(int err_code)571 int ignored_error_code(int err_code) {
572 return ((err_code == ER_SLAVE_IGNORED_TABLE) ||
573 (use_slave_mask && bitmap_is_set(&slave_error_mask, err_code)));
574 }
575
576 /*
577 This function converts an engine's error to a server error.
578
579 If the thread does not have an error already reported, it tries to
580 define it by calling the engine's method print_error. However, if a
581 mapping is not found, it uses the ER_UNKNOWN_ERROR and prints out a
582 warning message.
583 */
convert_handler_error(int error,THD * thd,TABLE * table)584 static int convert_handler_error(int error, THD *thd, TABLE *table) {
585 uint actual_error = (thd->is_error() ? thd->get_stmt_da()->mysql_errno() : 0);
586
587 if (actual_error == 0) {
588 table->file->print_error(error, MYF(0));
589 actual_error = (thd->is_error() ? thd->get_stmt_da()->mysql_errno()
590 : ER_UNKNOWN_ERROR);
591 if (actual_error == ER_UNKNOWN_ERROR)
592 LogErr(WARNING_LEVEL, ER_UNKNOWN_ERROR_DETECTED_IN_SE, error);
593 }
594
595 return (actual_error);
596 }
597
concurrency_error_code(int error)598 inline bool concurrency_error_code(int error) {
599 switch (error) {
600 case ER_LOCK_WAIT_TIMEOUT:
601 case ER_LOCK_DEADLOCK:
602 case ER_XA_RBDEADLOCK:
603 return true;
604 default:
605 return (false);
606 }
607 }
608
unexpected_error_code(int unexpected_error)609 inline bool unexpected_error_code(int unexpected_error) {
610 switch (unexpected_error) {
611 case ER_NET_READ_ERROR:
612 case ER_NET_ERROR_ON_WRITE:
613 case ER_QUERY_INTERRUPTED:
614 case ER_SERVER_SHUTDOWN:
615 case ER_NEW_ABORTING_CONNECTION:
616 return (true);
617 default:
618 return (false);
619 }
620 }
621
622 /*
623 pretty_print_str()
624 */
pretty_print_str(String * packet,const char * str,size_t len)625 static void pretty_print_str(String *packet, const char *str, size_t len) {
626 packet->append('\'');
627
628 for (size_t i = 0; i < len; i++) {
629 switch (str[i]) {
630 case '\n':
631 packet->append("\\n");
632 break;
633 case '\r':
634 packet->append("\\r");
635 break;
636 case '\\':
637 packet->append("\\\\");
638 break;
639 case '\b':
640 packet->append("\\b");
641 break;
642 case '\t':
643 packet->append("\\t");
644 break;
645 case '\'':
646 packet->append("\\'");
647 break;
648 case 0:
649 packet->append("\\0");
650 break;
651 default:
652 packet->append(str[i]);
653 break;
654 }
655 }
656 packet->append('\'');
657 }
658
pretty_print_str(String * packet,const String * str)659 static inline void pretty_print_str(String *packet, const String *str) {
660 pretty_print_str(packet, str->ptr(), str->length());
661 }
662
663 /**
664 Creates a temporary name for load data infile:.
665
666 @param buf Store new filename here
667 @param file_id File_id (part of file name)
668 @param event_server_id Event_id (part of file name)
669 @param ext Extension for file name
670
671 @return
672 Pointer to start of extension
673 */
674
slave_load_file_stem(char * buf,uint file_id,int event_server_id,const char * ext)675 static char *slave_load_file_stem(char *buf, uint file_id, int event_server_id,
676 const char *ext) {
677 char *res;
678 fn_format(buf, PREFIX_SQL_LOAD, slave_load_tmpdir, "", MY_UNPACK_FILENAME);
679 to_unix_path(buf);
680
681 buf = strend(buf);
682 int appended_length = sprintf(buf, "%s-%d-", server_uuid, event_server_id);
683 buf += appended_length;
684 res = longlong10_to_str(file_id, buf, 10);
685 my_stpcpy(res, ext); // Add extension last
686 return res; // Pointer to extension
687 }
688
689 /**
690 Delete all temporary files used for SQL_LOAD.
691 */
692
cleanup_load_tmpdir()693 static void cleanup_load_tmpdir() {
694 MY_DIR *dirp;
695 FILEINFO *file;
696 uint i;
697 char fname[FN_REFLEN], prefbuf[TEMP_FILE_MAX_LEN], *p;
698
699 if (!(dirp = my_dir(slave_load_tmpdir, MYF(0)))) return;
700
701 /*
702 When we are deleting temporary files, we should only remove
703 the files associated with the server id of our server.
704 We don't use event_server_id here because since we've disabled
705 direct binlogging of Create_file/Append_file/Exec_load events
706 we cannot meet Start_log event in the middle of events from one
707 LOAD DATA.
708 */
709 p = strmake(prefbuf, STRING_WITH_LEN(PREFIX_SQL_LOAD));
710 sprintf(p, "%s-", server_uuid);
711
712 for (i = 0; i < dirp->number_off_files; i++) {
713 file = dirp->dir_entry + i;
714 if (is_prefix(file->name, prefbuf)) {
715 fn_format(fname, file->name, slave_load_tmpdir, "", MY_UNPACK_FILENAME);
716 mysql_file_delete(key_file_misc, fname, MYF(0));
717 }
718 }
719
720 my_dirend(dirp);
721 }
722 #endif
723
724 template <typename T>
net_field_length_checked(const uchar ** packet,size_t * max_length,T * out)725 bool net_field_length_checked(const uchar **packet, size_t *max_length,
726 T *out) {
727 if (*max_length < 1) return true;
728 const uchar *pos = *packet;
729 if (*pos < 251) {
730 (*packet)++;
731 (*max_length)--;
732 *out = (T)*pos;
733 } else if (*pos == 251) {
734 (*packet)++;
735 (*max_length)--;
736 *out = (T)NULL_LENGTH;
737 } else if (*pos == 252) {
738 if (*max_length < 3) return true;
739 (*packet) += 3;
740 (*max_length) -= 3;
741 *out = (T)uint2korr(pos + 1);
742 } else if (*pos == 253) {
743 if (*max_length < 4) return true;
744 (*packet) += 4;
745 (*max_length) -= 4;
746 *out = (T)uint3korr(pos + 1);
747 } else {
748 if (*max_length < 9) return true;
749 (*packet) += 9;
750 (*max_length) -= 9;
751 *out = (T)uint8korr(pos + 1);
752 }
753 return false;
754 }
755 template bool net_field_length_checked<size_t>(const uchar **packet,
756 size_t *max_length, size_t *out);
757 template bool net_field_length_checked<ulonglong>(const uchar **packet,
758 size_t *max_length,
759 ulonglong *out);
760
761 /**
762 Transforms a string into "" or its expression in 0x... form.
763 */
764
str_to_hex(char * to,const char * from,size_t len)765 char *str_to_hex(char *to, const char *from, size_t len) {
766 if (len) {
767 *to++ = '0';
768 *to++ = 'x';
769 to = octet2hex(to, from, len);
770 } else
771 to = my_stpcpy(to, "\"\"");
772 return to; // pointer to end 0 of 'to'
773 }
774
775 #ifdef MYSQL_SERVER
776
777 /**
778 Append a version of the 'from' string suitable for use in a query to
779 the 'to' string. To generate a correct escaping, the character set
780 information in 'csinfo' is used.
781 */
782
append_query_string(const THD * thd,const CHARSET_INFO * csinfo,String const * from,String * to)783 int append_query_string(const THD *thd, const CHARSET_INFO *csinfo,
784 String const *from, String *to) {
785 char *beg, *ptr;
786 size_t const orig_len = to->length();
787 if (to->reserve(orig_len + from->length() * 2 + 3)) return 1;
788
789 beg = to->c_ptr_quick() + to->length();
790 ptr = beg;
791 if (csinfo->escape_with_backslash_is_dangerous)
792 ptr = str_to_hex(ptr, from->ptr(), from->length());
793 else {
794 *ptr++ = '\'';
795 if (!(thd->variables.sql_mode & MODE_NO_BACKSLASH_ESCAPES)) {
796 ptr +=
797 escape_string_for_mysql(csinfo, ptr, 0, from->ptr(), from->length());
798 } else {
799 const char *frm_str = from->ptr();
800
801 for (; frm_str < (from->ptr() + from->length()); frm_str++) {
802 /* Using '' way to represent "'" */
803 if (*frm_str == '\'') *ptr++ = *frm_str;
804
805 *ptr++ = *frm_str;
806 }
807 }
808
809 *ptr++ = '\'';
810 }
811 to->length(orig_len + ptr - beg);
812 return 0;
813 }
814 #endif
815
816 /**
817 Prints a "session_var=value" string. Used by mysqlbinlog to print some SET
818 commands just before it prints a query.
819 */
820
821 #ifndef MYSQL_SERVER
822
print_set_option(IO_CACHE * file,uint32 bits_changed,uint32 option,uint32 flags,const char * name,bool * need_comma)823 static void print_set_option(IO_CACHE *file, uint32 bits_changed, uint32 option,
824 uint32 flags, const char *name, bool *need_comma) {
825 if (bits_changed & option) {
826 if (*need_comma) my_b_printf(file, ", ");
827 my_b_printf(file, "%s=%d", name, static_cast<bool>(flags & option));
828 *need_comma = true;
829 }
830 }
831 #endif
832
833 #ifdef MYSQL_SERVER
Replicated_columns_view(Replicated_columns_view::enum_replication_flow direction,THD const * thd)834 Replicated_columns_view::Replicated_columns_view(
835 Replicated_columns_view::enum_replication_flow direction, THD const *thd)
836 : Replicated_columns_view{nullptr, direction, thd} {}
837
Replicated_columns_view(TABLE const * target,Replicated_columns_view::enum_replication_flow direction,THD const * thd)838 Replicated_columns_view::Replicated_columns_view(
839 TABLE const *target,
840 Replicated_columns_view::enum_replication_flow direction, THD const *thd)
841 : Table_columns_view{} {
842 filter_fn_type filter{nullptr};
843
844 if (direction == Replicated_columns_view::OUTBOUND)
__anon029c70820102(TABLE const *table, size_t column_index) 845 filter = [this](TABLE const *table, size_t column_index) -> bool {
846 return this->outbound_filtering(table, column_index);
847 };
848 else
__anon029c70820202(TABLE const *table, size_t column_index) 849 filter = [this](TABLE const *table, size_t column_index) -> bool {
850 return this->inbound_filtering(table, column_index);
851 };
852
853 this->set_thd(thd) //
854 .set_filter(filter) //
855 .set_table(target);
856 }
857
set_thd(THD const * thd)858 Replicated_columns_view &Replicated_columns_view::set_thd(THD const *thd) {
859 this->m_thd = thd;
860 this->init_fields_bitmaps();
861 return (*this);
862 }
863
is_inbound_filtering_enabled()864 bool Replicated_columns_view::is_inbound_filtering_enabled() {
865 return (this->m_thd == nullptr ||
866 this->m_thd->variables.immediate_server_version ==
867 UNDEFINED_SERVER_VERSION ||
868 this->m_thd->variables.immediate_server_version >= 80018);
869 }
870
inbound_filtering(TABLE const * table,size_t column_index)871 bool Replicated_columns_view::inbound_filtering(TABLE const *table,
872 size_t column_index) {
873 if (!this->is_inbound_filtering_enabled()) return false;
874 // If the set of filtered columns is changed, we need to replicate the change
875 // in other blocks that reproduce the behavior - Rapid binlog parser, for
876 // instance.
877 return bitmap_is_set(&table->fields_for_functional_indexes, column_index);
878 }
879
outbound_filtering(TABLE const * table,size_t column_index)880 bool Replicated_columns_view::outbound_filtering(TABLE const *table,
881 size_t column_index) {
882 // If the set of filtered columns is changed, we need to replicate the change
883 // in other blocks that reproduce the behavior - Rapid binlog parser, for
884 // instance.
885 return bitmap_is_set(&table->fields_for_functional_indexes, column_index);
886 }
887 #endif
888
889 /**************************************************************************
890 Log_event methods (= the parent class of all events)
891 **************************************************************************/
892
893 #ifdef MYSQL_SERVER
894
get_time()895 time_t Log_event::get_time() {
896 /* Not previously initialized */
897 if (!common_header->when.tv_sec && !common_header->when.tv_usec) {
898 THD *tmp_thd = thd ? thd : current_thd;
899 if (tmp_thd)
900 common_header->when = tmp_thd->start_time;
901 else
902 my_micro_time_to_timeval(my_micro_time(), &(common_header->when));
903 }
904 return (time_t)common_header->when.tv_sec;
905 }
906
907 #endif
908
909 /**
910 @return
911 returns the human readable name of the event's type
912 */
913
get_type_str(Log_event_type type)914 const char *Log_event::get_type_str(Log_event_type type) {
915 switch (type) {
916 case binary_log::STOP_EVENT:
917 return "Stop";
918 case binary_log::QUERY_EVENT:
919 return "Query";
920 case binary_log::ROTATE_EVENT:
921 return "Rotate";
922 case binary_log::INTVAR_EVENT:
923 return "Intvar";
924 case binary_log::APPEND_BLOCK_EVENT:
925 return "Append_block";
926 case binary_log::DELETE_FILE_EVENT:
927 return "Delete_file";
928 case binary_log::RAND_EVENT:
929 return "RAND";
930 case binary_log::XID_EVENT:
931 return "Xid";
932 case binary_log::USER_VAR_EVENT:
933 return "User var";
934 case binary_log::FORMAT_DESCRIPTION_EVENT:
935 return "Format_desc";
936 case binary_log::TABLE_MAP_EVENT:
937 return "Table_map";
938 case binary_log::WRITE_ROWS_EVENT_V1:
939 return "Write_rows_v1";
940 case binary_log::UPDATE_ROWS_EVENT_V1:
941 return "Update_rows_v1";
942 case binary_log::DELETE_ROWS_EVENT_V1:
943 return "Delete_rows_v1";
944 case binary_log::BEGIN_LOAD_QUERY_EVENT:
945 return "Begin_load_query";
946 case binary_log::EXECUTE_LOAD_QUERY_EVENT:
947 return "Execute_load_query";
948 case binary_log::INCIDENT_EVENT:
949 return "Incident";
950 case binary_log::IGNORABLE_LOG_EVENT:
951 return "Ignorable";
952 case binary_log::ROWS_QUERY_LOG_EVENT:
953 return "Rows_query";
954 case binary_log::WRITE_ROWS_EVENT:
955 return "Write_rows";
956 case binary_log::UPDATE_ROWS_EVENT:
957 return "Update_rows";
958 case binary_log::DELETE_ROWS_EVENT:
959 return "Delete_rows";
960 case binary_log::GTID_LOG_EVENT:
961 return "Gtid";
962 case binary_log::ANONYMOUS_GTID_LOG_EVENT:
963 return "Anonymous_Gtid";
964 case binary_log::PREVIOUS_GTIDS_LOG_EVENT:
965 return "Previous_gtids";
966 case binary_log::HEARTBEAT_LOG_EVENT:
967 return "Heartbeat";
968 case binary_log::TRANSACTION_CONTEXT_EVENT:
969 return "Transaction_context";
970 case binary_log::VIEW_CHANGE_EVENT:
971 return "View_change";
972 case binary_log::XA_PREPARE_LOG_EVENT:
973 return "XA_prepare";
974 case binary_log::PARTIAL_UPDATE_ROWS_EVENT:
975 return "Update_rows_partial";
976 case binary_log::TRANSACTION_PAYLOAD_EVENT:
977 return "Transaction_payload";
978 default:
979 return "Unknown"; /* impossible */
980 }
981 }
982
get_type_str() const983 const char *Log_event::get_type_str() const {
984 return get_type_str(get_type_code());
985 }
986
987 /*
988 Log_event::Log_event()
989 */
990
991 #ifdef MYSQL_SERVER
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)992 Log_event::Log_event(THD *thd_arg, uint16 flags_arg,
993 enum_event_cache_type cache_type_arg,
994 enum_event_logging_type logging_type_arg,
995 Log_event_header *header, Log_event_footer *footer)
996 : temp_buf(nullptr),
997 m_free_temp_buf_in_destructor(true),
998 exec_time(0),
999 event_cache_type(cache_type_arg),
1000 event_logging_type(logging_type_arg),
1001 crc(0),
1002 common_header(header),
1003 common_footer(footer),
1004 thd(thd_arg) {
1005 server_id = thd->server_id;
1006 common_header->unmasked_server_id = server_id;
1007 common_header->when = thd->start_time;
1008 common_header->log_pos = 0;
1009 common_header->flags = flags_arg;
1010 }
1011
1012 /**
1013 This minimal constructor is for when you are not even sure that there
1014 is a valid THD. For example in the server when we are shutting down or
1015 flushing logs after receiving a SIGHUP (then we must write a Rotate to
1016 the binlog but we have no THD, so we need this minimal constructor).
1017 */
1018
Log_event(Log_event_header * header,Log_event_footer * footer,enum_event_cache_type cache_type_arg,enum_event_logging_type logging_type_arg)1019 Log_event::Log_event(Log_event_header *header, Log_event_footer *footer,
1020 enum_event_cache_type cache_type_arg,
1021 enum_event_logging_type logging_type_arg)
1022 : temp_buf(nullptr),
1023 m_free_temp_buf_in_destructor(true),
1024 exec_time(0),
1025 event_cache_type(cache_type_arg),
1026 event_logging_type(logging_type_arg),
1027 crc(0),
1028 common_header(header),
1029 common_footer(footer),
1030 thd(nullptr) {
1031 server_id = ::server_id;
1032 common_header->unmasked_server_id = server_id;
1033 }
1034 #endif /* MYSQL_SERVER */
1035
1036 /*
1037 Log_event::Log_event()
1038 */
1039
Log_event(Log_event_header * header,Log_event_footer * footer)1040 Log_event::Log_event(Log_event_header *header, Log_event_footer *footer)
1041 : temp_buf(nullptr),
1042 m_free_temp_buf_in_destructor(true),
1043 exec_time(0),
1044 event_cache_type(EVENT_INVALID_CACHE),
1045 event_logging_type(EVENT_INVALID_LOGGING),
1046 crc(0),
1047 common_header(header),
1048 common_footer(footer) {
1049 #ifdef MYSQL_SERVER
1050 thd = nullptr;
1051 #endif
1052 /*
1053 Mask out any irrelevant parts of the server_id
1054 */
1055 server_id = common_header->unmasked_server_id & opt_server_id_mask;
1056 }
1057
1058 /*
1059 This method is not on header file to avoid using key_memory_log_event
1060 outside log_event.cc, allowing header file to be included on plugins.
1061 */
operator new(size_t size)1062 void *Log_event::operator new(size_t size) {
1063 return my_malloc(key_memory_log_event, size, MYF(MY_WME | MY_FAE));
1064 }
1065
1066 #ifdef MYSQL_SERVER
do_apply_event_worker(Slave_worker * w)1067 inline int Log_event::do_apply_event_worker(Slave_worker *w) {
1068 DBUG_EXECUTE_IF("crash_in_a_worker", {
1069 /* we will crash a worker after waiting for
1070 2 seconds to make sure that other transactions are
1071 scheduled and completed */
1072 if (w->id == 2) {
1073 DBUG_SET("-d,crash_in_a_worker");
1074 my_sleep(2000000);
1075 DBUG_SUICIDE();
1076 }
1077 });
1078 return do_apply_event(w);
1079 }
1080
do_update_pos(Relay_log_info * rli)1081 int Log_event::do_update_pos(Relay_log_info *rli) {
1082 int error = 0;
1083 DBUG_ASSERT(!rli->belongs_to_client());
1084
1085 if (rli) error = rli->stmt_done(common_header->log_pos);
1086 return error;
1087 }
1088
do_shall_skip(Relay_log_info * rli)1089 Log_event::enum_skip_reason Log_event::do_shall_skip(Relay_log_info *rli) {
1090 /*
1091 The logic for slave_skip_counter is as follows:
1092
1093 - Events that are skipped because they have the same server_id as
1094 the slave do not decrease slave_skip_counter.
1095
1096 - Other events (that pass the server_id test) will decrease
1097 slave_skip_counter.
1098
1099 - Except in one case: if slave_skip_counter==1, it will only
1100 decrease to 0 if we are at a so-called group boundary. Here, a
1101 group is defined as the range of events that represent a single
1102 transaction in the relay log: see comment for is_in_group in
1103 rpl_rli.h for a definition.
1104
1105 The difficult part to implement is the logic to avoid decreasing
1106 the counter to 0. Given that groups have the form described in
1107 is_in_group in rpl_rli.h, we implement the logic as follows:
1108
1109 - Gtid, Rand, User_var, Int_var will never decrease the counter to
1110 0.
1111
1112 - BEGIN will set thd->variables.option_bits & OPTION_BEGIN and
1113 COMMIT/Xid will clear it. This happens regardless of whether
1114 the BEGIN/COMMIT/Xid is skipped itself.
1115
1116 - Other events will decrease the counter unless OPTION_BEGIN is
1117 set.
1118 */
1119 DBUG_PRINT("info", ("ev->server_id=%lu, ::server_id=%lu,"
1120 " rli->replicate_same_server_id=%d,"
1121 " rli->slave_skip_counter=%d",
1122 (ulong)server_id, (ulong)::server_id,
1123 rli->replicate_same_server_id, rli->slave_skip_counter));
1124 if ((server_id == ::server_id && !rli->replicate_same_server_id) ||
1125 (rli->slave_skip_counter == 1 && rli->is_in_group()))
1126 return EVENT_SKIP_IGNORE;
1127 else if (rli->slave_skip_counter > 0)
1128 return EVENT_SKIP_COUNT;
1129 else
1130 return EVENT_SKIP_NOT;
1131 }
1132
1133 /*
1134 Log_event::pack_info()
1135 */
1136
pack_info(Protocol * protocol)1137 int Log_event::pack_info(Protocol *protocol) {
1138 protocol->store("", &my_charset_bin);
1139 return 0;
1140 }
1141
get_db()1142 const char *Log_event::get_db() { return thd ? thd->db().str : nullptr; }
1143
1144 /**
1145 Only called by SHOW BINLOG EVENTS
1146 */
net_send(Protocol * protocol,const char * log_name,my_off_t pos)1147 int Log_event::net_send(Protocol *protocol, const char *log_name,
1148 my_off_t pos) {
1149 const char *p = strrchr(log_name, FN_LIBCHAR);
1150 const char *event_type;
1151 if (p) log_name = p + 1;
1152
1153 protocol->start_row();
1154 protocol->store(log_name, &my_charset_bin);
1155 protocol->store((ulonglong)pos);
1156 event_type = get_type_str();
1157 protocol->store_string(event_type, strlen(event_type), &my_charset_bin);
1158 protocol->store((uint32)server_id);
1159 protocol->store((ulonglong)common_header->log_pos);
1160 if (pack_info(protocol)) return 1;
1161 return protocol->end_row();
1162 }
1163
1164 /**
1165 init_show_field_list() prepares the column names and types for the
1166 output of SHOW BINLOG EVENTS; it is used only by SHOW BINLOG
1167 EVENTS.
1168 */
1169
init_show_field_list(List<Item> * field_list)1170 void Log_event::init_show_field_list(List<Item> *field_list) {
1171 field_list->push_back(new Item_empty_string("Log_name", 20));
1172 field_list->push_back(new Item_return_int("Pos", MY_INT32_NUM_DECIMAL_DIGITS,
1173 MYSQL_TYPE_LONGLONG));
1174 field_list->push_back(new Item_empty_string("Event_type", 20));
1175 field_list->push_back(new Item_return_int("Server_id", 10, MYSQL_TYPE_LONG));
1176 field_list->push_back(new Item_return_int(
1177 "End_log_pos", MY_INT32_NUM_DECIMAL_DIGITS, MYSQL_TYPE_LONGLONG));
1178 field_list->push_back(new Item_empty_string("Info", 20));
1179 }
1180
1181 /**
1182 A decider of whether to trigger checksum computation or not.
1183 To be invoked in Log_event::write() stack.
1184 The decision is positive
1185
1186 S,M) if it's been marked for checksumming with @c checksum_alg
1187
1188 M) otherwise, if @@global.binlog_checksum is not NONE and the event is
1189 directly written to the binlog file.
1190 The to-be-cached event decides at @c write_cache() time.
1191
1192 Otherwise the decision is negative.
1193
1194 @note A side effect of the method is altering Log_event::checksum_alg
1195 it the latter was undefined at calling.
1196
1197 @return true (positive) or false (negative)
1198 */
need_checksum()1199 bool Log_event::need_checksum() {
1200 DBUG_TRACE;
1201 bool ret = false;
1202 /*
1203 few callers of Log_event::write
1204 (incl FD::write, FD constructing code on the slave side, Rotate relay log
1205 and Stop event)
1206 provides their checksum alg preference through Log_event::checksum_alg.
1207 */
1208 if (common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_UNDEF)
1209 ret = (common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_OFF);
1210 else if (binlog_checksum_options != binary_log::BINLOG_CHECKSUM_ALG_OFF &&
1211 event_cache_type == Log_event::EVENT_NO_CACHE)
1212 ret = (binlog_checksum_options != 0);
1213 else
1214 ret = false;
1215
1216 /*
1217 FD calls the methods before data_written has been calculated.
1218 The following invariant claims if the current is not the first
1219 call (and therefore data_written is not zero) then `ret' must be
1220 true. It may not be null because FD is always checksummed.
1221 */
1222
1223 DBUG_ASSERT(get_type_code() != binary_log::FORMAT_DESCRIPTION_EVENT || ret ||
1224 common_header->data_written == 0);
1225
1226 if (common_footer->checksum_alg == binary_log::BINLOG_CHECKSUM_ALG_UNDEF)
1227 common_footer->checksum_alg =
1228 ret ? // calculated value stored
1229 static_cast<enum_binlog_checksum_alg>(binlog_checksum_options)
1230 : binary_log::BINLOG_CHECKSUM_ALG_OFF;
1231
1232 DBUG_ASSERT(
1233 !ret ||
1234 ((common_footer->checksum_alg ==
1235 static_cast<enum_binlog_checksum_alg>(binlog_checksum_options) ||
1236 /*
1237 Stop event closes the relay-log and its checksum alg
1238 preference is set by the caller can be different
1239 from the server's binlog_checksum_options.
1240 */
1241 get_type_code() == binary_log::STOP_EVENT ||
1242 /*
1243 Rotate:s can be checksummed regardless of the server's
1244 binlog_checksum_options. That applies to both
1245 the local RL's Rotate and the master's Rotate
1246 which IO thread instantiates via queue_binlog_ver_3_event.
1247 */
1248 get_type_code() == binary_log::ROTATE_EVENT ||
1249 /*
1250 The previous event has its checksum option defined
1251 according to the format description event.
1252 */
1253 get_type_code() == binary_log::PREVIOUS_GTIDS_LOG_EVENT ||
1254 /* FD is always checksummed */
1255 get_type_code() == binary_log::FORMAT_DESCRIPTION_EVENT ||
1256 /*
1257 View_change_log_event is queued into relay log by the
1258 local member, which may have a different checksum algorithm
1259 than the one of the event source.
1260 */
1261 get_type_code() == binary_log::VIEW_CHANGE_EVENT) &&
1262 common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_OFF));
1263
1264 DBUG_ASSERT(common_footer->checksum_alg !=
1265 binary_log::BINLOG_CHECKSUM_ALG_UNDEF);
1266 DBUG_ASSERT(((get_type_code() != binary_log::ROTATE_EVENT &&
1267 get_type_code() != binary_log::STOP_EVENT) ||
1268 get_type_code() != binary_log::FORMAT_DESCRIPTION_EVENT) ||
1269 event_cache_type == Log_event::EVENT_NO_CACHE);
1270
1271 return ret;
1272 }
1273
wrapper_my_b_safe_write(Basic_ostream * ostream,const uchar * buf,size_t size)1274 bool Log_event::wrapper_my_b_safe_write(Basic_ostream *ostream,
1275 const uchar *buf, size_t size) {
1276 if (size == 0) return false;
1277
1278 if (need_checksum() && size != 0) crc = checksum_crc32(crc, buf, size);
1279
1280 return ostream->write(buf, size);
1281 }
1282
write_footer(Basic_ostream * ostream)1283 bool Log_event::write_footer(Basic_ostream *ostream) {
1284 /*
1285 footer contains the checksum-algorithm descriptor
1286 followed by the checksum value
1287 */
1288 if (need_checksum()) {
1289 uchar buf[BINLOG_CHECKSUM_LEN];
1290 int4store(buf, crc);
1291 return ostream->write((uchar *)buf, sizeof(buf));
1292 }
1293 return false;
1294 }
1295
write_header_to_memory(uchar * buf)1296 uint32 Log_event::write_header_to_memory(uchar *buf) {
1297 // Query start time
1298 ulong timestamp = (ulong)get_time();
1299
1300 #ifndef DBUG_OFF
1301 if (DBUG_EVALUATE_IF("inc_event_time_by_1_hour", 1, 0) &&
1302 DBUG_EVALUATE_IF("dec_event_time_by_1_hour", 1, 0)) {
1303 /**
1304 This assertion guarantees that these debug flags are not
1305 used at the same time (they would cancel each other).
1306 */
1307 DBUG_ASSERT(0);
1308 } else {
1309 DBUG_EXECUTE_IF("inc_event_time_by_1_hour", timestamp = timestamp + 3600;);
1310 DBUG_EXECUTE_IF("dec_event_time_by_1_hour", timestamp = timestamp - 3600;);
1311 }
1312 #endif
1313
1314 /*
1315 Header will be of size LOG_EVENT_HEADER_LEN for all events, except for
1316 FORMAT_DESCRIPTION_EVENT and ROTATE_EVENT, where it will be
1317 LOG_EVENT_MINIMAL_HEADER_LEN (remember these 2 have a frozen header,
1318 because we read them before knowing the format).
1319 */
1320
1321 int4store(buf, timestamp);
1322 buf[EVENT_TYPE_OFFSET] = get_type_code();
1323 int4store(buf + SERVER_ID_OFFSET, server_id);
1324 int4store(buf + EVENT_LEN_OFFSET,
1325 static_cast<uint32>(common_header->data_written));
1326 int4store(buf + LOG_POS_OFFSET, static_cast<uint32>(common_header->log_pos));
1327 int2store(buf + FLAGS_OFFSET, common_header->flags);
1328
1329 return LOG_EVENT_HEADER_LEN;
1330 }
1331
write_header(Basic_ostream * ostream,size_t event_data_length)1332 bool Log_event::write_header(Basic_ostream *ostream, size_t event_data_length) {
1333 uchar header[LOG_EVENT_HEADER_LEN];
1334 bool ret;
1335 DBUG_TRACE;
1336
1337 /* Store number of bytes that will be written by this event */
1338 common_header->data_written = event_data_length + sizeof(header);
1339
1340 if (need_checksum()) {
1341 crc = checksum_crc32(0L, nullptr, 0);
1342 common_header->data_written += BINLOG_CHECKSUM_LEN;
1343 }
1344
1345 /*
1346 Usually events are written into binlog cache first. And later, they are
1347 flushed into binlog file. When events are being written into binlog cache,
1348 log_pos(a.k.a. end_log_pos) field is meaningless. So it is set to 0. the
1349 log_pos field will be updated later when the events are being flushed into
1350 binlog file.
1351
1352 In a few cases(e.g. rotation(FD, Rotate events)), events are written into
1353 binlog file directly through event->write(). In these cases, log_pos is
1354 updated to the begin position of the event before calling event->write().
1355 Then log_pos is updated to the end position of the event here.
1356 */
1357 if (common_header->log_pos != 0) {
1358 common_header->log_pos += common_header->data_written;
1359 }
1360
1361 write_header_to_memory(header);
1362
1363 ret = ostream->write(header, LOG_EVENT_HEADER_LEN);
1364
1365 /*
1366 Update the checksum.
1367
1368 In case this is a Format_description_log_event, we need to clear
1369 the LOG_EVENT_BINLOG_IN_USE_F flag before computing the checksum,
1370 since the flag will be cleared when the binlog is closed. On
1371 verification, the flag is dropped before computing the checksum
1372 too.
1373 */
1374 if (need_checksum() &&
1375 (common_header->flags & LOG_EVENT_BINLOG_IN_USE_F) != 0) {
1376 common_header->flags &= ~LOG_EVENT_BINLOG_IN_USE_F;
1377 int2store(header + FLAGS_OFFSET, common_header->flags);
1378 }
1379 crc = my_checksum(crc, header, LOG_EVENT_HEADER_LEN);
1380
1381 return ret;
1382 }
1383 #endif /* MYSQL_SERVER */
1384
is_valid()1385 bool Log_event::is_valid() {
1386 return common_header != nullptr && common_header->get_is_valid();
1387 }
1388
1389 #ifndef MYSQL_SERVER
1390
1391 /*
1392 Log_event::print_header()
1393 */
1394
print_header(IO_CACHE * file,PRINT_EVENT_INFO * print_event_info,bool is_more MY_ATTRIBUTE ((unused))) const1395 void Log_event::print_header(IO_CACHE *file, PRINT_EVENT_INFO *print_event_info,
1396 bool is_more MY_ATTRIBUTE((unused))) const {
1397 char llbuff[22];
1398 my_off_t hexdump_from = print_event_info->hexdump_from;
1399 DBUG_TRACE;
1400
1401 my_b_printf(file, "#");
1402 print_timestamp(file, nullptr);
1403 my_b_printf(file, " server id %lu end_log_pos %s ", (ulong)server_id,
1404 llstr(common_header->log_pos, llbuff));
1405
1406 /* print the checksum */
1407
1408 if (common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_OFF &&
1409 common_footer->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_UNDEF) {
1410 char checksum_buf[BINLOG_CHECKSUM_LEN * 2 + 4]; // to fit to "0x%lx "
1411 size_t const bytes_written =
1412 snprintf(checksum_buf, sizeof(checksum_buf), "0x%08lx ", (ulong)crc);
1413 my_b_printf(
1414 file, "%s ",
1415 get_type(&binlog_checksum_typelib, common_footer->checksum_alg));
1416 my_b_printf(file, checksum_buf, bytes_written);
1417 }
1418
1419 /* mysqlbinlog --hexdump */
1420 if (print_event_info->hexdump_from) {
1421 my_b_printf(file, "\n");
1422 uchar *ptr = (uchar *)temp_buf;
1423 my_off_t size =
1424 uint4korr(ptr + EVENT_LEN_OFFSET) - LOG_EVENT_MINIMAL_HEADER_LEN;
1425 my_off_t i;
1426
1427 /* Header len * 4 >= header len * (2 chars + space + extra space) */
1428 char *h, hex_string[49] = {0};
1429 char *c, char_string[16 + 1] = {0};
1430
1431 /* Pretty-print event common header if header is exactly 19 bytes */
1432 if (print_event_info->common_header_len == LOG_EVENT_MINIMAL_HEADER_LEN) {
1433 char emit_buf[256]; // Enough for storing one line
1434 my_b_printf(file,
1435 "# Position Timestamp Type Master ID "
1436 "Size Master Pos Flags \n");
1437 size_t const bytes_written = snprintf(
1438 emit_buf, sizeof(emit_buf),
1439 "# %8.8lx %02x %02x %02x %02x %02x "
1440 "%02x %02x %02x %02x %02x %02x %02x %02x "
1441 "%02x %02x %02x %02x %02x %02x\n",
1442 (unsigned long)hexdump_from, ptr[0], ptr[1], ptr[2], ptr[3], ptr[4],
1443 ptr[5], ptr[6], ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], ptr[12],
1444 ptr[13], ptr[14], ptr[15], ptr[16], ptr[17], ptr[18]);
1445 DBUG_ASSERT(static_cast<size_t>(bytes_written) < sizeof(emit_buf));
1446 my_b_write(file, (uchar *)emit_buf, bytes_written);
1447 ptr += LOG_EVENT_MINIMAL_HEADER_LEN;
1448 hexdump_from += LOG_EVENT_MINIMAL_HEADER_LEN;
1449 }
1450
1451 /* Rest of event (without common header) */
1452 for (i = 0, c = char_string, h = hex_string; i < size; i++, ptr++) {
1453 snprintf(h, 4, (i % 16 <= 7) ? "%02x " : " %02x", *ptr);
1454 h += 3;
1455
1456 *c++ = my_isalnum(&my_charset_bin, *ptr) ? *ptr : '.';
1457
1458 if (i % 16 == 15) {
1459 /*
1460 my_b_printf() does not support full printf() formats, so we
1461 have to do it this way.
1462
1463 TODO: Rewrite my_b_printf() to support full printf() syntax.
1464 */
1465 char emit_buf[256];
1466 size_t const bytes_written =
1467 snprintf(emit_buf, sizeof(emit_buf), "# %8.8lx %-48.48s |%16s|\n",
1468 (unsigned long)(hexdump_from + (i & 0xfffffff0)),
1469 hex_string, char_string);
1470 DBUG_ASSERT(static_cast<size_t>(bytes_written) < sizeof(emit_buf));
1471 my_b_write(file, (uchar *)emit_buf, bytes_written);
1472 hex_string[0] = 0;
1473 char_string[0] = 0;
1474 c = char_string;
1475 h = hex_string;
1476 }
1477 }
1478 *c = '\0';
1479 DBUG_ASSERT(hex_string[48] == 0);
1480
1481 if (hex_string[0]) {
1482 char emit_buf[256];
1483 // Right-pad hex_string with spaces, up to 48 characters.
1484 memset(h, ' ', (sizeof(hex_string) - 1) - (h - hex_string));
1485 size_t const bytes_written =
1486 snprintf(emit_buf, sizeof(emit_buf), "# %8.8lx %-48.48s |%s|\n",
1487 (unsigned long)(hexdump_from + (i & 0xfffffff0)), hex_string,
1488 char_string);
1489 DBUG_ASSERT(static_cast<size_t>(bytes_written) < sizeof(emit_buf));
1490 my_b_write(file, (uchar *)emit_buf, bytes_written);
1491 }
1492 /*
1493 need a # to prefix the rest of printouts for example those of
1494 Rows_log_event::print_helper().
1495 */
1496 my_b_write(file, reinterpret_cast<const uchar *>("# "), 2);
1497 }
1498 }
1499
1500 /**
1501 Auxiliary function that sets up a conversion table for m_b_write_quoted.
1502
1503 The table has 256 elements. The i'th element is 5 characters, the
1504 first being the length (1..4) and the remaining containing character
1505 #i quoted and not null-terminated. If character #i does not need
1506 quoting (it is >= 32 and not backslash or single-quote), the table
1507 only contains the character itself. A quoted character needs at
1508 most 4 bytes ("\xXX"), plus the length byte, so each element is 5
1509 bytes.
1510
1511 This function is called exactly once even in a multi-threaded
1512 environment, because it is only called in the initializer of a
1513 static variable.
1514
1515 @return Pointer to the table, a 256*5 character array where
1516 character i quoted .
1517 */
get_quote_table()1518 static const uchar *get_quote_table() {
1519 static uchar buf[256][5];
1520 for (int i = 0; i < 256; i++) {
1521 char str[6];
1522 switch (i) {
1523 case '\b':
1524 strcpy(str, "\\b");
1525 break;
1526 case '\f':
1527 strcpy(str, "\\f");
1528 break;
1529 case '\n':
1530 strcpy(str, "\\n");
1531 break;
1532 case '\r':
1533 strcpy(str, "\\r");
1534 break;
1535 case '\t':
1536 strcpy(str, "\\t");
1537 break;
1538 case '\\':
1539 strcpy(str, "\\\\");
1540 break;
1541 case '\'':
1542 strcpy(str, "\\'");
1543 break;
1544 default:
1545 if (i < 32)
1546 sprintf(str, "\\x%02x", i);
1547 else {
1548 str[0] = i;
1549 str[1] = '\0';
1550 }
1551 break;
1552 }
1553 buf[i][0] = strlen(str);
1554 memcpy(buf[i] + 1, str, strlen(str));
1555 }
1556 return (const uchar *)(buf);
1557 }
1558
1559 /**
1560 Prints a quoted string to io cache.
1561 Control characters are displayed as hex sequence, e.g. \x00
1562
1563 @param[in] file IO cache
1564 @param[in] ptr Pointer to string
1565 @param[in] length String length
1566
1567 @retval false Success
1568 @retval true Failure
1569 */
my_b_write_quoted(IO_CACHE * file,const uchar * ptr,uint length)1570 static bool my_b_write_quoted(IO_CACHE *file, const uchar *ptr, uint length) {
1571 const uchar *s;
1572 static const uchar *quote_table = get_quote_table();
1573 my_b_printf(file, "'");
1574 for (s = ptr; length > 0; s++, length--) {
1575 const uchar *len_and_str = quote_table + *s * 5;
1576 my_b_write(file, len_and_str + 1, len_and_str[0]);
1577 }
1578 if (my_b_printf(file, "'") == (size_t)-1) return true;
1579 return false;
1580 }
1581
1582 /**
1583 Prints a bit string to io cache in format b'1010'.
1584
1585 @param[in] file IO cache
1586 @param[in] ptr Pointer to string
1587 @param[in] nbits Number of bits
1588 */
my_b_write_bit(IO_CACHE * file,const uchar * ptr,uint nbits)1589 static void my_b_write_bit(IO_CACHE *file, const uchar *ptr, uint nbits) {
1590 uint bitnum, nbits8 = ((nbits + 7) / 8) * 8, skip_bits = nbits8 - nbits;
1591 my_b_printf(file, "b'");
1592 for (bitnum = skip_bits; bitnum < nbits8; bitnum++) {
1593 int is_set = (ptr[(bitnum) / 8] >> (7 - bitnum % 8)) & 0x01;
1594 my_b_write(file, (const uchar *)(is_set ? "1" : "0"), 1);
1595 }
1596 my_b_printf(file, "'");
1597 }
1598
1599 /**
1600 Prints a packed string to io cache.
1601 The string consists of length packed to 1 or 2 bytes,
1602 followed by string data itself.
1603
1604 @param[in] file IO cache
1605 @param[in] ptr Pointer to string
1606 @param[in] length String size
1607
1608 @retval - number of bytes scanned.
1609 */
my_b_write_quoted_with_length(IO_CACHE * file,const uchar * ptr,uint length)1610 static size_t my_b_write_quoted_with_length(IO_CACHE *file, const uchar *ptr,
1611 uint length) {
1612 if (length < 256) {
1613 length = *ptr;
1614 my_b_write_quoted(file, ptr + 1, length);
1615 return length + 1;
1616 } else {
1617 length = uint2korr(ptr);
1618 my_b_write_quoted(file, ptr + 2, length);
1619 return length + 2;
1620 }
1621 }
1622
1623 /**
1624 Prints a 32-bit number in both signed and unsigned representation
1625
1626 @param[in] file IO cache
1627 @param[in] si Signed number
1628 @param[in] ui Unsigned number
1629 */
my_b_write_sint32_and_uint32(IO_CACHE * file,int32 si,uint32 ui)1630 static void my_b_write_sint32_and_uint32(IO_CACHE *file, int32 si, uint32 ui) {
1631 my_b_printf(file, "%d", si);
1632 if (si < 0) my_b_printf(file, " (%u)", ui);
1633 }
1634
1635 #ifndef MYSQL_SERVER
json_diff_operation_name(enum_json_diff_operation op,int last_path_char)1636 static const char *json_diff_operation_name(enum_json_diff_operation op,
1637 int last_path_char) {
1638 switch (op) {
1639 case enum_json_diff_operation::REPLACE:
1640 return "JSON_REPLACE";
1641 case enum_json_diff_operation::INSERT:
1642 if (last_path_char == ']')
1643 return "JSON_ARRAY_INSERT";
1644 else
1645 return "JSON_INSERT";
1646 case enum_json_diff_operation::REMOVE:
1647 return "JSON_REMOVE";
1648 }
1649 /* NOTREACHED */
1650 /* purecov: begin deadcode */
1651 DBUG_ASSERT(0);
1652 return nullptr;
1653 /* purecov: end */
1654 }
1655
json_wrapper_to_string(IO_CACHE * out,String * buf,Json_wrapper * wrapper,bool json_type)1656 static bool json_wrapper_to_string(IO_CACHE *out, String *buf,
1657 Json_wrapper *wrapper, bool json_type) {
1658 if (wrapper->to_string(buf, false, "json_wrapper_to_string"))
1659 return true; /* purecov: inspected */ // OOM
1660 if (json_type)
1661 return my_b_write_quoted(out, (uchar *)buf->ptr(), buf->length());
1662 switch (wrapper->type()) {
1663 case enum_json_type::J_NULL:
1664 case enum_json_type::J_DECIMAL:
1665 case enum_json_type::J_INT:
1666 case enum_json_type::J_UINT:
1667 case enum_json_type::J_DOUBLE:
1668 case enum_json_type::J_BOOLEAN:
1669 my_b_write(out, (uchar *)buf->ptr(), buf->length());
1670 break;
1671 case enum_json_type::J_STRING:
1672 case enum_json_type::J_DATE:
1673 case enum_json_type::J_TIME:
1674 case enum_json_type::J_DATETIME:
1675 case enum_json_type::J_TIMESTAMP:
1676 case enum_json_type::J_OPAQUE:
1677 case enum_json_type::J_ERROR:
1678 my_b_write_quoted(out, (uchar *)buf->ptr(), buf->length());
1679 break;
1680 case enum_json_type::J_OBJECT:
1681 case enum_json_type::J_ARRAY:
1682 my_b_printf(out, "CAST(");
1683 my_b_write_quoted(out, (uchar *)buf->ptr(), buf->length());
1684 my_b_printf(out, " AS JSON)");
1685 break;
1686 default:
1687 DBUG_ASSERT(0); /* purecov: deadcode */
1688 }
1689 return false;
1690 }
1691
print_json_diff(IO_CACHE * out,const uchar * data,size_t length,const char * col_name)1692 static const char *print_json_diff(IO_CACHE *out, const uchar *data,
1693 size_t length, const char *col_name) {
1694 DBUG_TRACE;
1695
1696 static const char *line_separator = "\n### ";
1697
1698 // read length
1699 const uchar *p = data;
1700
1701 const uchar *start_p = p;
1702 size_t start_length = length;
1703
1704 // Read the list of operations.
1705 std::vector<const char *> operation_names;
1706 while (length) {
1707 // read operation
1708 int operation_int = *p;
1709 if (operation_int >= JSON_DIFF_OPERATION_COUNT)
1710 return "reading operation type (invalid operation code)";
1711 enum_json_diff_operation operation =
1712 static_cast<enum_json_diff_operation>(operation_int);
1713 p++;
1714 length--;
1715
1716 // skip path
1717 size_t path_length;
1718 if (net_field_length_checked<size_t>(&p, &length, &path_length))
1719 return "reading path length to skip";
1720 if (path_length > length) return "skipping path";
1721 p += path_length;
1722 length -= path_length;
1723
1724 // compute operation name
1725 const char *operation_name = json_diff_operation_name(operation, p[-1]);
1726 operation_names.push_back(operation_name);
1727
1728 // skip value
1729 if (operation != enum_json_diff_operation::REMOVE) {
1730 size_t value_length;
1731 if (net_field_length_checked<size_t>(&p, &length, &value_length))
1732 return "reading value length to skip";
1733 if (value_length > length) return "skipping value";
1734 p += value_length;
1735 length -= value_length;
1736 }
1737 }
1738
1739 // Print function names in reverse order.
1740 bool printed = false;
1741 for (int i = operation_names.size() - 1; i >= 0; i--) {
1742 if (i == 0 || operation_names[i - 1] != operation_names[i]) {
1743 if (printed)
1744 if (my_b_printf(out, "%s", line_separator) == (size_t)-1)
1745 return "printing line separator";
1746 /* purecov: inspected */ // error writing to output
1747 if (my_b_printf(out, "%s(", operation_names[i]) == (size_t)-1)
1748 return "printing function name";
1749 /* purecov: inspected */ // error writing to output
1750 printed = true;
1751 }
1752 }
1753
1754 // Print column id
1755 if (my_b_printf(out, "%s", col_name) == (size_t)-1)
1756 return "printing column id";
1757 /* purecov: inspected */ // error writing to output
1758
1759 // In case this vector is empty (a no-op), make an early return
1760 // after printing only the column name
1761 if (operation_names.size() == 0) return nullptr;
1762
1763 // Print comma between column name and next function argument
1764 if (my_b_printf(out, ", ") == (size_t)-1) return "printing comma";
1765 /* purecov: inspected */ // error writing to output
1766
1767 // Print paths and values.
1768 p = start_p;
1769 length = start_length;
1770 StringBuffer<STRING_BUFFER_USUAL_SIZE> buf;
1771 int diff_i = 0;
1772 while (length) {
1773 // Read operation
1774 enum_json_diff_operation operation = (enum_json_diff_operation)*p;
1775 p++;
1776 length--;
1777
1778 // Read path length
1779 size_t path_length;
1780 if (net_field_length_checked<size_t>(&p, &length, &path_length))
1781 return "reading path length";
1782 /* purecov: deadcode */ // already checked in loop above
1783
1784 // Print path
1785 if (my_b_write_quoted(out, p, path_length)) return "printing path";
1786 /* purecov: inspected */ // error writing to output
1787 p += path_length;
1788 length -= path_length;
1789
1790 if (operation != enum_json_diff_operation::REMOVE) {
1791 // Print comma between path and value
1792 if (my_b_printf(out, ", ") == (size_t)-1) return "printing comma";
1793 /* purecov: inspected */ // error writing to output
1794
1795 // Read value length
1796 size_t value_length;
1797 if (net_field_length_checked<size_t>(&p, &length, &value_length))
1798 return "reading value length";
1799 /* purecov: deadcode */ // already checked in loop above
1800
1801 // Read value
1802 json_binary::Value value =
1803 json_binary::parse_binary((const char *)p, value_length);
1804 p += value_length;
1805 length -= value_length;
1806 if (value.type() == json_binary::Value::ERROR)
1807 return "parsing json value";
1808 Json_wrapper wrapper(value);
1809
1810 // Print value
1811 buf.length(0);
1812 if (json_wrapper_to_string(out, &buf, &wrapper, false))
1813 return "converting json to string";
1814 /* purecov: inspected */ // OOM
1815 buf.length(0);
1816 }
1817
1818 // Print closing parenthesis
1819 if (length == 0 || operation_names[diff_i + 1] != operation_names[diff_i])
1820 if (my_b_printf(out, ")") == (size_t)-1)
1821 return "printing closing parenthesis";
1822 /* purecov: inspected */ // error writing to output
1823
1824 // Print ending comma
1825 if (length != 0)
1826 if (my_b_printf(out, ",%s", line_separator) == (size_t)-1)
1827 return "printing comma";
1828 /* purecov: inspected */ // error writing to output
1829
1830 diff_i++;
1831 }
1832
1833 return nullptr;
1834 }
1835 #endif // ifndef MYSQL_SERVER
1836
1837 /**
1838 Print a packed value of the given SQL type into IO cache
1839
1840 @param[in] file IO cache
1841 @param[in] ptr Pointer to string
1842 @param[in] type Column type
1843 @param[in] meta Column meta information
1844 @param[out] typestr SQL type string buffer (for verbose output)
1845 @param[in] typestr_length Size of typestr
1846 @param[in] col_name Column name
1847 @param[in] is_partial True if this is a JSON column that will be
1848 read in partial format, false otherwise.
1849
1850 @retval 0 on error
1851 @retval number of bytes scanned from ptr for non-NULL fields, or
1852 another positive number for NULL fields
1853 */
1854 #ifndef MYSQL_SERVER
log_event_print_value(IO_CACHE * file,const uchar * ptr,uint type,uint meta,char * typestr,size_t typestr_length,char * col_name,bool is_partial)1855 static size_t log_event_print_value(IO_CACHE *file, const uchar *ptr, uint type,
1856 uint meta, char *typestr,
1857 size_t typestr_length, char *col_name,
1858 bool is_partial) {
1859 uint32 length = 0;
1860
1861 if (type == MYSQL_TYPE_STRING) {
1862 if (meta >= 256) {
1863 uint byte0 = meta >> 8;
1864 uint byte1 = meta & 0xFF;
1865
1866 if ((byte0 & 0x30) != 0x30) {
1867 /* a long CHAR() field: see #37426 */
1868 length = byte1 | (((byte0 & 0x30) ^ 0x30) << 4);
1869 type = byte0 | 0x30;
1870 } else
1871 length = meta & 0xFF;
1872 } else
1873 length = meta;
1874 }
1875
1876 switch (type) {
1877 case MYSQL_TYPE_LONG: {
1878 snprintf(typestr, typestr_length, "INT");
1879 if (!ptr) return my_b_printf(file, "NULL");
1880 int32 si = sint4korr(ptr);
1881 uint32 ui = uint4korr(ptr);
1882 my_b_write_sint32_and_uint32(file, si, ui);
1883 return 4;
1884 }
1885
1886 case MYSQL_TYPE_TINY: {
1887 snprintf(typestr, typestr_length, "TINYINT");
1888 if (!ptr) return my_b_printf(file, "NULL");
1889 my_b_write_sint32_and_uint32(file, (int)(signed char)*ptr,
1890 (uint)(unsigned char)*ptr);
1891 return 1;
1892 }
1893
1894 case MYSQL_TYPE_SHORT: {
1895 snprintf(typestr, typestr_length, "SHORTINT");
1896 if (!ptr) return my_b_printf(file, "NULL");
1897 int32 si = (int32)sint2korr(ptr);
1898 uint32 ui = (uint32)uint2korr(ptr);
1899 my_b_write_sint32_and_uint32(file, si, ui);
1900 return 2;
1901 }
1902
1903 case MYSQL_TYPE_INT24: {
1904 snprintf(typestr, typestr_length, "MEDIUMINT");
1905 if (!ptr) return my_b_printf(file, "NULL");
1906 int32 si = sint3korr(ptr);
1907 uint32 ui = uint3korr(ptr);
1908 my_b_write_sint32_and_uint32(file, si, ui);
1909 return 3;
1910 }
1911
1912 case MYSQL_TYPE_LONGLONG: {
1913 snprintf(typestr, typestr_length, "LONGINT");
1914 if (!ptr) return my_b_printf(file, "NULL");
1915 char tmp[64];
1916 longlong si = sint8korr(ptr);
1917 longlong10_to_str(si, tmp, -10);
1918 my_b_printf(file, "%s", tmp);
1919 if (si < 0) {
1920 ulonglong ui = uint8korr(ptr);
1921 longlong10_to_str((longlong)ui, tmp, 10);
1922 my_b_printf(file, " (%s)", tmp);
1923 }
1924 return 8;
1925 }
1926
1927 case MYSQL_TYPE_NEWDECIMAL: {
1928 uint precision = meta >> 8;
1929 uint decimals = meta & 0xFF;
1930 snprintf(typestr, typestr_length, "DECIMAL(%d,%d)", precision, decimals);
1931 if (!ptr) return my_b_printf(file, "NULL");
1932 uint bin_size = my_decimal_get_binary_size(precision, decimals);
1933 my_decimal dec;
1934 binary2my_decimal(E_DEC_FATAL_ERROR, pointer_cast<const uchar *>(ptr),
1935 &dec, precision, decimals);
1936 char buff[DECIMAL_MAX_STR_LENGTH + 1];
1937 int len = sizeof(buff);
1938 decimal2string(&dec, buff, &len);
1939 my_b_printf(file, "%s", buff);
1940 return bin_size;
1941 }
1942
1943 case MYSQL_TYPE_FLOAT: {
1944 snprintf(typestr, typestr_length, "FLOAT");
1945 if (!ptr) return my_b_printf(file, "NULL");
1946 float fl = float4get(ptr);
1947 char tmp[320];
1948 sprintf(tmp, "%-20g", (double)fl);
1949 my_b_printf(file, "%s", tmp); /* my_b_printf doesn't support %-20g */
1950 return 4;
1951 }
1952
1953 case MYSQL_TYPE_DOUBLE: {
1954 strcpy(typestr, "DOUBLE");
1955 if (!ptr) return my_b_printf(file, "NULL");
1956 double dbl = float8get(ptr);
1957 char tmp[320];
1958 sprintf(tmp, "%-.20g", dbl); /* my_b_printf doesn't support %-20g */
1959 my_b_printf(file, "%s", tmp);
1960 return 8;
1961 }
1962
1963 case MYSQL_TYPE_BIT: {
1964 /* Meta-data: bit_len, bytes_in_rec, 2 bytes */
1965 uint nbits = ((meta >> 8) * 8) + (meta & 0xFF);
1966 snprintf(typestr, typestr_length, "BIT(%d)", nbits);
1967 if (!ptr) return my_b_printf(file, "NULL");
1968 length = (nbits + 7) / 8;
1969 my_b_write_bit(file, ptr, nbits);
1970 return length;
1971 }
1972
1973 case MYSQL_TYPE_TIMESTAMP: {
1974 snprintf(typestr, typestr_length, "TIMESTAMP");
1975 if (!ptr) return my_b_printf(file, "NULL");
1976 uint32 i32 = uint4korr(ptr);
1977 my_b_printf(file, "%d", i32);
1978 return 4;
1979 }
1980
1981 case MYSQL_TYPE_TIMESTAMP2: {
1982 snprintf(typestr, typestr_length, "TIMESTAMP(%d)", meta);
1983 if (!ptr) return my_b_printf(file, "NULL");
1984 char buf[MAX_DATE_STRING_REP_LENGTH];
1985 struct timeval tm;
1986 my_timestamp_from_binary(&tm, ptr, meta);
1987 int buflen = my_timeval_to_str(&tm, buf, meta);
1988 my_b_write(file, pointer_cast<uchar *>(buf), buflen);
1989 return my_timestamp_binary_length(meta);
1990 }
1991
1992 case MYSQL_TYPE_DATETIME: {
1993 snprintf(typestr, typestr_length, "DATETIME");
1994 if (!ptr) return my_b_printf(file, "NULL");
1995 size_t d, t;
1996 uint64 i64 = uint8korr(ptr); /* YYYYMMDDhhmmss */
1997 d = static_cast<size_t>(i64 / 1000000);
1998 t = i64 % 1000000;
1999 my_b_printf(file, "%04d-%02d-%02d %02d:%02d:%02d",
2000 static_cast<int>(d / 10000),
2001 static_cast<int>(d % 10000) / 100, static_cast<int>(d % 100),
2002 static_cast<int>(t / 10000),
2003 static_cast<int>(t % 10000) / 100, static_cast<int>(t % 100));
2004 return 8;
2005 }
2006
2007 case MYSQL_TYPE_DATETIME2: {
2008 snprintf(typestr, typestr_length, "DATETIME(%d)", meta);
2009 if (!ptr) return my_b_printf(file, "NULL");
2010 char buf[MAX_DATE_STRING_REP_LENGTH];
2011 MYSQL_TIME ltime;
2012 longlong packed = my_datetime_packed_from_binary(ptr, meta);
2013 TIME_from_longlong_datetime_packed(<ime, packed);
2014 int buflen = my_datetime_to_str(ltime, buf, meta);
2015 my_b_write_quoted(file, (uchar *)buf, buflen);
2016 return my_datetime_binary_length(meta);
2017 }
2018
2019 case MYSQL_TYPE_TIME: {
2020 snprintf(typestr, typestr_length, "TIME");
2021 if (!ptr) return my_b_printf(file, "NULL");
2022 uint32 i32 = uint3korr(ptr);
2023 my_b_printf(file, "'%02d:%02d:%02d'", i32 / 10000, (i32 % 10000) / 100,
2024 i32 % 100);
2025 return 3;
2026 }
2027
2028 case MYSQL_TYPE_TIME2: {
2029 snprintf(typestr, typestr_length, "TIME(%d)", meta);
2030 if (!ptr) return my_b_printf(file, "NULL");
2031 char buf[MAX_DATE_STRING_REP_LENGTH];
2032 MYSQL_TIME ltime;
2033 longlong packed = my_time_packed_from_binary(ptr, meta);
2034 TIME_from_longlong_time_packed(<ime, packed);
2035 int buflen = my_time_to_str(ltime, buf, meta);
2036 my_b_write_quoted(file, (uchar *)buf, buflen);
2037 return my_time_binary_length(meta);
2038 }
2039
2040 case MYSQL_TYPE_NEWDATE: {
2041 snprintf(typestr, typestr_length, "DATE");
2042 if (!ptr) return my_b_printf(file, "NULL");
2043 uint32 tmp = uint3korr(ptr);
2044 int part;
2045 char buf[11];
2046 char *pos = &buf[10]; // start from '\0' to the beginning
2047
2048 /* Copied from field.cc */
2049 *pos-- = 0; // End NULL
2050 part = (int)(tmp & 31);
2051 *pos-- = (char)('0' + part % 10);
2052 *pos-- = (char)('0' + part / 10);
2053 *pos-- = ':';
2054 part = (int)(tmp >> 5 & 15);
2055 *pos-- = (char)('0' + part % 10);
2056 *pos-- = (char)('0' + part / 10);
2057 *pos-- = ':';
2058 part = (int)(tmp >> 9);
2059 *pos-- = (char)('0' + part % 10);
2060 part /= 10;
2061 *pos-- = (char)('0' + part % 10);
2062 part /= 10;
2063 *pos-- = (char)('0' + part % 10);
2064 part /= 10;
2065 *pos = (char)('0' + part);
2066 my_b_printf(file, "'%s'", buf);
2067 return 3;
2068 }
2069
2070 case MYSQL_TYPE_YEAR: {
2071 snprintf(typestr, typestr_length, "YEAR");
2072 if (!ptr) return my_b_printf(file, "NULL");
2073 uint32 i32 = *ptr;
2074 my_b_printf(file, "%04d", i32 + 1900);
2075 return 1;
2076 }
2077
2078 case MYSQL_TYPE_ENUM:
2079 switch (meta & 0xFF) {
2080 case 1:
2081 snprintf(typestr, typestr_length, "ENUM(1 byte)");
2082 if (!ptr) return my_b_printf(file, "NULL");
2083 my_b_printf(file, "%d", (int)*ptr);
2084 return 1;
2085 case 2: {
2086 snprintf(typestr, typestr_length, "ENUM(2 bytes)");
2087 if (!ptr) return my_b_printf(file, "NULL");
2088 int32 i32 = uint2korr(ptr);
2089 my_b_printf(file, "%d", i32);
2090 return 2;
2091 }
2092 default:
2093 my_b_printf(file, "!! Unknown ENUM packlen=%d", meta & 0xFF);
2094 return 0;
2095 }
2096 break;
2097
2098 case MYSQL_TYPE_SET:
2099 snprintf(typestr, typestr_length, "SET(%d bytes)", meta & 0xFF);
2100 if (!ptr) return my_b_printf(file, "NULL");
2101 my_b_write_bit(file, ptr, (meta & 0xFF) * 8);
2102 return meta & 0xFF;
2103
2104 case MYSQL_TYPE_BLOB:
2105 switch (meta) {
2106 case 1:
2107 snprintf(typestr, typestr_length, "TINYBLOB/TINYTEXT");
2108 if (!ptr) return my_b_printf(file, "NULL");
2109 length = *ptr;
2110 my_b_write_quoted(file, ptr + 1, length);
2111 return length + 1;
2112 case 2:
2113 snprintf(typestr, typestr_length, "BLOB/TEXT");
2114 if (!ptr) return my_b_printf(file, "NULL");
2115 length = uint2korr(ptr);
2116 my_b_write_quoted(file, ptr + 2, length);
2117 return length + 2;
2118 case 3:
2119 snprintf(typestr, typestr_length, "MEDIUMBLOB/MEDIUMTEXT");
2120 if (!ptr) return my_b_printf(file, "NULL");
2121 length = uint3korr(ptr);
2122 my_b_write_quoted(file, ptr + 3, length);
2123 return length + 3;
2124 case 4:
2125 snprintf(typestr, typestr_length, "LONGBLOB/LONGTEXT");
2126 if (!ptr) return my_b_printf(file, "NULL");
2127 length = uint4korr(ptr);
2128 my_b_write_quoted(file, ptr + 4, length);
2129 return length + 4;
2130 default:
2131 my_b_printf(file, "!! Unknown BLOB packlen=%d", length);
2132 return 0;
2133 }
2134
2135 case MYSQL_TYPE_VARCHAR:
2136 case MYSQL_TYPE_VAR_STRING:
2137 length = meta;
2138 snprintf(typestr, typestr_length, "VARSTRING(%d)", length);
2139 if (!ptr) return my_b_printf(file, "NULL");
2140 return my_b_write_quoted_with_length(file, ptr, length);
2141
2142 case MYSQL_TYPE_STRING:
2143 snprintf(typestr, typestr_length, "STRING(%d)", length);
2144 if (!ptr) return my_b_printf(file, "NULL");
2145 return my_b_write_quoted_with_length(file, ptr, length);
2146
2147 case MYSQL_TYPE_JSON: {
2148 snprintf(typestr, typestr_length, "JSON");
2149 if (!ptr) return my_b_printf(file, "NULL");
2150 length = uint4korr(ptr);
2151 ptr += 4;
2152 if (is_partial) {
2153 const char *error = print_json_diff(file, ptr, length, col_name);
2154 if (error != nullptr)
2155 my_b_printf(file, "Error %s while printing JSON diff\n", error);
2156 } else {
2157 json_binary::Value value =
2158 json_binary::parse_binary((const char *)ptr, length);
2159 if (value.type() == json_binary::Value::ERROR) {
2160 if (my_b_printf(
2161 file,
2162 "Invalid JSON\n")) /* purecov: inspected */ // corrupted
2163 // event
2164 return 0; /* purecov: inspected */ // error writing output
2165 } else {
2166 Json_wrapper wrapper(value);
2167 StringBuffer<STRING_BUFFER_USUAL_SIZE> s;
2168 if (json_wrapper_to_string(file, &s, &wrapper, true))
2169 my_b_printf(file, "Failed to format JSON object as string.\n");
2170 /* purecov: inspected */ // OOM
2171 }
2172 }
2173 return length + meta;
2174 }
2175 default: {
2176 char tmp[5];
2177 snprintf(tmp, sizeof(tmp), "%04x", meta);
2178 my_b_printf(file,
2179 "!! Don't know how to handle column type=%d meta=%d (%s)\n",
2180 type, meta, tmp);
2181 } break;
2182 }
2183 *typestr = 0;
2184 return 0;
2185 }
2186 #endif
2187
2188 /**
2189 Print a packed row into IO cache
2190
2191 @param[in] file IO cache
2192 @param[in] td Table definition
2193 @param[in] print_event_info Print parameters
2194 @param[in] cols_bitmap Column bitmaps.
2195 @param[in] value Pointer to packed row
2196 @param[in] prefix Row's SQL clause ("SET", "WHERE", etc)
2197
2198 @retval - number of bytes scanned.
2199 */
2200
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,enum_row_image_type row_image_type)2201 size_t Rows_log_event::print_verbose_one_row(
2202 IO_CACHE *file, table_def *td, PRINT_EVENT_INFO *print_event_info,
2203 MY_BITMAP *cols_bitmap, const uchar *value, const uchar *prefix,
2204 enum_row_image_type row_image_type) {
2205 const uchar *value0 = value;
2206 char typestr[64] = "";
2207
2208 // Read value_options if this is AI for PARTIAL_UPDATE_ROWS_EVENT
2209 ulonglong value_options = 0;
2210 Bit_reader partial_bits;
2211 if (get_type_code() == binary_log::PARTIAL_UPDATE_ROWS_EVENT &&
2212 row_image_type == enum_row_image_type::UPDATE_AI) {
2213 size_t length = m_rows_end - value;
2214 if (net_field_length_checked<ulonglong>(&value, &length, &value_options)) {
2215 my_b_printf(file,
2216 "*** Error reading binlog_row_value_options from "
2217 "Partial_update_rows_log_event\n");
2218 return 0;
2219 }
2220 if ((value_options & PARTIAL_JSON_UPDATES) != 0) {
2221 partial_bits.set_ptr(value);
2222 value += (td->json_column_count() + 7) / 8;
2223 }
2224 }
2225
2226 /*
2227 Metadata bytes which gives the information about nullabity of
2228 master columns. Master writes one bit for each column in the
2229 image.
2230 */
2231 Bit_reader null_bits(value);
2232 value += (bitmap_bits_set(cols_bitmap) + 7) / 8;
2233
2234 my_b_printf(file, "%s", prefix);
2235
2236 for (size_t i = 0; i < td->size(); i++) {
2237 /*
2238 Note: need to read partial bit before reading cols_bitmap, since
2239 the partial_bits bitmap has a bit for every JSON column
2240 regardless of whether it is included in the bitmap or not.
2241 */
2242 bool is_partial = (value_options & PARTIAL_JSON_UPDATES) != 0 &&
2243 row_image_type == enum_row_image_type::UPDATE_AI &&
2244 td->type(i) == MYSQL_TYPE_JSON && partial_bits.get();
2245
2246 if (bitmap_is_set(cols_bitmap, i) == 0) continue;
2247
2248 bool is_null = null_bits.get();
2249
2250 my_b_printf(file, "### @%d=", static_cast<int>(i + 1));
2251 if (!is_null) {
2252 size_t fsize =
2253 td->calc_field_size((uint)i, pointer_cast<const uchar *>(value));
2254 if (fsize > (size_t)(m_rows_end - value)) {
2255 my_b_printf(file,
2256 "***Corrupted replication event was detected: "
2257 "field size is set to %u, but there are only %u bytes "
2258 "left of the event. Not printing the value***\n",
2259 (uint)fsize, (uint)(m_rows_end - value));
2260 return 0;
2261 }
2262 }
2263 char col_name[256];
2264 sprintf(col_name, "@%lu", (unsigned long)i + 1);
2265 size_t size = log_event_print_value(
2266 file, is_null ? nullptr : value, td->type(i), td->field_metadata(i),
2267 typestr, sizeof(typestr), col_name, is_partial);
2268 if (!size) return 0;
2269
2270 if (!is_null) value += size;
2271
2272 if (print_event_info->verbose > 1) {
2273 my_b_printf(file, " /* ");
2274
2275 my_b_printf(file, "%s ", typestr);
2276
2277 my_b_printf(file, "meta=%d nullable=%d is_null=%d ",
2278 td->field_metadata(i), td->maybe_null(i), is_null);
2279 my_b_printf(file, "*/");
2280 }
2281
2282 my_b_printf(file, "\n");
2283 }
2284 return value - value0;
2285 }
2286
2287 /**
2288 Print a row event into IO cache in human readable form (in SQL format)
2289
2290 @param[in] file IO cache
2291 @param[in] print_event_info Print parameters
2292 */
print_verbose(IO_CACHE * file,PRINT_EVENT_INFO * print_event_info)2293 void Rows_log_event::print_verbose(IO_CACHE *file,
2294 PRINT_EVENT_INFO *print_event_info) {
2295 // Quoted length of the identifier can be twice the original length
2296 char quoted_db[1 + NAME_LEN * 2 + 2];
2297 char quoted_table[1 + NAME_LEN * 2 + 2];
2298 size_t quoted_db_len, quoted_table_len;
2299 Table_map_log_event *map;
2300 table_def *td;
2301 const char *sql_command, *sql_clause1, *sql_clause2;
2302 Log_event_type general_type_code = get_general_type_code();
2303
2304 enum_row_image_type row_image_type =
2305 get_general_type_code() == binary_log::WRITE_ROWS_EVENT
2306 ? enum_row_image_type::WRITE_AI
2307 : get_general_type_code() == binary_log::DELETE_ROWS_EVENT
2308 ? enum_row_image_type::DELETE_BI
2309 : enum_row_image_type::UPDATE_BI;
2310
2311 if (m_extra_row_info.have_ndb_info() ||
2312 DBUG_EVALUATE_IF("simulate_error_in_ndb_info_print", 1, 0)) {
2313 int extra_row_ndb_info_payload_len =
2314 m_extra_row_info.get_ndb_length() - EXTRA_ROW_INFO_HEADER_LENGTH;
2315
2316 if (m_extra_row_info.get_ndb_length() < EXTRA_ROW_INFO_HEADER_LENGTH) {
2317 my_b_printf(file,
2318 "***Error: The number of extra_row_ndb_info is smaller"
2319 " than the minimum acceptable value.\n");
2320 return;
2321 }
2322 unsigned char *ndb_info = m_extra_row_info.get_ndb_info();
2323 my_b_printf(file, "### Extra row ndb info: data_format: %u, len: %u, ",
2324 ndb_info[EXTRA_ROW_INFO_FORMAT_OFFSET],
2325 extra_row_ndb_info_payload_len);
2326 /*
2327 Buffer for hex view of string, including '0x' prefix,
2328 2 hex chars / byte and trailing 0
2329 */
2330 const int buff_len = 2 + (256 * 2) + 1;
2331 char buff[buff_len];
2332 str_to_hex(buff, (const char *)&(ndb_info[EXTRA_ROW_INFO_HEADER_LENGTH]),
2333 extra_row_ndb_info_payload_len);
2334 my_b_printf(file, "data: %s\n", buff);
2335 }
2336
2337 if (m_extra_row_info.have_part()) {
2338 if (general_type_code == binary_log::UPDATE_ROWS_EVENT) {
2339 my_b_printf(file,
2340 "### Extra row info for partitioning: source_partition: %d"
2341 " target_partition: %d",
2342 m_extra_row_info.get_source_partition_id(),
2343 m_extra_row_info.get_partition_id());
2344 } else
2345 my_b_printf(file, "### Extra row info for partitioning: partition: %u",
2346 m_extra_row_info.get_partition_id());
2347 my_b_printf(file, "\n");
2348 }
2349
2350 switch (general_type_code) {
2351 case binary_log::WRITE_ROWS_EVENT:
2352 sql_command = "INSERT INTO";
2353 sql_clause1 = "### SET\n";
2354 sql_clause2 = nullptr;
2355 break;
2356 case binary_log::DELETE_ROWS_EVENT:
2357 sql_command = "DELETE FROM";
2358 sql_clause1 = "### WHERE\n";
2359 sql_clause2 = nullptr;
2360 break;
2361 case binary_log::UPDATE_ROWS_EVENT:
2362 case binary_log::PARTIAL_UPDATE_ROWS_EVENT:
2363 sql_command = "UPDATE";
2364 sql_clause1 = "### WHERE\n";
2365 sql_clause2 = "### SET\n";
2366 break;
2367 default:
2368 sql_command = sql_clause1 = sql_clause2 = nullptr;
2369 DBUG_ASSERT(0); /* Not possible */
2370 }
2371
2372 if (!(map = print_event_info->m_table_map.get_table(m_table_id)) ||
2373 !(td = map->create_table_def())) {
2374 char llbuff[22];
2375 my_b_printf(file, "### Row event for unknown table #%s",
2376 llstr(m_table_id, llbuff));
2377 return;
2378 }
2379
2380 /* If the write rows event contained no values for the AI */
2381 if (((general_type_code == binary_log::WRITE_ROWS_EVENT) &&
2382 (m_rows_buf == m_rows_end))) {
2383 my_b_printf(file, "### INSERT INTO `%s`.`%s` VALUES ()\n",
2384 map->get_db_name(), map->get_table_name());
2385 goto end;
2386 }
2387
2388 for (const uchar *value = m_rows_buf; value < m_rows_end;) {
2389 size_t length;
2390 quoted_db_len =
2391 my_strmov_quoted_identifier((char *)quoted_db, map->get_db_name());
2392 quoted_table_len = my_strmov_quoted_identifier((char *)quoted_table,
2393 map->get_table_name());
2394 quoted_db[quoted_db_len] = '\0';
2395 quoted_table[quoted_table_len] = '\0';
2396 my_b_printf(file, "### %s %s.%s\n", sql_command, quoted_db, quoted_table);
2397 /* Print the first image */
2398 if (!(length = print_verbose_one_row(file, td, print_event_info, &m_cols,
2399 value, (const uchar *)sql_clause1,
2400 row_image_type)))
2401 goto end;
2402 value += length;
2403
2404 /* Print the second image (for UPDATE only) */
2405 if (sql_clause2) {
2406 if (!(length = print_verbose_one_row(
2407 file, td, print_event_info, &m_cols_ai, value,
2408 (const uchar *)sql_clause2, enum_row_image_type::UPDATE_AI)))
2409 goto end;
2410 value += length;
2411 }
2412 }
2413
2414 end:
2415 delete td;
2416 }
2417
print_base64(IO_CACHE * file,PRINT_EVENT_INFO * print_event_info,bool more) const2418 void Log_event::print_base64(IO_CACHE *file, PRINT_EVENT_INFO *print_event_info,
2419 bool more) const {
2420 const uchar *ptr = (const uchar *)temp_buf;
2421 uint32 size = uint4korr(ptr + EVENT_LEN_OFFSET);
2422 DBUG_TRACE;
2423
2424 uint64 const tmp_str_sz = base64_needed_encoded_length((uint64)size);
2425 char *const tmp_str =
2426 (char *)my_malloc(key_memory_log_event, tmp_str_sz, MYF(MY_WME));
2427 if (!tmp_str) {
2428 fprintf(stderr,
2429 "\nError: Out of memory. "
2430 "Could not print correct binlog event.\n");
2431 return;
2432 }
2433
2434 if (base64_encode(ptr, (size_t)size, tmp_str)) {
2435 DBUG_ASSERT(0);
2436 }
2437
2438 if (print_event_info->base64_output_mode != BASE64_OUTPUT_DECODE_ROWS) {
2439 if (my_b_tell(file) == 0) my_b_printf(file, "\nBINLOG '\n");
2440
2441 my_b_printf(file, "%s\n", tmp_str);
2442
2443 if (!more) my_b_printf(file, "'%s\n", print_event_info->delimiter);
2444 }
2445
2446 if (print_event_info->verbose) {
2447 Rows_log_event *ev = nullptr;
2448 Log_event_type et = (Log_event_type)ptr[EVENT_TYPE_OFFSET];
2449
2450 enum_binlog_checksum_alg ev_checksum_alg = common_footer->checksum_alg;
2451 Format_description_event fd_evt =
2452 Format_description_event(BINLOG_VERSION, server_version);
2453 fd_evt.footer()->checksum_alg = ev_checksum_alg;
2454
2455 switch (et) {
2456 case binary_log::TABLE_MAP_EVENT: {
2457 Table_map_log_event *map;
2458 map = new Table_map_log_event((const char *)ptr, &fd_evt);
2459 print_event_info->m_table_map.set_table(map->get_table_id(), map);
2460 break;
2461 }
2462 case binary_log::WRITE_ROWS_EVENT:
2463 case binary_log::WRITE_ROWS_EVENT_V1: {
2464 ev = new Write_rows_log_event((const char *)ptr, &fd_evt);
2465 break;
2466 }
2467 case binary_log::DELETE_ROWS_EVENT:
2468 case binary_log::DELETE_ROWS_EVENT_V1: {
2469 ev = new Delete_rows_log_event((const char *)ptr, &fd_evt);
2470 break;
2471 }
2472 case binary_log::UPDATE_ROWS_EVENT:
2473 case binary_log::UPDATE_ROWS_EVENT_V1:
2474 case binary_log::PARTIAL_UPDATE_ROWS_EVENT: {
2475 ev = new Update_rows_log_event((const char *)ptr, &fd_evt);
2476 break;
2477 }
2478 default:
2479 break;
2480 }
2481
2482 if (ev) {
2483 ev->print_verbose(&print_event_info->footer_cache, print_event_info);
2484 delete ev;
2485 }
2486 }
2487
2488 my_free(tmp_str);
2489 }
2490
2491 /*
2492 Log_event::print_timestamp()
2493 */
2494
print_timestamp(IO_CACHE * file,time_t * ts) const2495 void Log_event::print_timestamp(IO_CACHE *file, time_t *ts) const {
2496 struct tm *res;
2497 /*
2498 In some Windows versions timeval.tv_sec is defined as "long",
2499 not as "time_t" and can be of a different size.
2500 Let's use a temporary time_t variable to execute localtime()
2501 with a correct argument type.
2502 */
2503 time_t ts_tmp = ts ? *ts : (ulong)common_header->when.tv_sec;
2504 DBUG_TRACE;
2505 struct tm tm_tmp;
2506 localtime_r(&ts_tmp, (res = &tm_tmp));
2507 my_b_printf(file, "%02d%02d%02d %2d:%02d:%02d", res->tm_year % 100,
2508 res->tm_mon + 1, res->tm_mday, res->tm_hour, res->tm_min,
2509 res->tm_sec);
2510 }
2511
2512 #endif /* !MYSQL_SERVER */
2513
2514 #if defined(MYSQL_SERVER)
continue_group(Relay_log_info * rli)2515 inline Log_event::enum_skip_reason Log_event::continue_group(
2516 Relay_log_info *rli) {
2517 if (rli->slave_skip_counter == 1) return Log_event::EVENT_SKIP_IGNORE;
2518 return Log_event::do_shall_skip(rli);
2519 }
2520
2521 /**
2522 @param end_group_sets_max_dbs when true the group terminal event
2523 can carry partition info, see a note below.
2524 @return true in cases the current event
2525 carries partition data,
2526 false otherwise
2527
2528 @note Some events combination may force to adjust partition info.
2529 In particular BEGIN, BEGIN_LOAD_QUERY_EVENT, COMMIT
2530 where none of the events holds partitioning data
2531 causes the sequential applying of the group through
2532 assigning OVER_MAX_DBS_IN_EVENT_MTS to mts_accessed_dbs
2533 of the group terminator (e.g COMMIT query) event.
2534 */
contains_partition_info(bool end_group_sets_max_dbs)2535 bool Log_event::contains_partition_info(bool end_group_sets_max_dbs) {
2536 bool res;
2537
2538 switch (get_type_code()) {
2539 case binary_log::TABLE_MAP_EVENT:
2540 case binary_log::EXECUTE_LOAD_QUERY_EVENT:
2541 case binary_log::TRANSACTION_PAYLOAD_EVENT:
2542 res = true;
2543
2544 break;
2545
2546 case binary_log::QUERY_EVENT: {
2547 Query_log_event *qev = static_cast<Query_log_event *>(this);
2548 if ((ends_group() && end_group_sets_max_dbs) ||
2549 (qev->is_query_prefix_match(STRING_WITH_LEN("XA COMMIT")) ||
2550 qev->is_query_prefix_match(STRING_WITH_LEN("XA ROLLBACK")))) {
2551 res = true;
2552 qev->mts_accessed_dbs = OVER_MAX_DBS_IN_EVENT_MTS;
2553 } else
2554 res = (!ends_group() && !starts_group()) ? true : false;
2555 break;
2556 }
2557 default:
2558 res = false;
2559 }
2560
2561 return res;
2562 }
2563 /*
2564 SYNOPSIS
2565 This function assigns a parent ID to the job group being scheduled in
2566 parallel. It also checks if we can schedule the new event in parallel with the
2567 previous ones being executed.
2568
2569 @param ev log event that has to be scheduled next.
2570 @param rli Pointer to coordinator's relay log info.
2571 @return true if error
2572 false otherwise
2573 */
schedule_next_event(Log_event * ev,Relay_log_info * rli)2574 static bool schedule_next_event(Log_event *ev, Relay_log_info *rli) {
2575 int error;
2576 // Check if we can schedule this event
2577 error = rli->current_mts_submode->schedule_next_event(rli, ev);
2578 switch (error) {
2579 char llbuff[22];
2580 case ER_MTS_CANT_PARALLEL:
2581 llstr(rli->get_event_relay_log_pos(), llbuff);
2582 my_error(ER_MTS_CANT_PARALLEL, MYF(0), ev->get_type_str(),
2583 rli->get_event_relay_log_name(), llbuff,
2584 "The master event is logically timestamped incorrectly.");
2585 return true;
2586 case ER_MTS_INCONSISTENT_DATA:
2587 llstr(rli->get_event_relay_log_pos(), llbuff);
2588 {
2589 char errfmt[] =
2590 "Coordinator experienced an error or was killed while scheduling "
2591 "an event at relay-log name %s position %s.";
2592 char errbuf[sizeof(errfmt) + FN_REFLEN + sizeof(llbuff)];
2593 sprintf(errbuf, errfmt, rli->get_event_relay_log_name(), llbuff);
2594 my_error(ER_MTS_INCONSISTENT_DATA, MYF(0), errbuf);
2595 return true;
2596 }
2597 /* Don't have to do anything. */
2598 return true;
2599 case -1:
2600 /* Unable to schedule: wait_for_last_committed_trx has failed */
2601 return true;
2602 default:
2603 return false;
2604 }
2605 /* Keep compiler happy */
2606 return false;
2607 }
2608
2609 /**
2610 The method maps the event to a Worker and return a pointer to it.
2611 Sending the event to the Worker is done by the caller.
2612
2613 Irrespective of the type of Group marking (DB partioned or BGC) the
2614 following holds true:
2615
2616 - recognize the beginning of a group to allocate the group descriptor
2617 and queue it;
2618 - associate an event with a Worker (which also handles possible conflicts
2619 detection and waiting for their termination);
2620 - finalize the group assignement when the group closing event is met.
2621
2622 When parallelization mode is BGC-based the partitioning info in the event
2623 is simply ignored. Thereby association with a Worker does not require
2624 Assigned Partition Hash of the partitioned method.
2625 This method is not interested in all the taxonomy of the event group
2626 property, what we care about is the boundaries of the group.
2627
2628 As a part of the group, an event belongs to one of the following types:
2629
2630 B - beginning of a group of events (BEGIN query_log_event)
2631 g - mini-group representative event containing the partition info
2632 (any Table_map, a Query_log_event)
2633 p - a mini-group internal event that *p*receeding its g-parent
2634 (int_, rand_, user_ var:s)
2635 r - a mini-group internal "regular" event that follows its g-parent
2636 (Delete, Update, Write -rows)
2637 T - terminator of the group (XID, COMMIT, ROLLBACK, auto-commit query)
2638
2639 Only the first g-event computes the assigned Worker which once
2640 is determined remains to be for the rest of the group.
2641 That is the g-event solely carries partitioning info.
2642 For B-event the assigned Worker is NULL to indicate Coordinator
2643 has not yet decided. The same applies to p-event.
2644
2645 Notice, these is a special group consisting of optionally multiple p-events
2646 terminating with a g-event.
2647 Such case is caused by old master binlog and a few corner-cases of
2648 the current master version (todo: to fix).
2649
2650 In case of the event accesses more than OVER_MAX_DBS the method
2651 has to ensure sure previously assigned groups to all other workers are
2652 done.
2653
2654
2655 @note The function updates GAQ queue directly, updates APH hash
2656 plus relocates some temporary tables from Coordinator's list into
2657 involved entries of APH through @c map_db_to_worker.
2658 There's few memory allocations commented where to be freed.
2659
2660 @return a pointer to the Worker struct or NULL.
2661 */
2662
get_slave_worker(Relay_log_info * rli)2663 Slave_worker *Log_event::get_slave_worker(Relay_log_info *rli) {
2664 Slave_job_group group = Slave_job_group(), *ptr_group = nullptr;
2665 bool is_s_event;
2666 Slave_worker *ret_worker = nullptr;
2667 char llbuff[22];
2668 Slave_committed_queue *gaq = rli->gaq;
2669 DBUG_TRACE;
2670
2671 /* checking partioning properties and perform corresponding actions */
2672
2673 // Beginning of a group designated explicitly with BEGIN or GTID
2674 if ((is_s_event = starts_group()) || is_gtid_event(this) ||
2675 // or DDL:s or autocommit queries possibly associated with own p-events
2676 (!rli->curr_group_seen_begin && !rli->curr_group_seen_gtid &&
2677 /*
2678 the following is a special case of B-free still multi-event group like
2679 { p_1,p_2,...,p_k, g }.
2680 In that case either GAQ is empty (the very first group is being
2681 assigned) or the last assigned group index points at one of
2682 mapped-to-a-worker.
2683 */
2684 (gaq->empty() ||
2685 gaq->get_job_group(rli->gaq->assigned_group_index)->worker_id !=
2686 MTS_WORKER_UNDEF))) {
2687 if (!rli->curr_group_seen_gtid && !rli->curr_group_seen_begin) {
2688 rli->mts_groups_assigned++;
2689
2690 rli->curr_group_isolated = false;
2691 group.reset(common_header->log_pos, rli->mts_groups_assigned);
2692 // the last occupied GAQ's array index
2693 gaq->assigned_group_index = gaq->en_queue(&group);
2694 DBUG_PRINT("info", ("gaq_idx= %ld gaq->size=%ld",
2695 gaq->assigned_group_index, gaq->size));
2696 DBUG_ASSERT(gaq->assigned_group_index != MTS_WORKER_UNDEF);
2697 DBUG_ASSERT(gaq->assigned_group_index < gaq->size);
2698 DBUG_ASSERT(gaq->get_job_group(rli->gaq->assigned_group_index)
2699 ->group_relay_log_name == nullptr);
2700 DBUG_ASSERT(rli->last_assigned_worker == nullptr ||
2701 !is_mts_db_partitioned(rli));
2702
2703 if (is_s_event || is_gtid_event(this)) {
2704 Slave_job_item job_item = {this, rli->get_event_relay_log_number(),
2705 rli->get_event_start_pos()};
2706 // B-event is appended to the Deferred Array associated with GCAP
2707 rli->curr_group_da.push_back(job_item);
2708
2709 DBUG_ASSERT(rli->curr_group_da.size() == 1);
2710
2711 if (starts_group()) {
2712 // mark the current group as started with explicit B-event
2713 rli->mts_end_group_sets_max_dbs = true;
2714 rli->curr_group_seen_begin = true;
2715 }
2716
2717 if (is_gtid_event(this)) {
2718 // mark the current group as started with explicit Gtid-event
2719 rli->curr_group_seen_gtid = true;
2720
2721 Gtid_log_event *gtid_log_ev = static_cast<Gtid_log_event *>(this);
2722 rli->started_processing(gtid_log_ev);
2723 }
2724
2725 if (schedule_next_event(this, rli)) {
2726 rli->abort_slave = true;
2727 if (is_gtid_event(this)) {
2728 rli->clear_processing_trx();
2729 }
2730 return nullptr;
2731 }
2732 return ret_worker;
2733 }
2734 } else {
2735 /*
2736 The block is a result of not making GTID event as group starter.
2737 TODO: Make GITD event as B-event that is starts_group() to
2738 return true.
2739 */
2740 Slave_job_item job_item = {this, rli->get_event_relay_log_number(),
2741 rli->get_event_relay_log_pos()};
2742
2743 // B-event is appended to the Deferred Array associated with GCAP
2744 rli->curr_group_da.push_back(job_item);
2745 rli->curr_group_seen_begin = true;
2746 rli->mts_end_group_sets_max_dbs = true;
2747 if (!rli->curr_group_seen_gtid && schedule_next_event(this, rli)) {
2748 rli->abort_slave = true;
2749 return nullptr;
2750 }
2751
2752 DBUG_ASSERT(rli->curr_group_da.size() == 2);
2753 DBUG_ASSERT(starts_group());
2754 return ret_worker;
2755 }
2756 if (schedule_next_event(this, rli)) {
2757 rli->abort_slave = true;
2758 return nullptr;
2759 }
2760 }
2761
2762 ptr_group = gaq->get_job_group(rli->gaq->assigned_group_index);
2763 if (!is_mts_db_partitioned(rli)) {
2764 /* Get least occupied worker */
2765 ret_worker = rli->current_mts_submode->get_least_occupied_worker(
2766 rli, &rli->workers, this);
2767 if (ret_worker == nullptr) {
2768 /* get_least_occupied_worker may return NULL if the thread is killed */
2769 Slave_job_item job_item = {this, rli->get_event_relay_log_number(),
2770 rli->get_event_start_pos()};
2771 rli->curr_group_da.push_back(job_item);
2772
2773 DBUG_ASSERT(thd->killed);
2774 return nullptr;
2775 }
2776 ptr_group->worker_id = ret_worker->id;
2777 } else if (contains_partition_info(rli->mts_end_group_sets_max_dbs)) {
2778 int i = 0;
2779 Mts_db_names mts_dbs;
2780
2781 get_mts_dbs(&mts_dbs, rli->rpl_filter);
2782 /*
2783 Bug 12982188 - MTS: SBR ABORTS WITH ERROR 1742 ON LOAD DATA
2784 Logging on master can create a group with no events holding
2785 the partition info.
2786 The following assert proves there's the only reason
2787 for such group.
2788 */
2789 #ifndef DBUG_OFF
2790 {
2791 bool empty_group_with_gtids = rli->curr_group_seen_begin &&
2792 rli->curr_group_seen_gtid && ends_group();
2793
2794 bool begin_load_query_event =
2795 ((rli->curr_group_da.size() == 3 && rli->curr_group_seen_gtid) ||
2796 (rli->curr_group_da.size() == 2 && !rli->curr_group_seen_gtid)) &&
2797 (rli->curr_group_da.back().data->get_type_code() ==
2798 binary_log::BEGIN_LOAD_QUERY_EVENT);
2799
2800 bool delete_file_event =
2801 ((rli->curr_group_da.size() == 4 && rli->curr_group_seen_gtid) ||
2802 (rli->curr_group_da.size() == 3 && !rli->curr_group_seen_gtid)) &&
2803 (rli->curr_group_da.back().data->get_type_code() ==
2804 binary_log::DELETE_FILE_EVENT);
2805
2806 DBUG_ASSERT((!ends_group() ||
2807 (get_type_code() == binary_log::TRANSACTION_PAYLOAD_EVENT) ||
2808 (get_type_code() == binary_log::QUERY_EVENT &&
2809 static_cast<Query_log_event *>(this)->is_query_prefix_match(
2810 STRING_WITH_LEN("XA ROLLBACK")))) ||
2811 empty_group_with_gtids ||
2812 (rli->mts_end_group_sets_max_dbs &&
2813 (begin_load_query_event || delete_file_event)));
2814 }
2815 #endif
2816
2817 // partioning info is found which drops the flag
2818 rli->mts_end_group_sets_max_dbs = false;
2819 ret_worker = rli->last_assigned_worker;
2820 if (mts_dbs.num == OVER_MAX_DBS_IN_EVENT_MTS) {
2821 // Worker with id 0 to handle serial execution
2822 if (!ret_worker) ret_worker = rli->workers.at(0);
2823 // No need to know a possible error out of synchronization call.
2824 (void)rli->current_mts_submode->wait_for_workers_to_finish(rli,
2825 ret_worker);
2826 /*
2827 this marking is transferred further into T-event of the current group.
2828 */
2829 rli->curr_group_isolated = true;
2830 }
2831 #ifndef DBUG_OFF
2832 {
2833 std::ostringstream oss;
2834 for (i = 0;
2835 i < ((mts_dbs.num != OVER_MAX_DBS_IN_EVENT_MTS) ? mts_dbs.num : 1);
2836 i++) {
2837 if (mts_dbs.name[i] != 0) {
2838 oss << mts_dbs.name[i] << ", ";
2839 }
2840 }
2841 DBUG_PRINT("debug", ("ASSIGN %p %s", current_thd, oss.str().c_str()));
2842 }
2843 #endif
2844
2845 /* One run of the loop in the case of over-max-db:s */
2846 for (i = 0;
2847 i < ((mts_dbs.num != OVER_MAX_DBS_IN_EVENT_MTS) ? mts_dbs.num : 1);
2848 i++) {
2849 /*
2850 The over max db:s case handled through passing to map_db_to_worker
2851 such "all" db as encoded as the "" empty string.
2852 Note, the empty string is allocated in a large buffer
2853 to satisfy hashcmp() implementation.
2854 */
2855 const char all_db[NAME_LEN] = {0};
2856 if (!(ret_worker = map_db_to_worker(
2857 mts_dbs.num == OVER_MAX_DBS_IN_EVENT_MTS ? all_db
2858 : mts_dbs.name[i],
2859 rli, &mts_assigned_partitions[i],
2860 /*
2861 todo: optimize it. Although pure
2862 rows- event load in insensetive to the flag value
2863 */
2864 true, ret_worker))) {
2865 llstr(rli->get_event_relay_log_pos(), llbuff);
2866 my_error(ER_MTS_CANT_PARALLEL, MYF(0), get_type_str(),
2867 rli->get_event_relay_log_name(), llbuff,
2868 "could not distribute the event to a Worker");
2869 return ret_worker;
2870 }
2871 // all temporary tables are transferred from Coordinator in over-max case
2872 DBUG_ASSERT(mts_dbs.num != OVER_MAX_DBS_IN_EVENT_MTS ||
2873 !thd->temporary_tables);
2874 DBUG_ASSERT(!strcmp(
2875 mts_assigned_partitions[i]->db,
2876 mts_dbs.num != OVER_MAX_DBS_IN_EVENT_MTS ? mts_dbs.name[i] : all_db));
2877 DBUG_ASSERT(ret_worker == mts_assigned_partitions[i]->worker);
2878 DBUG_ASSERT(mts_assigned_partitions[i]->usage >= 0);
2879 }
2880
2881 if ((ptr_group = gaq->get_job_group(rli->gaq->assigned_group_index))
2882 ->worker_id == MTS_WORKER_UNDEF) {
2883 ptr_group->worker_id = ret_worker->id;
2884
2885 DBUG_ASSERT(ptr_group->group_relay_log_name == nullptr);
2886 }
2887
2888 DBUG_ASSERT(i == mts_dbs.num || mts_dbs.num == OVER_MAX_DBS_IN_EVENT_MTS);
2889 } else {
2890 // a mini-group internal "regular" event
2891 if (rli->last_assigned_worker) {
2892 ret_worker = rli->last_assigned_worker;
2893
2894 DBUG_ASSERT(rli->curr_group_assigned_parts.size() > 0 ||
2895 ret_worker->id == 0);
2896 } else // int_, rand_, user_ var:s, load-data events
2897 {
2898 if (!(get_type_code() == binary_log::INTVAR_EVENT ||
2899 get_type_code() == binary_log::RAND_EVENT ||
2900 get_type_code() == binary_log::USER_VAR_EVENT ||
2901 get_type_code() == binary_log::BEGIN_LOAD_QUERY_EVENT ||
2902 get_type_code() == binary_log::APPEND_BLOCK_EVENT ||
2903 get_type_code() == binary_log::DELETE_FILE_EVENT ||
2904 is_ignorable_event())) {
2905 DBUG_ASSERT(!ret_worker);
2906
2907 llstr(rli->get_event_relay_log_pos(), llbuff);
2908 my_error(ER_MTS_CANT_PARALLEL, MYF(0), get_type_str(),
2909 rli->get_event_relay_log_name(), llbuff,
2910 "the event is a part of a group that is unsupported in "
2911 "the parallel execution mode");
2912
2913 return ret_worker;
2914 }
2915 /*
2916 In the logical clock scheduler any internal gets scheduled directly.
2917 That is Int_var, @User_var and Rand bypass the deferred array.
2918 Their association with relay-log physical coordinates is provided
2919 by the same mechanism that applies to a regular event.
2920 */
2921 Slave_job_item job_item = {this, rli->get_event_relay_log_number(),
2922 rli->get_event_start_pos()};
2923 rli->curr_group_da.push_back(job_item);
2924
2925 DBUG_ASSERT(!ret_worker);
2926 return ret_worker;
2927 }
2928 }
2929
2930 DBUG_ASSERT(ret_worker);
2931 // T-event: Commit, Xid, a DDL query or dml query of B-less group.4
2932
2933 /*
2934 Preparing event physical coordinates info for Worker before any
2935 event got scheduled so when Worker error-stopped at the first
2936 event it would be aware of where exactly in the event stream.
2937 */
2938 if (!ret_worker->master_log_change_notified) {
2939 if (!ptr_group)
2940 ptr_group = gaq->get_job_group(rli->gaq->assigned_group_index);
2941 ptr_group->group_master_log_name = my_strdup(
2942 key_memory_log_event, rli->get_group_master_log_name(), MYF(MY_WME));
2943 ret_worker->master_log_change_notified = true;
2944
2945 DBUG_ASSERT(!ptr_group->notified);
2946 #ifndef DBUG_OFF
2947 ptr_group->notified = true;
2948 #endif
2949 }
2950
2951 /* Notify the worker about new FD */
2952 if (!ret_worker->fd_change_notified) {
2953 if (!ptr_group)
2954 ptr_group = gaq->get_job_group(rli->gaq->assigned_group_index);
2955 /*
2956 Increment the usage counter on behalf of Worker.
2957 This avoids inadvertent FD deletion in a race case where Coordinator
2958 would install a next new FD before Worker has noticed the previous one.
2959 */
2960 ++rli->get_rli_description_event()->atomic_usage_counter;
2961 ptr_group->new_fd_event = rli->get_rli_description_event();
2962 ret_worker->fd_change_notified = true;
2963 }
2964
2965 if (ends_group() ||
2966 (!rli->curr_group_seen_begin &&
2967 (get_type_code() == binary_log::QUERY_EVENT ||
2968 /*
2969 When applying an old binary log without Gtid_log_event and
2970 Anonymous_gtid_log_event, the logic of multi-threaded slave
2971 still need to require that an event (for example, Query_log_event,
2972 User_var_log_event, Intvar_log_event, and Rand_log_event) that
2973 appeared outside of BEGIN...COMMIT was treated as a transaction
2974 of its own. This was just a technicality in the code and did not
2975 cause a problem, since the event and the following Query_log_event
2976 would both be assigned to dedicated worker 0.
2977 */
2978 !rli->curr_group_seen_gtid))) {
2979 rli->mts_group_status = Relay_log_info::MTS_END_GROUP;
2980 if (rli->curr_group_isolated) set_mts_isolate_group();
2981 if (!ptr_group)
2982 ptr_group = gaq->get_job_group(rli->gaq->assigned_group_index);
2983
2984 DBUG_ASSERT(ret_worker != nullptr);
2985
2986 // coordinator has ended buffering this group, update monitoring info
2987 if (rli->is_processing_trx()) {
2988 DBUG_EXECUTE_IF("rpl_ps_tables", {
2989 const char act[] =
2990 "now SIGNAL signal.rpl_ps_tables_process_before "
2991 "WAIT_FOR signal.rpl_ps_tables_process_finish";
2992 DBUG_ASSERT(opt_debug_sync_timeout > 0);
2993 DBUG_ASSERT(!debug_sync_set_action(current_thd, STRING_WITH_LEN(act)));
2994 };);
2995 rli->finished_processing();
2996 DBUG_EXECUTE_IF("rpl_ps_tables", {
2997 const char act[] =
2998 "now SIGNAL signal.rpl_ps_tables_process_after_finish "
2999 "WAIT_FOR signal.rpl_ps_tables_process_continue";
3000 DBUG_ASSERT(opt_debug_sync_timeout > 0);
3001 DBUG_ASSERT(!debug_sync_set_action(current_thd, STRING_WITH_LEN(act)));
3002 };);
3003 }
3004
3005 /*
3006 The following two blocks are executed if the worker has not been
3007 notified about new relay-log or a new checkpoints.
3008 Relay-log string is freed by Coordinator, Worker deallocates
3009 strings in the checkpoint block.
3010 However if the worker exits earlier reclaiming for both happens anyway at
3011 GAQ delete.
3012 */
3013 if (!ret_worker->relay_log_change_notified) {
3014 /*
3015 Prior this event, C rotated the relay log to drop each
3016 Worker's notified flag. Now group terminating event initiates
3017 the new relay-log (where the current event is from) name
3018 delivery to Worker that will receive it in commit_positions().
3019 */
3020 DBUG_ASSERT(ptr_group->group_relay_log_name == nullptr);
3021
3022 ptr_group->group_relay_log_name = (char *)my_malloc(
3023 key_memory_log_event, strlen(rli->get_group_relay_log_name()) + 1,
3024 MYF(MY_WME));
3025 strcpy(ptr_group->group_relay_log_name, rli->get_event_relay_log_name());
3026
3027 DBUG_ASSERT(ptr_group->group_relay_log_name != nullptr);
3028
3029 ret_worker->relay_log_change_notified = true;
3030 }
3031
3032 if (!ret_worker->checkpoint_notified) {
3033 if (!ptr_group)
3034 ptr_group = gaq->get_job_group(rli->gaq->assigned_group_index);
3035 ptr_group->checkpoint_log_name = my_strdup(
3036 key_memory_log_event, rli->get_group_master_log_name(), MYF(MY_WME));
3037 ptr_group->checkpoint_log_pos = rli->get_group_master_log_pos();
3038 ptr_group->checkpoint_relay_log_name = my_strdup(
3039 key_memory_log_event, rli->get_group_relay_log_name(), MYF(MY_WME));
3040 ptr_group->checkpoint_relay_log_pos = rli->get_group_relay_log_pos();
3041 ptr_group->shifted = ret_worker->bitmap_shifted;
3042 ret_worker->bitmap_shifted = 0;
3043 ret_worker->checkpoint_notified = true;
3044 }
3045 ptr_group->checkpoint_seqno = rli->rli_checkpoint_seqno;
3046 ptr_group->ts = common_header->when.tv_sec +
3047 (time_t)exec_time; // Seconds_behind_master related
3048 rli->rli_checkpoint_seqno++;
3049 /*
3050 Coordinator should not use the main memroot however its not
3051 reset elsewhere either, so let's do it safe way.
3052 The main mem root is also reset by the SQL thread in at the end
3053 of applying which Coordinator does not do in this case.
3054 That concludes the memroot reset can't harm anything in SQL thread roles
3055 after Coordinator has finished its current scheduling.
3056 */
3057 free_root(thd->mem_root, MYF(MY_KEEP_PREALLOC));
3058
3059 #ifndef DBUG_OFF
3060 w_rr++;
3061 #endif
3062 }
3063
3064 return ret_worker;
3065 }
3066
apply_gtid_event(Relay_log_info * rli)3067 int Log_event::apply_gtid_event(Relay_log_info *rli) {
3068 DBUG_TRACE;
3069
3070 int error = 0;
3071 if (rli->curr_group_da.size() < 1) return 1;
3072
3073 Log_event *ev = rli->curr_group_da[0].data;
3074 DBUG_ASSERT(ev->get_type_code() == binary_log::GTID_LOG_EVENT ||
3075 ev->get_type_code() == binary_log::ANONYMOUS_GTID_LOG_EVENT);
3076
3077 error = ev->do_apply_event(rli);
3078 /* Clean up */
3079 delete ev;
3080 rli->curr_group_da.clear();
3081 rli->curr_group_seen_gtid = false;
3082 /*
3083 Removes the job from the (G)lobal (A)ssigned (Q)ueue after
3084 applying it.
3085 */
3086 DBUG_ASSERT(rli->gaq->len > 0);
3087 Slave_job_group g = Slave_job_group();
3088 rli->gaq->de_tail(&g);
3089 /*
3090 The rli->mts_groups_assigned is increased when adding the slave job
3091 generated for the gtid into the (G)lobal (A)ssigned (Q)ueue. So we
3092 decrease it here.
3093 */
3094 rli->mts_groups_assigned--;
3095
3096 return error;
3097 }
3098
3099 /**
3100 Scheduling event to execute in parallel or execute it directly.
3101 In MTS case the event gets associated with either Coordinator or a
3102 Worker. A special case of the association is NULL when the Worker
3103 can't be decided yet. In the single threaded sequential mode the
3104 event maps to SQL thread rli.
3105
3106 @note in case of MTS failure Coordinator destroys all gathered
3107 deferred events.
3108
3109 @return 0 as success, otherwise a failure.
3110 */
apply_event(Relay_log_info * rli)3111 int Log_event::apply_event(Relay_log_info *rli) {
3112 DBUG_TRACE;
3113 DBUG_PRINT("info", ("event_type=%s", get_type_str()));
3114 bool parallel = false;
3115 enum enum_mts_event_exec_mode actual_exec_mode = EVENT_EXEC_PARALLEL;
3116 THD *rli_thd = rli->info_thd;
3117
3118 worker = rli;
3119
3120 if (rli->is_mts_recovery()) {
3121 bool skip = bitmap_is_set(&rli->recovery_groups, rli->mts_recovery_index) &&
3122 (get_mts_execution_mode(rli->mts_group_status ==
3123 Relay_log_info::MTS_IN_GROUP) ==
3124 EVENT_EXEC_PARALLEL);
3125 if (skip) {
3126 return 0;
3127 } else {
3128 int error = do_apply_event(rli);
3129 if (rli->is_processing_trx()) {
3130 // needed to identify DDL's; uses the same logic as in
3131 // get_slave_worker()
3132 if (starts_group() && get_type_code() == binary_log::QUERY_EVENT) {
3133 rli->curr_group_seen_begin = true;
3134 }
3135 if (error == 0 &&
3136 (ends_group() || (get_type_code() == binary_log::QUERY_EVENT &&
3137 !rli->curr_group_seen_begin))) {
3138 rli->finished_processing();
3139 rli->curr_group_seen_begin = false;
3140 }
3141 }
3142 return error;
3143 }
3144 }
3145
3146 if (!(parallel = rli->is_parallel_exec()) ||
3147 ((actual_exec_mode = get_mts_execution_mode(
3148 rli->mts_group_status == Relay_log_info::MTS_IN_GROUP)) !=
3149 EVENT_EXEC_PARALLEL)) {
3150 if (parallel) {
3151 /*
3152 There are two classes of events that Coordinator executes
3153 itself. One e.g the master Rotate requires all Workers to finish up
3154 their assignments. The other async class, e.g the slave Rotate,
3155 can't have this such synchronization because Worker might be waiting
3156 for terminal events to finish.
3157 */
3158
3159 if (actual_exec_mode != EVENT_EXEC_ASYNC) {
3160 /*
3161 this event does not split the current group but is indeed
3162 a separator beetwen two master's binlog therefore requiring
3163 Workers to sync.
3164 */
3165 if (rli->curr_group_da.size() > 0 && is_mts_db_partitioned(rli) &&
3166 get_type_code() != binary_log::INCIDENT_EVENT) {
3167 char llbuff[22];
3168 /*
3169 Possible reason is a old version binlog sequential event
3170 wrappped with BEGIN/COMMIT or preceeded by User|Int|Random- var.
3171 MTS has to stop to suggest restart in the permanent sequential
3172 mode.
3173 */
3174 llstr(rli->get_event_relay_log_pos(), llbuff);
3175 my_error(ER_MTS_CANT_PARALLEL, MYF(0), get_type_str(),
3176 rli->get_event_relay_log_name(), llbuff,
3177 "possible malformed group of events from an old master");
3178
3179 /* Coordinator cant continue, it marks MTS group status accordingly */
3180 rli->mts_group_status = Relay_log_info::MTS_KILLED_GROUP;
3181
3182 goto err;
3183 }
3184
3185 if (get_type_code() == binary_log::INCIDENT_EVENT &&
3186 rli->curr_group_da.size() > 0 &&
3187 rli->current_mts_submode->get_type() ==
3188 MTS_PARALLEL_TYPE_LOGICAL_CLOCK) {
3189 #ifndef DBUG_OFF
3190 DBUG_ASSERT(rli->curr_group_da.size() == 1);
3191 Log_event *ev = rli->curr_group_da[0].data;
3192 DBUG_ASSERT(ev->get_type_code() == binary_log::GTID_LOG_EVENT ||
3193 ev->get_type_code() ==
3194 binary_log::ANONYMOUS_GTID_LOG_EVENT);
3195 #endif
3196 /*
3197 With MTS logical clock mode, when coordinator is applying an
3198 incident event, it must withdraw delegated_job increased by
3199 the incident's GTID before waiting for workers to finish.
3200 So that it can exit from mts_checkpoint_routine.
3201 */
3202 ((Mts_submode_logical_clock *)rli->current_mts_submode)
3203 ->withdraw_delegated_job();
3204 }
3205 /*
3206 Marking sure the event will be executed in sequential mode.
3207 */
3208 if (rli->current_mts_submode->wait_for_workers_to_finish(rli) == -1) {
3209 // handle synchronization error
3210 rli->report(WARNING_LEVEL, 0,
3211 "Slave worker thread has failed to apply an event. As a "
3212 "consequence, the coordinator thread is stopping "
3213 "execution.");
3214 return -1;
3215 }
3216 /*
3217 Given not in-group mark the event handler can invoke checkpoint
3218 update routine in the following course.
3219 */
3220 DBUG_ASSERT(rli->mts_group_status == Relay_log_info::MTS_NOT_IN_GROUP ||
3221 !is_mts_db_partitioned(rli));
3222
3223 if (get_type_code() == binary_log::INCIDENT_EVENT &&
3224 rli->curr_group_da.size() > 0) {
3225 DBUG_ASSERT(rli->curr_group_da.size() == 1);
3226 /*
3227 When MTS is enabled, the incident event must be applied by the
3228 coordinator. So the coordinator applies its GTID right before
3229 applying the incident event..
3230 */
3231 int error = apply_gtid_event(rli);
3232 if (error) return -1;
3233 }
3234
3235 #ifndef DBUG_OFF
3236 /* all Workers are idle as done through wait_for_workers_to_finish */
3237 for (uint k = 0; k < rli->curr_group_da.size(); k++) {
3238 DBUG_ASSERT(!(rli->workers[k]->usage_partition));
3239 DBUG_ASSERT(!(rli->workers[k]->jobs.len));
3240 }
3241 #endif
3242 } else {
3243 DBUG_ASSERT(actual_exec_mode == EVENT_EXEC_ASYNC);
3244 }
3245 }
3246
3247 int error = do_apply_event(rli);
3248 if (rli->is_processing_trx()) {
3249 // needed to identify DDL's; uses the same logic as in get_slave_worker()
3250 if (starts_group() && get_type_code() == binary_log::QUERY_EVENT) {
3251 rli->curr_group_seen_begin = true;
3252 }
3253 if (error == 0 &&
3254 (ends_group() || (get_type_code() == binary_log::QUERY_EVENT &&
3255 !rli->curr_group_seen_begin))) {
3256 DBUG_EXECUTE_IF("rpl_ps_tables", {
3257 const char act[] =
3258 "now SIGNAL signal.rpl_ps_tables_apply_before "
3259 "WAIT_FOR signal.rpl_ps_tables_apply_finish";
3260 DBUG_ASSERT(opt_debug_sync_timeout > 0);
3261 DBUG_ASSERT(
3262 !debug_sync_set_action(current_thd, STRING_WITH_LEN(act)));
3263 };);
3264 rli->finished_processing();
3265 rli->curr_group_seen_begin = false;
3266 DBUG_EXECUTE_IF("rpl_ps_tables", {
3267 const char act[] =
3268 "now SIGNAL signal.rpl_ps_tables_apply_after_finish "
3269 "WAIT_FOR signal.rpl_ps_tables_apply_continue";
3270 DBUG_ASSERT(opt_debug_sync_timeout > 0);
3271 DBUG_ASSERT(
3272 !debug_sync_set_action(current_thd, STRING_WITH_LEN(act)));
3273 };);
3274 }
3275 }
3276 return error;
3277 }
3278
3279 DBUG_ASSERT(actual_exec_mode == EVENT_EXEC_PARALLEL);
3280 DBUG_ASSERT(!(rli->curr_group_seen_begin && ends_group()) ||
3281 /*
3282 This is an empty group being processed due to gtids.
3283 */
3284 (rli->curr_group_seen_begin && rli->curr_group_seen_gtid &&
3285 ends_group()) ||
3286 is_mts_db_partitioned(rli) || rli->last_assigned_worker ||
3287 /*
3288 Begin_load_query can be logged w/o db info and within
3289 Begin/Commit. That's a pattern forcing sequential
3290 applying of LOAD-DATA.
3291 */
3292 (rli->curr_group_da.back().data->get_type_code() ==
3293 binary_log::BEGIN_LOAD_QUERY_EVENT) ||
3294 /*
3295 Delete_file can also be logged w/o db info and within
3296 Begin/Commit. That's a pattern forcing sequential
3297 applying of LOAD-DATA.
3298 */
3299 (rli->curr_group_da.back().data->get_type_code() ==
3300 binary_log::DELETE_FILE_EVENT));
3301
3302 worker = nullptr;
3303 rli->mts_group_status = Relay_log_info::MTS_IN_GROUP;
3304
3305 worker =
3306 (Relay_log_info *)(rli->last_assigned_worker = get_slave_worker(rli));
3307
3308 #ifndef DBUG_OFF
3309 if (rli->last_assigned_worker)
3310 DBUG_PRINT("mts",
3311 ("Assigning job to worker %lu", rli->last_assigned_worker->id));
3312 #endif
3313
3314 err:
3315 if (rli_thd->is_error() || (!worker && rli->abort_slave)) {
3316 DBUG_ASSERT(!worker);
3317
3318 /*
3319 Destroy all deferred buffered events but the current prior to exit.
3320 The current one will be deleted as an event never destined/assigned
3321 to any Worker in Coordinator's regular execution path.
3322 */
3323 for (uint k = 0; k < rli->curr_group_da.size(); k++) {
3324 Log_event *ev_buf = rli->curr_group_da[k].data;
3325 if (this != ev_buf) delete ev_buf;
3326 }
3327 rli->curr_group_da.clear();
3328 } else {
3329 DBUG_ASSERT(worker || rli->curr_group_assigned_parts.size() == 0);
3330 }
3331
3332 return (!(rli_thd->is_error() || (!worker && rli->abort_slave)) ||
3333 DBUG_EVALUATE_IF("fault_injection_get_slave_worker", 1, 0))
3334 ? 0
3335 : -1;
3336 }
3337
3338 /**************************************************************************
3339 Query_log_event methods
3340 **************************************************************************/
3341
3342 /**
3343 This (which is used only for SHOW BINLOG EVENTS) could be updated to
3344 print SET @@session_var=. But this is not urgent, as SHOW BINLOG EVENTS is
3345 only an information, it does not produce suitable queries to replay (for
3346 example it does not print LOAD DATA INFILE).
3347 @todo
3348 show the catalog ??
3349 */
3350
pack_info(Protocol * protocol)3351 int Query_log_event::pack_info(Protocol *protocol) {
3352 // TODO: show the catalog ??
3353 String str_buf;
3354 // Add use `DB` to the string if required
3355 if (!(common_header->flags & LOG_EVENT_SUPPRESS_USE_F) && db && db_len) {
3356 str_buf.append("use ");
3357 append_identifier(this->thd, &str_buf, db, db_len);
3358 str_buf.append("; ");
3359 }
3360 // Add the query to the string
3361 if (query && q_len) {
3362 str_buf.append(query);
3363 if (ddl_xid != binary_log::INVALID_XID) {
3364 char xid_buf[64];
3365 str_buf.append(" /* xid=");
3366 longlong10_to_str(ddl_xid, xid_buf, 10);
3367 str_buf.append(xid_buf);
3368 str_buf.append(" */");
3369 }
3370 }
3371 // persist the buffer in protocol
3372 protocol->store_string(str_buf.ptr(), str_buf.length(), &my_charset_bin);
3373 return 0;
3374 }
3375
3376 /**
3377 Utility function for the next method (Query_log_event::write()) .
3378 */
write_str_with_code_and_len(uchar ** dst,const char * src,size_t len,uint code)3379 static void write_str_with_code_and_len(uchar **dst, const char *src,
3380 size_t len, uint code) {
3381 /*
3382 only 1 byte to store the length of catalog, so it should not
3383 surpass 255
3384 */
3385 DBUG_ASSERT(len <= 255);
3386 DBUG_ASSERT(src);
3387 *((*dst)++) = code;
3388 *((*dst)++) = (uchar)len;
3389 memmove(*dst, src, len);
3390 (*dst) += len;
3391 }
3392
3393 /**
3394 Query_log_event::write().
3395
3396 @note
3397 In this event we have to modify the header to have the correct
3398 EVENT_LEN_OFFSET as we don't yet know how many status variables we
3399 will print!
3400 */
3401
write(Basic_ostream * ostream)3402 bool Query_log_event::write(Basic_ostream *ostream) {
3403 uchar buf[Binary_log_event::QUERY_HEADER_LEN + MAX_SIZE_LOG_EVENT_STATUS];
3404 uchar *start, *start_of_status;
3405 size_t event_length;
3406
3407 if (!query) return true; // Something wrong with event
3408
3409 /*
3410 We want to store the thread id:
3411 (- as an information for the user when he reads the binlog)
3412 - if the query uses temporary table: for the slave SQL thread to know to
3413 which master connection the temp table belongs.
3414 Now imagine we (write()) are called by the slave SQL thread (we are
3415 logging a query executed by this thread; the slave runs with
3416 --log-slave-updates). Then this query will be logged with
3417 thread_id=the_thread_id_of_the_SQL_thread. Imagine that 2 temp tables of
3418 the same name were created simultaneously on the master (in the masters
3419 binlog you have
3420 CREATE TEMPORARY TABLE t; (thread 1)
3421 CREATE TEMPORARY TABLE t; (thread 2)
3422 ...)
3423 then in the slave's binlog there will be
3424 CREATE TEMPORARY TABLE t; (thread_id_of_the_slave_SQL_thread)
3425 CREATE TEMPORARY TABLE t; (thread_id_of_the_slave_SQL_thread)
3426 which is bad (same thread id!).
3427
3428 To avoid this, we log the thread's thread id EXCEPT for the SQL
3429 slave thread for which we log the original (master's) thread id.
3430 Now this moves the bug: what happens if the thread id on the
3431 master was 10 and when the slave replicates the query, a
3432 connection number 10 is opened by a normal client on the slave,
3433 and updates a temp table of the same name? We get a problem
3434 again. To avoid this, in the handling of temp tables (sql_base.cc)
3435 we use thread_id AND server_id. TODO when this is merged into
3436 4.1: in 4.1, slave_proxy_id has been renamed to pseudo_thread_id
3437 and is a session variable: that's to make mysqlbinlog work with
3438 temp tables. We probably need to introduce
3439
3440 SET PSEUDO_SERVER_ID
3441 for mysqlbinlog in 4.1. mysqlbinlog would print:
3442 SET PSEUDO_SERVER_ID=
3443 SET PSEUDO_THREAD_ID=
3444 for each query using temp tables.
3445 */
3446 int4store(buf + Q_THREAD_ID_OFFSET, slave_proxy_id);
3447 int4store(buf + Q_EXEC_TIME_OFFSET, exec_time);
3448 buf[Q_DB_LEN_OFFSET] = (char)db_len;
3449 int2store(buf + Q_ERR_CODE_OFFSET, error_code);
3450
3451 /*
3452 You MUST always write status vars in increasing order of code. This
3453 guarantees that a slightly older slave will be able to parse those he
3454 knows.
3455 */
3456 start_of_status = start = buf + Binary_log_event::QUERY_HEADER_LEN;
3457 if (flags2_inited) {
3458 *start++ = Q_FLAGS2_CODE;
3459 int4store(start, flags2);
3460 start += 4;
3461 }
3462 if (sql_mode_inited) {
3463 *start++ = Q_SQL_MODE_CODE;
3464 int8store(start, sql_mode);
3465 start += 8;
3466 }
3467 if (catalog_len) // i.e. this var is inited (false for 4.0 events)
3468 {
3469 write_str_with_code_and_len(&start, catalog, catalog_len,
3470 Q_CATALOG_NZ_CODE);
3471 /*
3472 In 5.0.x where x<4 masters we used to store the end zero here. This was
3473 a waste of one byte so we don't do it in x>=4 masters. We change code to
3474 Q_CATALOG_NZ_CODE, because re-using the old code would make x<4 slaves
3475 of this x>=4 master segfault (expecting a zero when there is
3476 none). Remaining compatibility problems are: the older slave will not
3477 find the catalog; but it is will not crash, and it's not an issue
3478 that it does not find the catalog as catalogs were not used in these
3479 older MySQL versions (we store it in binlog and read it from relay log
3480 but do nothing useful with it). What is an issue is that the older slave
3481 will stop processing the Q_* blocks (and jumps to the db/query) as soon
3482 as it sees unknown Q_CATALOG_NZ_CODE; so it will not be able to read
3483 Q_AUTO_INCREMENT*, Q_CHARSET and so replication will fail silently in
3484 various ways. Documented that you should not mix alpha/beta versions if
3485 they are not exactly the same version, with example of 5.0.3->5.0.2 and
3486 5.0.4->5.0.3. If replication is from older to new, the new will
3487 recognize Q_CATALOG_CODE and have no problem.
3488 */
3489 }
3490 if (auto_increment_increment != 1 || auto_increment_offset != 1) {
3491 *start++ = Q_AUTO_INCREMENT;
3492 int2store(start, static_cast<uint16>(auto_increment_increment));
3493 int2store(start + 2, static_cast<uint16>(auto_increment_offset));
3494 start += 4;
3495 }
3496 if (charset_inited) {
3497 *start++ = Q_CHARSET_CODE;
3498 memcpy(start, charset, 6);
3499 start += 6;
3500 }
3501 if (time_zone_len) {
3502 /* In the TZ sys table, column Name is of length 64 so this should be ok */
3503 DBUG_ASSERT(time_zone_len <= MAX_TIME_ZONE_NAME_LENGTH);
3504 write_str_with_code_and_len(&start, time_zone_str, time_zone_len,
3505 Q_TIME_ZONE_CODE);
3506 }
3507 if (lc_time_names_number) {
3508 DBUG_ASSERT(lc_time_names_number <= 0xFF);
3509 *start++ = Q_LC_TIME_NAMES_CODE;
3510 int2store(start, lc_time_names_number);
3511 start += 2;
3512 }
3513 if (charset_database_number) {
3514 *start++ = Q_CHARSET_DATABASE_CODE;
3515 int2store(start, charset_database_number);
3516 start += 2;
3517 }
3518 if (table_map_for_update) {
3519 *start++ = Q_TABLE_MAP_FOR_UPDATE_CODE;
3520 int8store(start, table_map_for_update);
3521 start += 8;
3522 }
3523
3524 if (thd && thd->need_binlog_invoker()) {
3525 LEX_CSTRING invoker_user{nullptr, 0};
3526 LEX_CSTRING invoker_host{nullptr, 0};
3527 memset(&invoker_user, 0, sizeof(invoker_user));
3528 memset(&invoker_host, 0, sizeof(invoker_host));
3529
3530 if (thd->slave_thread && thd->has_invoker()) {
3531 /* user will be null, if master is older than this patch */
3532 invoker_user = thd->get_invoker_user();
3533 invoker_host = thd->get_invoker_host();
3534 } else {
3535 Security_context *ctx = thd->security_context();
3536 LEX_CSTRING priv_user = ctx->priv_user();
3537 LEX_CSTRING priv_host = ctx->priv_host();
3538
3539 invoker_user.length = priv_user.length;
3540 invoker_user.str = priv_user.str;
3541 if (priv_host.str[0] != '\0') {
3542 invoker_host.str = priv_host.str;
3543 invoker_host.length = priv_host.length;
3544 }
3545 }
3546
3547 *start++ = Q_INVOKER;
3548
3549 DBUG_EXECUTE_IF("wl12571_long_invoker_host", {
3550 invoker_host.str =
3551 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
3552 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
3553 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
3554 "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";
3555 invoker_host.length = strlen(invoker_host.str);
3556 });
3557
3558 /*
3559 Store user length and user. The max length of use is 16, so 1 byte is
3560 enough to store the user's length.
3561 */
3562 *start++ = (uchar)invoker_user.length;
3563 memcpy(start, invoker_user.str, invoker_user.length);
3564 start += invoker_user.length;
3565
3566 /*
3567 Store host length and host. The max length of host is 255, so 1 byte
3568 is enough to store the host's length.
3569 */
3570 *start++ = (uchar)invoker_host.length;
3571 if (invoker_host.length > 0)
3572 memcpy(start, invoker_host.str, invoker_host.length);
3573 start += invoker_host.length;
3574 }
3575
3576 if (thd && thd->get_binlog_accessed_db_names() != nullptr) {
3577 uchar dbs;
3578 *start++ = Q_UPDATED_DB_NAMES;
3579
3580 static_assert(MAX_DBS_IN_EVENT_MTS <= OVER_MAX_DBS_IN_EVENT_MTS, "");
3581
3582 /*
3583 In case of the number of db:s exceeds MAX_DBS_IN_EVENT_MTS
3584 no db:s is written and event will require the sequential applying on
3585 slave.
3586 */
3587 dbs =
3588 (thd->get_binlog_accessed_db_names()->elements <= MAX_DBS_IN_EVENT_MTS)
3589 ? thd->get_binlog_accessed_db_names()->elements
3590 : OVER_MAX_DBS_IN_EVENT_MTS;
3591
3592 DBUG_ASSERT(dbs != 0);
3593
3594 if (dbs <= MAX_DBS_IN_EVENT_MTS) {
3595 List_iterator_fast<char> it(*thd->get_binlog_accessed_db_names());
3596 char *db_name = it++;
3597 /*
3598 the single "" db in the acccessed db list corresponds to the same as
3599 exceeds MAX_DBS_IN_EVENT_MTS case, so dbs is set to the over-max.
3600 */
3601 if (dbs == 1 && !strcmp(db_name, "")) dbs = OVER_MAX_DBS_IN_EVENT_MTS;
3602 *start++ = dbs;
3603 if (dbs != OVER_MAX_DBS_IN_EVENT_MTS) do {
3604 strcpy((char *)start, db_name);
3605 start += strlen(db_name) + 1;
3606 } while ((db_name = it++));
3607 } else {
3608 *start++ = dbs;
3609 }
3610 }
3611
3612 if (thd && thd->query_start_usec_used) {
3613 *start++ = Q_MICROSECONDS;
3614 get_time();
3615 int3store(start, common_header->when.tv_usec);
3616 start += 3;
3617 }
3618
3619 if (thd && thd->binlog_need_explicit_defaults_ts == true) {
3620 *start++ = Q_EXPLICIT_DEFAULTS_FOR_TIMESTAMP;
3621 *start++ = thd->variables.explicit_defaults_for_timestamp;
3622 }
3623
3624 if (ddl_xid != binary_log::INVALID_XID) {
3625 *start++ = Q_DDL_LOGGED_WITH_XID;
3626 int8store(start, ddl_xid);
3627 start += 8;
3628 }
3629
3630 if (default_collation_for_utf8mb4_number) {
3631 DBUG_ASSERT(default_collation_for_utf8mb4_number <= 0xFF);
3632 *start++ = Q_DEFAULT_COLLATION_FOR_UTF8MB4;
3633 int2store(start, default_collation_for_utf8mb4_number);
3634 start += 2;
3635 }
3636
3637 if (thd && need_sql_require_primary_key) {
3638 *start++ = Q_SQL_REQUIRE_PRIMARY_KEY;
3639 *start++ = thd->variables.sql_require_primary_key;
3640 }
3641
3642 if (thd && needs_default_table_encryption) {
3643 *start++ = Q_DEFAULT_TABLE_ENCRYPTION;
3644 *start++ = thd->variables.default_table_encryption;
3645 }
3646
3647 /*
3648 NOTE: When adding new status vars, please don't forget to update
3649 the MAX_SIZE_LOG_EVENT_STATUS in log_event.h
3650
3651 Here there could be code like
3652 if (command-line-option-which-says-"log_this_variable" && inited)
3653 {
3654 *start++= Q_THIS_VARIABLE_CODE;
3655 int4store(start, this_variable);
3656 start+= 4;
3657 }
3658 */
3659
3660 /* Store length of status variables */
3661 status_vars_len = (uint)(start - start_of_status);
3662 DBUG_ASSERT(status_vars_len <= MAX_SIZE_LOG_EVENT_STATUS);
3663 int2store(buf + Q_STATUS_VARS_LEN_OFFSET, status_vars_len);
3664
3665 /*
3666 Calculate length of whole event
3667 The "1" below is the \0 in the db's length
3668 */
3669 event_length = (uint)(start - buf) + get_post_header_size_for_derived() +
3670 db_len + 1 + q_len;
3671
3672 return (write_header(ostream, event_length) ||
3673 wrapper_my_b_safe_write(ostream, (uchar *)buf,
3674 Binary_log_event::QUERY_HEADER_LEN) ||
3675 write_post_header_for_derived(ostream) ||
3676 wrapper_my_b_safe_write(ostream, start_of_status,
3677 (uint)(start - start_of_status)) ||
3678 wrapper_my_b_safe_write(ostream,
3679 db ? pointer_cast<const uchar *>(db)
3680 : pointer_cast<const uchar *>(""),
3681 db_len + 1) ||
3682 wrapper_my_b_safe_write(ostream, pointer_cast<const uchar *>(query),
3683 q_len) ||
3684 write_footer(ostream))
3685 ? true
3686 : false;
3687 }
3688
3689 /**
3690 The simplest constructor that could possibly work. This is used for
3691 creating static objects that have a special meaning and are invisible
3692 to the log.
3693 */
Query_log_event()3694 Query_log_event::Query_log_event()
3695 : binary_log::Query_event(),
3696 Log_event(header(), footer()),
3697 data_buf(nullptr) {}
3698
3699 /**
3700 Returns true when the lex context determines an atomic DDL.
3701 The result is optimistic as there can be more properties to check out.
3702
3703 CREATE TABLE ... START TRANSACTION is not treated as atomic here, because
3704 the table is not really committed at the end of CREATE TABLE processing.
3705 It gets committed by a explicit call to COMMIT after INSERTing rows into
3706 the table.
3707
3708 @param lex pointer to LEX object of being executed statement
3709 */
is_sql_command_atomic_ddl(const LEX * lex)3710 inline bool is_sql_command_atomic_ddl(const LEX *lex) {
3711 return ((sql_command_flags[lex->sql_command] & CF_POTENTIAL_ATOMIC_DDL) &&
3712 lex->sql_command != SQLCOM_OPTIMIZE &&
3713 lex->sql_command != SQLCOM_REPAIR &&
3714 lex->sql_command != SQLCOM_ANALYZE) ||
3715 (lex->sql_command == SQLCOM_CREATE_TABLE &&
3716 !(lex->create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
3717 !lex->create_info->m_transactional_ddl) ||
3718 (lex->sql_command == SQLCOM_DROP_TABLE && !lex->drop_temporary);
3719 }
3720
3721 /**
3722 Returns whether or not the statement held by the `LEX` object parameter
3723 requires `Q_SQL_REQUIRE_PRIMARY_KEY` to be logged together with the statement.
3724 */
is_sql_require_primary_key_needed(const LEX * lex)3725 static bool is_sql_require_primary_key_needed(const LEX *lex) {
3726 enum enum_sql_command cmd = lex->sql_command;
3727 switch (cmd) {
3728 case SQLCOM_CREATE_TABLE:
3729 case SQLCOM_ALTER_TABLE:
3730 return true;
3731 default:
3732 break;
3733 }
3734 return false;
3735 }
3736
3737 /**
3738 Returns whether or not the statement held by the `LEX` object parameter
3739 requires `Q_DEFAULT_TABLE_ENCRYPTION` to be logged together with the
3740 statement.
3741 */
is_default_table_encryption_needed(const LEX * lex)3742 static bool is_default_table_encryption_needed(const LEX *lex) {
3743 enum enum_sql_command cmd = lex->sql_command;
3744 switch (cmd) {
3745 case SQLCOM_CREATE_DB:
3746 // If it is CREATE DATABASE without an ENCRYPTION clause
3747 return !(lex->create_info->used_fields &
3748 HA_CREATE_USED_DEFAULT_ENCRYPTION);
3749 case SQLCOM_ALTER_TABLESPACE: {
3750 /*
3751 If it is CREATE TABLESPACE without an ENCRYPTION clause. Note
3752 that CREATE TABLESPACE uses SQLCOM_ALTER_TABLESPACE, so to
3753 know if it is really a CREATE TABLESPACE we check that the
3754 dynamic_cast to Sql_cmd_create_tablespace works.
3755 */
3756 const Sql_cmd_tablespace *sct =
3757 dynamic_cast<const Sql_cmd_create_tablespace *>(lex->m_sql_cmd);
3758 return ((sct != nullptr) &&
3759 (sct->get_options().encryption.str == nullptr));
3760 }
3761 default:
3762 break;
3763 }
3764 return false;
3765 }
3766
is_atomic_ddl(THD * thd,bool using_trans_arg)3767 bool is_atomic_ddl(THD *thd, bool using_trans_arg) {
3768 LEX *lex = thd->lex;
3769
3770 #ifndef DBUG_OFF
3771 enum enum_sql_command cmd = lex->sql_command;
3772 switch (cmd) {
3773 case SQLCOM_CREATE_USER:
3774 case SQLCOM_RENAME_USER:
3775 case SQLCOM_DROP_USER:
3776 case SQLCOM_ALTER_USER:
3777 case SQLCOM_ALTER_USER_DEFAULT_ROLE:
3778 case SQLCOM_GRANT:
3779 case SQLCOM_GRANT_ROLE:
3780 case SQLCOM_REVOKE:
3781 case SQLCOM_REVOKE_ALL:
3782 case SQLCOM_REVOKE_ROLE:
3783 case SQLCOM_DROP_ROLE:
3784 case SQLCOM_CREATE_ROLE:
3785 case SQLCOM_SET_PASSWORD:
3786 case SQLCOM_CREATE_TRIGGER:
3787 case SQLCOM_DROP_TRIGGER:
3788 case SQLCOM_ALTER_FUNCTION:
3789 case SQLCOM_CREATE_SPFUNCTION:
3790 case SQLCOM_DROP_FUNCTION:
3791 case SQLCOM_CREATE_FUNCTION:
3792 case SQLCOM_CREATE_PROCEDURE:
3793 case SQLCOM_DROP_PROCEDURE:
3794 case SQLCOM_ALTER_PROCEDURE:
3795 case SQLCOM_ALTER_EVENT:
3796 case SQLCOM_DROP_EVENT:
3797 case SQLCOM_CREATE_VIEW:
3798 case SQLCOM_DROP_VIEW:
3799
3800 DBUG_ASSERT(using_trans_arg || thd->slave_thread || lex->drop_if_exists);
3801
3802 break;
3803
3804 case SQLCOM_CREATE_EVENT:
3805 /*
3806 trx cache is *not* used if event already exists and IF NOT EXISTS clause
3807 is used in the statement or if call is from the slave applier.
3808 */
3809 DBUG_ASSERT(using_trans_arg || thd->slave_thread ||
3810 (lex->create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS));
3811 break;
3812
3813 default:
3814 break;
3815 }
3816 #endif
3817
3818 return using_trans_arg && is_sql_command_atomic_ddl(lex);
3819 }
3820
3821 /**
3822 Creates a Query Log Event.
3823
3824 @param thd_arg Thread handle
3825 @param query_arg Array of char representing the query
3826 @param query_length Size of the 'query_arg' array
3827 @param using_trans Indicates that there are transactional changes.
3828 @param immediate After being written to the binary log, the event
3829 must be flushed immediately. This indirectly implies
3830 the stmt-cache.
3831 @param suppress_use Suppress the generation of 'USE' statements
3832 @param errcode The error code of the query
3833 @param ignore_cmd_internals Ignore user's statement, i.e. lex
3834 information, while deciding which cache must be used.
3835 */
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)3836 Query_log_event::Query_log_event(THD *thd_arg, const char *query_arg,
3837 size_t query_length, bool using_trans,
3838 bool immediate, bool suppress_use, int errcode,
3839 bool ignore_cmd_internals)
3840
3841 : binary_log::Query_event(
3842 query_arg, thd_arg->catalog().str, thd_arg->db().str, query_length,
3843 thd_arg->thread_id(), thd_arg->variables.sql_mode,
3844 thd_arg->variables.auto_increment_increment,
3845 thd_arg->variables.auto_increment_offset,
3846 thd_arg->variables.lc_time_names->number,
3847 (ulonglong)thd_arg->table_map_for_update, errcode),
3848 Log_event(
3849 thd_arg,
3850 (thd_arg->thread_specific_used ? LOG_EVENT_THREAD_SPECIFIC_F : 0) |
3851 (suppress_use ? LOG_EVENT_SUPPRESS_USE_F : 0),
3852 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE
3853 : Log_event::EVENT_STMT_CACHE,
3854 Log_event::EVENT_NORMAL_LOGGING, header(), footer()),
3855 data_buf(nullptr) {
3856 /* save the original thread id; we already know the server id */
3857 slave_proxy_id = thd_arg->variables.pseudo_thread_id;
3858 common_header->set_is_valid(query != nullptr);
3859
3860 /*
3861 exec_time calculation has changed to use the same method that is used
3862 to fill out "thd_arg->start_time"
3863 */
3864
3865 struct timeval end_time;
3866 ulonglong micro_end_time = my_micro_time();
3867 my_micro_time_to_timeval(micro_end_time, &end_time);
3868
3869 exec_time = end_time.tv_sec - thd_arg->query_start_in_secs();
3870
3871 /**
3872 @todo this means that if we have no catalog, then it is replicated
3873 as an existing catalog of length zero. is that safe? /sven
3874 */
3875 catalog_len = (catalog) ? strlen(catalog) : 0;
3876 /* status_vars_len is set just before writing the event */
3877 db_len = (db) ? strlen(db) : 0;
3878 if (thd_arg->variables.collation_database != thd_arg->db_charset)
3879 charset_database_number = thd_arg->variables.collation_database->number;
3880
3881 default_collation_for_utf8mb4_number =
3882 thd_arg->variables.default_collation_for_utf8mb4->number;
3883
3884 /*
3885 We only replicate over the bits of flags2 that we need: the rest
3886 are masked out by "& OPTIONS_WRITTEN_TO_BINLOG".
3887
3888 We also force AUTOCOMMIT=1. Rationale (cf. BUG#29288): After
3889 fixing BUG#26395, we always write BEGIN and COMMIT around all
3890 transactions (even single statements in autocommit mode). This is
3891 so that replication from non-transactional to transactional table
3892 and error recovery from XA to non-XA table should work as
3893 expected. The BEGIN/COMMIT are added in log.cc. However, there is
3894 one exception: MyISAM bypasses log.cc and writes directly to the
3895 binlog. So if autocommit is off, master has MyISAM, and slave has
3896 a transactional engine, then the slave will just see one long
3897 never-ending transaction. The only way to bypass explicit
3898 BEGIN/COMMIT in the binlog is by using a non-transactional table.
3899 So setting AUTOCOMMIT=1 will make this work as expected.
3900
3901 Note: explicitly replicate AUTOCOMMIT=1 from master. We do not
3902 assume AUTOCOMMIT=1 on slave; the slave still reads the state of
3903 the autocommit flag as written by the master to the binlog. This
3904 behavior may change after WL#4162 has been implemented.
3905 */
3906 flags2 = (uint32)(thd_arg->variables.option_bits &
3907 (OPTIONS_WRITTEN_TO_BIN_LOG & ~OPTION_NOT_AUTOCOMMIT));
3908 DBUG_ASSERT(thd_arg->variables.character_set_client->number < 256 * 256);
3909 DBUG_ASSERT(thd_arg->variables.collation_connection->number < 256 * 256);
3910 DBUG_ASSERT(thd_arg->variables.collation_server->number < 256 * 256);
3911 DBUG_ASSERT(thd_arg->variables.character_set_client->mbminlen == 1);
3912 int2store(charset, thd_arg->variables.character_set_client->number);
3913 int2store(charset + 2, thd_arg->variables.collation_connection->number);
3914 int2store(charset + 4, thd_arg->variables.collation_server->number);
3915 if (thd_arg->time_zone_used) {
3916 /*
3917 Note that our event becomes dependent on the Time_zone object
3918 representing the time zone. Fortunately such objects are never deleted
3919 or changed during mysqld's lifetime.
3920 */
3921 time_zone_len = thd_arg->variables.time_zone->get_name()->length();
3922 time_zone_str = thd_arg->variables.time_zone->get_name()->ptr();
3923 } else
3924 time_zone_len = 0;
3925
3926 /*
3927 In what follows, we define in which cache, trx-cache or stmt-cache,
3928 this Query Log Event will be written to.
3929
3930 If ignore_cmd_internals is defined, we rely on the is_trans flag to
3931 choose the cache and this is done in the base class Log_event. False
3932 means that the stmt-cache will be used and upon statement commit/rollback
3933 the cache will be flushed to disk. True means that the trx-cache will
3934 be used and upon transaction commit/rollback the cache will be flushed
3935 to disk.
3936
3937 If set immediate cache is defined, for convenience, we automatically
3938 use the stmt-cache. This mean that the statement will be written
3939 to the stmt-cache and immediately flushed to disk without waiting
3940 for a commit/rollback notification.
3941
3942 For example, the cluster/ndb captures a request to execute a DDL
3943 statement and synchronously propagate it to all available MySQL
3944 servers. Unfortunately, the current protocol assumes that the
3945 generated events are immediately written to diks and does not check
3946 for commit/rollback.
3947
3948 Upon dropping a connection, DDLs (i.e. DROP TEMPORARY TABLE) are
3949 generated and in this case the statements have the immediate flag
3950 set because there is no commit/rollback.
3951
3952 If the immediate flag is not set, the decision on the cache is based
3953 on the current statement and the flag is_trans, which indicates if
3954 a transactional engine was updated.
3955
3956 Statements are classifed as row producers (i.e. can_generate_row_events())
3957 or non-row producers. Non-row producers, DDL in general, are treated
3958 as the immediate flag was set and for convenience are written to the
3959 stmt-cache and immediately flushed to disk.
3960
3961 Row producers are handled in general according to the is_trans flag.
3962 False means that the stmt-cache will be used and upon statement
3963 commit/rollback the cache will be flushed to disk. True means that the
3964 trx-cache will be used and upon transaction commit/rollback the cache
3965 will be flushed to disk.
3966
3967 Unfortunately, there are exceptions to this non-row and row producer
3968 rules:
3969
3970 . The SAVEPOINT, ROLLBACK TO SAVEPOINT, RELEASE SAVEPOINT does not
3971 have the flag is_trans set because there is no updated engine but
3972 must be written to the trx-cache.
3973
3974 . SET If auto-commit is on, it must not go through a cache.
3975
3976 . CREATE TABLE is classfied as non-row producer but CREATE TEMPORARY
3977 must be handled as row producer.
3978
3979 . DROP TABLE is classfied as non-row producer but DROP TEMPORARY
3980 must be handled as row producer.
3981
3982 Finally, some statements that does not have the flag is_trans set may
3983 be written to the trx-cache based on the following criteria:
3984
3985 . updated both a transactional and a non-transactional engine (i.e.
3986 stmt_has_updated_trans_table()).
3987
3988 . accessed both a transactional and a non-transactional engine and
3989 is classified as unsafe (i.e. is_mixed_stmt_unsafe()).
3990
3991 . is executed within a transaction and previously a transactional
3992 engine was updated and the flag binlog_direct_non_trans_update
3993 is set.
3994 */
3995 if (ignore_cmd_internals) return;
3996
3997 /*
3998 true defines that the trx-cache must be used.
3999 */
4000 bool cmd_can_generate_row_events = false;
4001 /*
4002 true defines that the trx-cache must be used.
4003 */
4004 bool cmd_must_go_to_trx_cache = false;
4005
4006 LEX *lex = thd->lex;
4007 if (!immediate) {
4008 switch (lex->sql_command) {
4009 case SQLCOM_DROP_TABLE:
4010 cmd_can_generate_row_events =
4011 lex->drop_temporary && thd->in_multi_stmt_transaction_mode();
4012 break;
4013 case SQLCOM_CREATE_TABLE:
4014 cmd_must_go_to_trx_cache =
4015 lex->select_lex->get_fields_list()->elements &&
4016 thd->is_current_stmt_binlog_format_row();
4017 cmd_can_generate_row_events =
4018 ((lex->create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
4019 thd->in_multi_stmt_transaction_mode()) ||
4020 cmd_must_go_to_trx_cache;
4021 break;
4022 case SQLCOM_SET_OPTION:
4023 if (lex->autocommit)
4024 cmd_can_generate_row_events = cmd_must_go_to_trx_cache = false;
4025 else
4026 cmd_can_generate_row_events = true;
4027 break;
4028 case SQLCOM_RELEASE_SAVEPOINT:
4029 case SQLCOM_ROLLBACK_TO_SAVEPOINT:
4030 case SQLCOM_SAVEPOINT:
4031 case SQLCOM_XA_PREPARE:
4032 cmd_can_generate_row_events = cmd_must_go_to_trx_cache = true;
4033 break;
4034 default:
4035 cmd_can_generate_row_events =
4036 sqlcom_can_generate_row_events(thd->lex->sql_command);
4037 break;
4038 }
4039 } else {
4040 DBUG_ASSERT(!using_trans); // immediate is imcompatible with using_trans
4041 }
4042
4043 /*
4044 Drop the flag as sort of reset right before the being logged query
4045 gets classified as possibly not atomic DDL.
4046 */
4047 if (thd->rli_slave) thd->rli_slave->ddl_not_atomic = false;
4048
4049 if (cmd_can_generate_row_events) {
4050 cmd_must_go_to_trx_cache = cmd_must_go_to_trx_cache || using_trans;
4051 if (cmd_must_go_to_trx_cache ||
4052 stmt_has_updated_trans_table(
4053 thd->get_transaction()->ha_trx_info(Transaction_ctx::STMT)) ||
4054 thd->lex->is_mixed_stmt_unsafe(
4055 thd->in_multi_stmt_transaction_mode(),
4056 thd->variables.binlog_direct_non_trans_update,
4057 trans_has_updated_trans_table(thd), thd->tx_isolation) ||
4058 (!thd->variables.binlog_direct_non_trans_update &&
4059 trans_has_updated_trans_table(thd))) {
4060 event_logging_type = Log_event::EVENT_NORMAL_LOGGING;
4061 event_cache_type = Log_event::EVENT_TRANSACTIONAL_CACHE;
4062 } else {
4063 event_logging_type = Log_event::EVENT_NORMAL_LOGGING;
4064 event_cache_type = Log_event::EVENT_STMT_CACHE;
4065 }
4066 } else if (is_atomic_ddl(thd, using_trans)) {
4067 DBUG_ASSERT(stmt_causes_implicit_commit(thd, CF_IMPLICIT_COMMIT_END));
4068 /*
4069 Event creation is normally followed by its logging.
4070 Todo: add exceptions if any.
4071 */
4072 DBUG_ASSERT(!thd->is_operating_substatement_implicitly);
4073
4074 Transaction_ctx *trn_ctx = thd->get_transaction();
4075
4076 /* Transaction needs to be active for xid to be assigned, */
4077 DBUG_ASSERT(trn_ctx->is_active(Transaction_ctx::SESSION));
4078 /* and the transaction's xid has been already computed. */
4079 DBUG_ASSERT(!trn_ctx->xid_state()->get_xid()->is_null());
4080
4081 my_xid xid = trn_ctx->xid_state()->get_xid()->get_my_xid();
4082
4083 /*
4084 xid uniqueness: the last time used not equal to the current one
4085 */
4086 DBUG_ASSERT(thd->debug_binlog_xid_last.is_null() ||
4087 thd->debug_binlog_xid_last.get_my_xid() != xid);
4088
4089 ddl_xid = xid;
4090 #ifndef DBUG_OFF
4091 thd->debug_binlog_xid_last = *trn_ctx->xid_state()->get_xid();
4092 #endif
4093 event_logging_type = Log_event::EVENT_NORMAL_LOGGING;
4094 event_cache_type = Log_event::EVENT_TRANSACTIONAL_CACHE;
4095 } else if (thd->lex->sql_command == SQLCOM_CREATE_TABLE &&
4096 thd->lex->create_info->m_transactional_ddl) {
4097 /*
4098 When executing CREATE-TABLE-SELECT using engine that support atomic
4099 DDL's, we cache the CREATE-TABLE event using normal logging. This
4100 enables using single transaction for execution of both CREATE-TABLE
4101 and INSERT's when applying the binlog events at slave.
4102 */
4103 event_logging_type = Log_event::EVENT_NORMAL_LOGGING;
4104 event_cache_type = Log_event::EVENT_TRANSACTIONAL_CACHE;
4105
4106 DBUG_ASSERT(ddl_xid == binary_log::INVALID_XID);
4107
4108 if (thd->rli_slave) thd->rli_slave->ddl_not_atomic = true;
4109 } else {
4110 /*
4111 Note SQLCOM_XA_COMMIT, SQLCOM_XA_ROLLBACK fall into this block.
4112 Even though CREATE-TABLE sub-statement of CREATE-TABLE-SELECT in
4113 RBR makes a turn here it is logged atomically with the SELECT
4114 Rows-log event part that determines the xid of the entire group.
4115 */
4116 event_logging_type = Log_event::EVENT_IMMEDIATE_LOGGING;
4117 event_cache_type = Log_event::EVENT_STMT_CACHE;
4118
4119 DBUG_ASSERT(ddl_xid == binary_log::INVALID_XID);
4120
4121 if (thd->rli_slave) thd->rli_slave->ddl_not_atomic = true;
4122 }
4123
4124 need_sql_require_primary_key = is_sql_require_primary_key_needed(lex);
4125
4126 needs_default_table_encryption = is_default_table_encryption_needed(lex);
4127
4128 DBUG_ASSERT(event_cache_type != Log_event::EVENT_INVALID_CACHE);
4129 DBUG_ASSERT(event_logging_type != Log_event::EVENT_INVALID_LOGGING);
4130 DBUG_PRINT("info", ("Query_log_event has flags2: %lu sql_mode: %llu",
4131 (ulong)flags2, (ulonglong)sql_mode));
4132 }
4133 #endif /* MYSQL_SERVER */
4134
4135 /**
4136 This is used by the SQL slave thread to prepare the event before execution.
4137 */
Query_log_event(const char * buf,const Format_description_event * description_event,Log_event_type event_type)4138 Query_log_event::Query_log_event(
4139 const char *buf, const Format_description_event *description_event,
4140 Log_event_type event_type)
4141 : binary_log::Query_event(buf, description_event, event_type),
4142 Log_event(header(), footer()),
4143 has_ddl_committed(false) {
4144 DBUG_TRACE;
4145 data_buf = nullptr;
4146 if (!is_valid()) return;
4147
4148 slave_proxy_id = thread_id;
4149 exec_time = query_exec_time;
4150
4151 ulong buf_len = catalog_len + 1 + time_zone_len + 1 + user_len + 1 +
4152 host_len + 1 + data_len + 1;
4153
4154 if (!(data_buf = (Log_event_header::Byte *)my_malloc(key_memory_log_event,
4155 buf_len, MYF(MY_WME)))) {
4156 common_header->set_is_valid(false);
4157 return;
4158 }
4159 /*
4160 The data buffer is used by the slave SQL thread while applying
4161 the event. The catalog, time_zone)str, user, host, db, query
4162 are pointers to this data_buf. The function call below, points these
4163 const pointers to the data buffer.
4164 */
4165 if (!(fill_data_buf(data_buf, buf_len))) {
4166 common_header->set_is_valid(false);
4167 return;
4168 }
4169
4170 common_header->set_is_valid(query != nullptr && q_len > 0);
4171 }
4172
4173 #ifndef MYSQL_SERVER
4174 /**
4175 Given a timestamp (microseconds since epoch), generate a string
4176 of the form YYYY-MM-DD HH:MM:SS.UUUUUU and return the length.
4177
4178 @param timestamp timestamp to convert to string.
4179 @param buf Buffer to which timestamp will be written as a string.
4180 @return The length of the string containing the converted timestamp
4181 */
microsecond_timestamp_to_str(ulonglong timestamp,char * buf)4182 inline size_t microsecond_timestamp_to_str(ulonglong timestamp, char *buf) {
4183 time_t seconds = (time_t)(timestamp / 1000000);
4184 int useconds = (int)(timestamp % 1000000);
4185 struct tm time_struct;
4186 localtime_r(&seconds, &time_struct);
4187 size_t length = strftime(buf, 255, "%F %T", &time_struct);
4188 length += sprintf(buf + length, ".%06d", useconds);
4189 length += strftime(buf + length, 255, " %Z", &time_struct);
4190 return length;
4191 }
4192
4193 /**
4194 Query_log_event::print().
4195
4196 @todo
4197 print the catalog ??
4198 */
print_query_header(IO_CACHE * file,PRINT_EVENT_INFO * print_event_info) const4199 void Query_log_event::print_query_header(
4200 IO_CACHE *file, PRINT_EVENT_INFO *print_event_info) const {
4201 // TODO: print the catalog ??
4202 char buff[48], *end; // Enough for "SET TIMESTAMP=1305535348.123456"
4203 char quoted_id[1 + 2 * FN_REFLEN + 2];
4204 size_t quoted_len = 0;
4205 bool different_db = true;
4206 uint32 tmp;
4207
4208 if (!print_event_info->short_form) {
4209 const char xid_assign[] = "\tXid = ";
4210 char xid_buf[64 + sizeof(xid_assign) - 1] = {0};
4211 if (ddl_xid != binary_log::INVALID_XID) {
4212 strcpy(xid_buf, xid_assign);
4213 longlong10_to_str(ddl_xid, xid_buf + strlen(xid_assign), 10);
4214 }
4215 print_header(file, print_event_info, false);
4216 my_b_printf(file, "\t%s\tthread_id=%lu\texec_time=%lu\terror_code=%d%s\n",
4217 get_type_str(), (ulong)thread_id, (ulong)exec_time, error_code,
4218 xid_buf);
4219 }
4220
4221 if ((common_header->flags & LOG_EVENT_SUPPRESS_USE_F)) {
4222 if (!is_trans_keyword()) print_event_info->db[0] = '\0';
4223 } else if (db) {
4224 quoted_len = my_strmov_quoted_identifier((char *)quoted_id, db);
4225 quoted_id[quoted_len] = '\0';
4226 different_db = memcmp(print_event_info->db, db, db_len + 1);
4227 if (different_db) memcpy(print_event_info->db, db, db_len + 1);
4228 if (db[0] && different_db)
4229 my_b_printf(file, "use %s%s\n", quoted_id, print_event_info->delimiter);
4230 }
4231
4232 end = longlong10_to_str(common_header->when.tv_sec,
4233 my_stpcpy(buff, "SET TIMESTAMP="), 10);
4234 if (common_header->when.tv_usec)
4235 end += sprintf(end, ".%06d", (int)common_header->when.tv_usec);
4236 end = my_stpcpy(end, print_event_info->delimiter);
4237 *end++ = '\n';
4238 DBUG_ASSERT(end < buff + sizeof(buff));
4239 my_b_write(file, (uchar *)buff, (uint)(end - buff));
4240 if (!print_event_info->require_row_format &&
4241 (!print_event_info->thread_id_printed ||
4242 ((common_header->flags & LOG_EVENT_THREAD_SPECIFIC_F) &&
4243 thread_id != print_event_info->thread_id))) {
4244 // If --short-form, print deterministic value instead of pseudo_thread_id.
4245 my_b_printf(file, "SET @@session.pseudo_thread_id=%lu%s\n",
4246 short_form ? 999999999 : (ulong)thread_id,
4247 print_event_info->delimiter);
4248 print_event_info->thread_id = thread_id;
4249 print_event_info->thread_id_printed = true;
4250 }
4251
4252 /*
4253 If flags2_inited==0, this is an event from 3.23 or 4.0; nothing to
4254 print (remember we don't produce mixed relay logs so there cannot be
4255 5.0 events before that one so there is nothing to reset).
4256 */
4257 if (likely(flags2_inited)) /* likely as this will mainly read 5.0 logs */
4258 {
4259 /* tmp is a bitmask of bits which have changed. */
4260 if (likely(print_event_info->flags2_inited))
4261 /* All bits which have changed */
4262 tmp = (print_event_info->flags2) ^ flags2;
4263 else /* that's the first Query event we read */
4264 {
4265 print_event_info->flags2_inited = true;
4266 tmp = ~((uint32)0); /* all bits have changed */
4267 }
4268
4269 if (unlikely(tmp)) /* some bits have changed */
4270 {
4271 bool need_comma = false;
4272 my_b_printf(file, "SET ");
4273 print_set_option(file, tmp, OPTION_NO_FOREIGN_KEY_CHECKS, ~flags2,
4274 "@@session.foreign_key_checks", &need_comma);
4275 print_set_option(file, tmp, OPTION_AUTO_IS_NULL, flags2,
4276 "@@session.sql_auto_is_null", &need_comma);
4277 print_set_option(file, tmp, OPTION_RELAXED_UNIQUE_CHECKS, ~flags2,
4278 "@@session.unique_checks", &need_comma);
4279 print_set_option(file, tmp, OPTION_NOT_AUTOCOMMIT, ~flags2,
4280 "@@session.autocommit", &need_comma);
4281 my_b_printf(file, "%s\n", print_event_info->delimiter);
4282 print_event_info->flags2 = flags2;
4283 }
4284 }
4285
4286 /*
4287 Now the session variables;
4288 it's more efficient to pass SQL_MODE as a number instead of a
4289 comma-separated list.
4290 FOREIGN_KEY_CHECKS, SQL_AUTO_IS_NULL, UNIQUE_CHECKS are session-only
4291 variables (they have no global version; they're not listed in
4292 sql_class.h), The tests below work for pure binlogs or pure relay
4293 logs. Won't work for mixed relay logs but we don't create mixed
4294 relay logs (that is, there is no relay log with a format change
4295 except within the 3 first events, which mysqlbinlog handles
4296 gracefully). So this code should always be good.
4297 */
4298
4299 if (likely(sql_mode_inited) &&
4300 (unlikely(print_event_info->sql_mode != sql_mode ||
4301 !print_event_info->sql_mode_inited))) {
4302 /*
4303 All the SQL_MODEs included in 0x1003ff00 were removed in 8.0.5. The
4304 upgrade procedure clears these bits. So the bits can only be set on older
4305 binlogs. Therefore, we generate this version-conditioned expression that
4306 masks out the removed modes in case this is executed on 8.0.5 or later.
4307 */
4308 const char *mask = "";
4309 if (sql_mode & 0x1003ff00) mask = "/*!80005 &~0x1003ff00*/";
4310 my_b_printf(file, "SET @@session.sql_mode=%lu%s%s\n", (ulong)sql_mode, mask,
4311 print_event_info->delimiter);
4312 print_event_info->sql_mode = sql_mode;
4313 print_event_info->sql_mode_inited = true;
4314 }
4315 if (print_event_info->auto_increment_increment != auto_increment_increment ||
4316 print_event_info->auto_increment_offset != auto_increment_offset) {
4317 my_b_printf(file,
4318 "SET @@session.auto_increment_increment=%u, "
4319 "@@session.auto_increment_offset=%u%s\n",
4320 auto_increment_increment, auto_increment_offset,
4321 print_event_info->delimiter);
4322 print_event_info->auto_increment_increment = auto_increment_increment;
4323 print_event_info->auto_increment_offset = auto_increment_offset;
4324 }
4325
4326 /* TODO: print the catalog when we feature SET CATALOG */
4327
4328 if (likely(charset_inited) &&
4329 (unlikely(!print_event_info->charset_inited ||
4330 memcmp(print_event_info->charset, charset, 6)))) {
4331 const char *charset_p = charset; // Avoid type-punning warning.
4332 CHARSET_INFO *cs_info = get_charset(uint2korr(charset_p), MYF(MY_WME));
4333 if (cs_info) {
4334 /* for mysql client */
4335 my_b_printf(file, "/*!\\C %s */%s\n", cs_info->csname,
4336 print_event_info->delimiter);
4337 }
4338 my_b_printf(file,
4339 "SET "
4340 "@@session.character_set_client=%d,"
4341 "@@session.collation_connection=%d,"
4342 "@@session.collation_server=%d"
4343 "%s\n",
4344 uint2korr(charset_p), uint2korr(charset + 2),
4345 uint2korr(charset + 4), print_event_info->delimiter);
4346 memcpy(print_event_info->charset, charset, 6);
4347 print_event_info->charset_inited = true;
4348 }
4349 if (time_zone_len) {
4350 if (memcmp(print_event_info->time_zone_str, time_zone_str,
4351 time_zone_len + 1)) {
4352 my_b_printf(file, "SET @@session.time_zone='%s'%s\n", time_zone_str,
4353 print_event_info->delimiter);
4354 memcpy(print_event_info->time_zone_str, time_zone_str, time_zone_len + 1);
4355 }
4356 }
4357 if (lc_time_names_number != print_event_info->lc_time_names_number) {
4358 my_b_printf(file, "SET @@session.lc_time_names=%d%s\n",
4359 lc_time_names_number, print_event_info->delimiter);
4360 print_event_info->lc_time_names_number = lc_time_names_number;
4361 }
4362 if (charset_database_number != print_event_info->charset_database_number) {
4363 if (charset_database_number)
4364 my_b_printf(file, "SET @@session.collation_database=%d%s\n",
4365 charset_database_number, print_event_info->delimiter);
4366 else
4367 my_b_printf(file, "SET @@session.collation_database=DEFAULT%s\n",
4368 print_event_info->delimiter);
4369 print_event_info->charset_database_number = charset_database_number;
4370 }
4371 if (explicit_defaults_ts != TERNARY_UNSET)
4372 my_b_printf(file, "SET @@session.explicit_defaults_for_timestamp=%d%s\n",
4373 explicit_defaults_ts == TERNARY_OFF ? 0 : 1,
4374 print_event_info->delimiter);
4375 if (default_collation_for_utf8mb4_number !=
4376 print_event_info->default_collation_for_utf8mb4_number) {
4377 if (default_collation_for_utf8mb4_number)
4378 my_b_printf(
4379 file, "/*!80011 SET @@session.default_collation_for_utf8mb4=%d*/%s\n",
4380 default_collation_for_utf8mb4_number, print_event_info->delimiter);
4381 print_event_info->default_collation_for_utf8mb4_number =
4382 default_collation_for_utf8mb4_number;
4383 }
4384 if (sql_require_primary_key != print_event_info->sql_require_primary_key) {
4385 my_b_printf(file, "/*!80013 SET @@session.sql_require_primary_key=%d*/%s\n",
4386 sql_require_primary_key, print_event_info->delimiter);
4387 }
4388 if (default_table_encryption != print_event_info->default_table_encryption) {
4389 my_b_printf(file,
4390 "/*!80016 SET @@session.default_table_encryption=%d*/%s\n",
4391 default_table_encryption, print_event_info->delimiter);
4392 }
4393 }
4394
print(FILE *,PRINT_EVENT_INFO * print_event_info) const4395 void Query_log_event::print(FILE *, PRINT_EVENT_INFO *print_event_info) const {
4396 IO_CACHE *const head = &print_event_info->head_cache;
4397
4398 /**
4399 reduce the size of io cache so that the write function is called
4400 for every call to my_b_write().
4401 */
4402 DBUG_EXECUTE_IF("simulate_file_write_error",
4403 { head->write_pos = head->write_end - 500; });
4404 print_query_header(head, print_event_info);
4405 my_b_write(head, pointer_cast<const uchar *>(query), q_len);
4406 my_b_printf(head, "\n%s\n", print_event_info->delimiter);
4407 }
4408 #endif /* !MYSQL_SERVER */
4409
4410 #if defined(MYSQL_SERVER)
4411
4412 /**
4413 Associating slave Worker thread to a subset of temporary tables.
4414
4415 @param thd_arg THD instance pointer
4416 @param rli Relay_log_info of the worker
4417 */
attach_temp_tables_worker(THD * thd_arg,const Relay_log_info * rli)4418 void Query_log_event::attach_temp_tables_worker(THD *thd_arg,
4419 const Relay_log_info *rli) {
4420 if (!is_skip_temp_tables_handling_by_worker())
4421 rli->current_mts_submode->attach_temp_tables(thd_arg, rli, this);
4422 }
4423
4424 /**
4425 Dissociating slave Worker thread from its thd->temporary_tables
4426 to possibly update the involved entries of db-to-worker hash
4427 with new values of temporary_tables.
4428
4429 @param thd_arg THD instance pointer
4430 @param rli relay log info of the worker thread
4431 */
detach_temp_tables_worker(THD * thd_arg,const Relay_log_info * rli)4432 void Query_log_event::detach_temp_tables_worker(THD *thd_arg,
4433 const Relay_log_info *rli) {
4434 if (!is_skip_temp_tables_handling_by_worker())
4435 rli->current_mts_submode->detach_temp_tables(thd_arg, rli, this);
4436 }
4437
4438 /*
4439 Query_log_event::do_apply_event()
4440 */
do_apply_event(Relay_log_info const * rli)4441 int Query_log_event::do_apply_event(Relay_log_info const *rli) {
4442 return do_apply_event(rli, query, q_len);
4443 }
4444
4445 /*
4446 is_silent_error
4447
4448 Return true if the thread has an error which should be
4449 handled silently
4450 */
4451
is_silent_error(THD * thd)4452 static bool is_silent_error(THD *thd) {
4453 DBUG_TRACE;
4454 Diagnostics_area::Sql_condition_iterator it =
4455 thd->get_stmt_da()->sql_conditions();
4456 const Sql_condition *err;
4457 while ((err = it++)) {
4458 DBUG_PRINT("info", ("has condition %d %s", err->mysql_errno(),
4459 err->message_text()));
4460 switch (err->mysql_errno()) {
4461 case ER_SLAVE_SILENT_RETRY_TRANSACTION: {
4462 return true;
4463 }
4464 default:
4465 break;
4466 }
4467 }
4468 return false;
4469 }
4470
4471 /**
4472 @todo
4473 Compare the values of "affected rows" around here. Something
4474 like:
4475 @code
4476 if ((uint32) affected_in_event != (uint32) affected_on_slave)
4477 {
4478 sql_print_error("Slave: did not get the expected number of affected \
4479 rows running query from master - expected %d, got %d (this numbers \
4480 should have matched modulo 4294967296).", 0, ...);
4481 thd->query_error = 1;
4482 }
4483 @endcode
4484 We may also want an option to tell the slave to ignore "affected"
4485 mismatch. This mismatch could be implemented with a new ER_ code, and
4486 to ignore it you would use --slave-skip-errors...
4487 */
do_apply_event(Relay_log_info const * rli,const char * query_arg,size_t q_len_arg)4488 int Query_log_event::do_apply_event(Relay_log_info const *rli,
4489 const char *query_arg, size_t q_len_arg) {
4490 DBUG_TRACE;
4491 int expected_error, actual_error = 0;
4492
4493 DBUG_PRINT("info", ("query=%s, q_len_arg=%lu", query,
4494 static_cast<unsigned long>(q_len_arg)));
4495
4496 /*
4497 Colleagues: please never free(thd->catalog) in MySQL. This would
4498 lead to bugs as here thd->catalog is a part of an alloced block,
4499 not an entire alloced block (see
4500 Query_log_event::do_apply_event()). Same for thd->db().str. Thank
4501 you.
4502 */
4503
4504 if (catalog_len) {
4505 LEX_CSTRING catalog_lex_cstr = {catalog, catalog_len};
4506 thd->set_catalog(catalog_lex_cstr);
4507 } else
4508 thd->set_catalog(EMPTY_CSTR);
4509
4510 bool need_inc_rewrite_db_filter_counter;
4511 size_t valid_len;
4512 bool len_error;
4513 bool is_invalid_db_name =
4514 validate_string(system_charset_info, db, db_len, &valid_len, &len_error);
4515
4516 DBUG_PRINT("debug", ("is_invalid_db_name= %s, valid_len=%zu, len_error=%s",
4517 is_invalid_db_name ? "true" : "false", valid_len,
4518 len_error ? "true" : "false"));
4519
4520 if (is_invalid_db_name || len_error) {
4521 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
4522 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
4523 "Invalid database name in Query event.");
4524 thd->is_slave_error = true;
4525 goto end;
4526 }
4527
4528 need_inc_rewrite_db_filter_counter = set_thd_db(thd, db, db_len);
4529
4530 /*
4531 Setting the character set and collation of the current database thd->db.
4532 */
4533 if (get_default_db_collation(thd, thd->db().str, &thd->db_charset)) {
4534 DBUG_ASSERT(thd->is_error() || thd->killed);
4535 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
4536 "Error in get_default_db_collation: %s",
4537 thd->get_stmt_da()->message_text());
4538 thd->is_slave_error = true;
4539 goto end;
4540 }
4541
4542 thd->db_charset = thd->db_charset ? thd->db_charset : thd->collation();
4543
4544 thd->variables.auto_increment_increment = auto_increment_increment;
4545 thd->variables.auto_increment_offset = auto_increment_offset;
4546 if (explicit_defaults_ts != TERNARY_UNSET)
4547 thd->variables.explicit_defaults_for_timestamp =
4548 explicit_defaults_ts == TERNARY_OFF ? false : true;
4549
4550 /*
4551 todo: such cleanup should not be specific to Query event and therefore
4552 is preferable at a common with other event pre-execution point
4553 */
4554 clear_all_errors(thd, const_cast<Relay_log_info *>(rli));
4555 if (strcmp("COMMIT", query) == 0 && rli->tables_to_lock != nullptr) {
4556 /*
4557 Cleaning-up the last statement context:
4558 the terminal event of the current statement flagged with
4559 STMT_END_F got filtered out in ndb circular replication.
4560 */
4561 int error;
4562 char llbuff[22];
4563 if ((error =
4564 rows_event_stmt_cleanup(const_cast<Relay_log_info *>(rli), thd))) {
4565 const_cast<Relay_log_info *>(rli)->report(
4566 ERROR_LEVEL, error,
4567 "Error in cleaning up after an event preceding the commit; "
4568 "the group log file/position: %s %s",
4569 const_cast<Relay_log_info *>(rli)->get_group_master_log_name(),
4570 llstr(const_cast<Relay_log_info *>(rli)->get_group_master_log_pos(),
4571 llbuff));
4572 }
4573 /*
4574 Executing a part of rli->stmt_done() logics that does not deal
4575 with group position change. The part is redundant now but is
4576 future-change-proof addon, e.g if COMMIT handling will start checking
4577 invariants like IN_STMT flag must be off at committing the transaction.
4578 */
4579 const_cast<Relay_log_info *>(rli)->inc_event_relay_log_pos();
4580 const_cast<Relay_log_info *>(rli)->clear_flag(Relay_log_info::IN_STMT);
4581 } else {
4582 const_cast<Relay_log_info *>(rli)->slave_close_thread_tables(thd);
4583 }
4584
4585 {
4586 Applier_security_context_guard security_context{rli, thd};
4587 if (!thd->variables.require_row_format) {
4588 if (!security_context.skip_priv_checks() &&
4589 !security_context.has_access({SUPER_ACL}) &&
4590 !security_context.has_access({"SYSTEM_VARIABLES_ADMIN"}) &&
4591 !security_context.has_access({"SESSION_VARIABLES_ADMIN"})) {
4592 rli->report(ERROR_LEVEL, ER_SPECIFIC_ACCESS_DENIED_ERROR,
4593 ER_THD(thd, ER_SPECIFIC_ACCESS_DENIED_ERROR),
4594 "SUPER, SYSTEM_VARIABLES_ADMIN or SESSION_VARIABLES_ADMIN");
4595 thd->is_slave_error = true;
4596 goto end;
4597 }
4598 thd->variables.pseudo_thread_id = thread_id; // for temp tables
4599 }
4600
4601 thd->set_time(&(common_header->when));
4602 thd->set_query(query_arg, q_len_arg);
4603 thd->set_query_for_display(query_arg, q_len_arg);
4604 thd->set_query_id(next_query_id());
4605 attach_temp_tables_worker(thd, rli);
4606 DBUG_PRINT("query", ("%s", thd->query().str));
4607
4608 DBUG_EXECUTE_IF("simulate_error_in_ddl", error_code = 1051;);
4609
4610 if (ignored_error_code((expected_error = error_code)) ||
4611 !unexpected_error_code(expected_error)) {
4612 if (flags2_inited)
4613 /*
4614 all bits of thd->variables.option_bits which are 1 in
4615 OPTIONS_WRITTEN_TO_BIN_LOG must take their value from flags2.
4616 */
4617 thd->variables.option_bits =
4618 flags2 | (thd->variables.option_bits & ~OPTIONS_WRITTEN_TO_BIN_LOG);
4619 /*
4620 else, we are in a 3.23/4.0 binlog; we previously received a
4621 Rotate_log_event which reset thd->variables.option_bits and sql_mode
4622 etc, so nothing to do.
4623 */
4624 /*
4625 We do not replicate MODE_NO_DIR_IN_CREATE. That is, if the master is a
4626 slave which runs with SQL_MODE=MODE_NO_DIR_IN_CREATE, this should not
4627 force us to ignore the dir too. Imagine you are a ring of machines, and
4628 one has a disk problem so that you temporarily need
4629 MODE_NO_DIR_IN_CREATE on this machine; you don't want it to propagate
4630 elsewhere (you don't want all slaves to start ignoring the dirs).
4631 */
4632 if (sql_mode_inited) {
4633 /*
4634 All the SQL_MODEs included in 0x1003ff00 were removed in 8.0.5.
4635 The upgrade procedure clears these bits. So the bits can only be set
4636 when replicating from an older server. We consider it safe to clear
4637 the bits, because:
4638 (1) all these bits except MAXDB has zero impact on replicated
4639 statements, and MAXDB has minimal impact only;
4640 (2) the upgrade-pre-check script warns when the bit is set, so we
4641 assume users have verified that it is safe to ignore the bit.
4642 */
4643 if (sql_mode & ~(MODE_ALLOWED_MASK | MODE_IGNORED_MASK)) {
4644 my_error(ER_UNSUPPORTED_SQL_MODE, MYF(0),
4645 sql_mode & ~(MODE_ALLOWED_MASK | MODE_IGNORED_MASK));
4646 goto compare_errors;
4647 }
4648 sql_mode &= MODE_ALLOWED_MASK;
4649 thd->variables.sql_mode =
4650 (sql_mode_t)((thd->variables.sql_mode & MODE_NO_DIR_IN_CREATE) |
4651 (sql_mode & ~(ulonglong)MODE_NO_DIR_IN_CREATE));
4652 }
4653 if (charset_inited) {
4654 if (rli->cached_charset_compare(charset)) {
4655 const char *charset_p = charset; // Avoid type-punning warning.
4656 /* Verify that we support the charsets found in the event. */
4657 if (!(thd->variables.character_set_client =
4658 get_charset(uint2korr(charset_p), MYF(MY_WME))) ||
4659 !(thd->variables.collation_connection =
4660 get_charset(uint2korr(charset + 2), MYF(MY_WME))) ||
4661 !(thd->variables.collation_server =
4662 get_charset(uint2korr(charset + 4), MYF(MY_WME)))) {
4663 /*
4664 We updated the thd->variables with nonsensical values (0). Let's
4665 set them to something safe (i.e. which avoids crash), and we'll
4666 stop with EE_UNKNOWN_CHARSET in compare_errors (unless set to
4667 ignore this error).
4668 */
4669 set_slave_thread_default_charset(thd, rli);
4670 goto compare_errors;
4671 }
4672 thd->update_charset(); // for the charset change to take effect
4673 /*
4674 We cannot ask for parsing a statement using a character set
4675 without state_maps (parser internal data).
4676 */
4677 if (!thd->variables.character_set_client->state_maps) {
4678 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
4679 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
4680 "character_set cannot be parsed");
4681 thd->is_slave_error = true;
4682 goto end;
4683 }
4684 /*
4685 Reset thd->query_string.cs to the newly set value.
4686 Note, there is a small flaw here. For a very short time frame
4687 if the new charset is different from the old charset and
4688 if another thread executes "SHOW PROCESSLIST" after
4689 the above thd->set_query() and before this thd->set_query(),
4690 and if the current query has some non-ASCII characters,
4691 the another thread may see some '?' marks in the PROCESSLIST
4692 result. This should be acceptable now. This is a reminder
4693 to fix this if any refactoring happens here sometime.
4694 */
4695 thd->set_query(query_arg, q_len_arg);
4696 thd->reset_query_for_display();
4697 }
4698 }
4699 if (time_zone_len) {
4700 String tmp(time_zone_str, time_zone_len, &my_charset_bin);
4701 if (!(thd->variables.time_zone = my_tz_find(thd, &tmp))) {
4702 my_error(ER_UNKNOWN_TIME_ZONE, MYF(0), tmp.c_ptr());
4703 thd->variables.time_zone = global_system_variables.time_zone;
4704 goto compare_errors;
4705 }
4706 }
4707 if (lc_time_names_number) {
4708 if (!(thd->variables.lc_time_names =
4709 my_locale_by_number(lc_time_names_number))) {
4710 my_printf_error(ER_UNKNOWN_ERROR, "Unknown locale: '%d'", MYF(0),
4711 lc_time_names_number);
4712 thd->variables.lc_time_names = &my_locale_en_US;
4713 goto compare_errors;
4714 }
4715 } else
4716 thd->variables.lc_time_names = &my_locale_en_US;
4717 if (charset_database_number) {
4718 CHARSET_INFO *cs;
4719 if (!(cs = get_charset(charset_database_number, MYF(0)))) {
4720 char buf[20];
4721 longlong10_to_str(charset_database_number, buf, 10);
4722 my_error(ER_UNKNOWN_COLLATION, MYF(0), buf);
4723 goto compare_errors;
4724 }
4725 thd->variables.collation_database = cs;
4726 } else
4727 thd->variables.collation_database = thd->db_charset;
4728 if (default_collation_for_utf8mb4_number) {
4729 CHARSET_INFO *cs;
4730 if (!(cs = get_charset(default_collation_for_utf8mb4_number, MYF(0)))) {
4731 char buf[20];
4732 longlong10_to_str(default_collation_for_utf8mb4_number, buf, 10);
4733 my_error(ER_UNKNOWN_COLLATION, MYF(0), buf);
4734 goto compare_errors;
4735 }
4736 thd->variables.default_collation_for_utf8mb4 = cs;
4737 } else
4738 // The transaction was replicated from a server with utf8mb4_general_ci
4739 // as default collation for utf8mb4 (versions 5.7-)
4740 thd->variables.default_collation_for_utf8mb4 =
4741 &my_charset_utf8mb4_general_ci;
4742
4743 if (sql_require_primary_key != 0xff &&
4744 Relay_log_info::PK_CHECK_STREAM ==
4745 rli->get_require_table_primary_key_check()) {
4746 DBUG_ASSERT(sql_require_primary_key == 0 ||
4747 sql_require_primary_key == 1);
4748 if (!security_context.skip_priv_checks() &&
4749 !security_context.has_access({SUPER_ACL}) &&
4750 !security_context.has_access({"SYSTEM_VARIABLES_ADMIN"}) &&
4751 !security_context.has_access({"SESSION_VARIABLES_ADMIN"})) {
4752 rli->report(
4753 ERROR_LEVEL, ER_SPECIFIC_ACCESS_DENIED_ERROR,
4754 ER_THD(thd, ER_SPECIFIC_ACCESS_DENIED_ERROR),
4755 "SUPER, SYSTEM_VARIABLES_ADMIN or SESSION_VARIABLES_ADMIN");
4756 thd->is_slave_error = true;
4757 goto end;
4758 }
4759 thd->variables.sql_require_primary_key = sql_require_primary_key;
4760 }
4761
4762 if (default_table_encryption != 0xff) {
4763 DBUG_ASSERT(default_table_encryption == 0 ||
4764 default_table_encryption == 1);
4765 if (thd->variables.default_table_encryption !=
4766 default_table_encryption &&
4767 !security_context.skip_priv_checks() &&
4768 !security_context.has_access({SUPER_ACL}) &&
4769 !security_context.has_access(
4770 {"SYSTEM_VARIABLES_ADMIN", "TABLE_ENCRYPTION_ADMIN"})) {
4771 rli->report(
4772 ERROR_LEVEL, ER_SPECIFIC_ACCESS_DENIED_ERROR,
4773 ER_THD(thd, ER_SPECIFIC_ACCESS_DENIED_ERROR),
4774 "SUPER or SYSTEM_VARIABLES_ADMIN and TABLE_ENCRYPTION_ADMIN");
4775 thd->is_slave_error = true;
4776 goto end;
4777 }
4778 thd->variables.default_table_encryption = default_table_encryption;
4779 }
4780
4781 thd->table_map_for_update = (table_map)table_map_for_update;
4782
4783 LEX_STRING user_lex = LEX_STRING();
4784 LEX_STRING host_lex = LEX_STRING();
4785 if (user) {
4786 user_lex.str = const_cast<char *>(user);
4787 user_lex.length = strlen(user);
4788 }
4789 if (host) {
4790 host_lex.str = const_cast<char *>(host);
4791 host_lex.length = strlen(host);
4792 }
4793 thd->set_invoker(&user_lex, &host_lex);
4794
4795 /*
4796 Flag if we need to rollback the statement transaction on
4797 slave if it by chance succeeds.
4798 If we expected a non-zero error code and get nothing and,
4799 it is a concurrency issue or ignorable issue, effects
4800 of the statement should be rolled back.
4801 */
4802 if (expected_error && (ignored_error_code(expected_error) ||
4803 concurrency_error_code(expected_error))) {
4804 thd->variables.option_bits |= OPTION_MASTER_SQL_ERROR;
4805 }
4806 /* Execute the query (note that we bypass dispatch_command()) */
4807 Parser_state parser_state;
4808 if (!parser_state.init(thd, thd->query().str, thd->query().length)) {
4809 DBUG_ASSERT(thd->m_digest == nullptr);
4810 thd->m_digest = &thd->m_digest_state;
4811 DBUG_ASSERT(thd->m_statement_psi == nullptr);
4812 thd->m_statement_psi = MYSQL_START_STATEMENT(
4813 &thd->m_statement_state, stmt_info_rpl.m_key, thd->db().str,
4814 thd->db().length, thd->charset(), nullptr);
4815 THD_STAGE_INFO(thd, stage_starting);
4816
4817 if (thd->m_digest != nullptr)
4818 thd->m_digest->reset(thd->m_token_array, max_digest_length);
4819
4820 struct System_status_var query_start_status;
4821 struct System_status_var *query_start_status_ptr = nullptr;
4822 if (opt_log_slow_extra) {
4823 query_start_status_ptr = &query_start_status;
4824 query_start_status = thd->status_var;
4825 }
4826
4827 /*
4828 Prevent "hanging" of previous rewritten query in SHOW PROCESSLIST.
4829 */
4830 thd->reset_rewritten_query();
4831 mysql_parse(thd, &parser_state);
4832
4833 enum_sql_command command = thd->lex->sql_command;
4834
4835 /*
4836 Transaction isolation level of pure row based replicated transactions
4837 can be optimized to ISO_READ_COMMITTED by the applier when applying
4838 the Gtid_log_event.
4839
4840 If we are applying a statement other than transaction control ones
4841 after having optimized the transactions isolation level, we must warn
4842 about the non-standard situation we have found.
4843 */
4844 if (is_sbr_logging_format() &&
4845 thd->variables.transaction_isolation > ISO_READ_COMMITTED &&
4846 thd->tx_isolation == ISO_READ_COMMITTED) {
4847 String message;
4848 message.append(
4849 "The isolation level for the current transaction "
4850 "was changed to READ_COMMITTED based on the "
4851 "assumption that it had only row events and was "
4852 "not mixed with statements. "
4853 "However, an unexpected statement was found in "
4854 "the middle of the transaction."
4855 "Query: '");
4856 message.append(thd->query().str);
4857 message.append("'");
4858 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
4859 ER_THD(thd, ER_SLAVE_FATAL_ERROR), message.c_ptr());
4860 thd->is_slave_error = true;
4861 goto end;
4862 }
4863
4864 /*
4865 Do not need to increase rewrite_db_filter counter for
4866 SQLCOM_CREATE_DB, SQLCOM_DROP_DB, SQLCOM_BEGIN and
4867 SQLCOM_COMMIT.
4868 */
4869 if (need_inc_rewrite_db_filter_counter && command != SQLCOM_CREATE_DB &&
4870 command != SQLCOM_DROP_DB && command != SQLCOM_BEGIN &&
4871 command != SQLCOM_COMMIT) {
4872 Rpl_filter *rpl_filter = thd->rli_slave->rpl_filter;
4873 if (rpl_filter)
4874 rpl_filter->get_rewrite_db_statistics()->increase_counter();
4875 }
4876 /* Finalize server status flags after executing a statement. */
4877 thd->update_slow_query_status();
4878 log_slow_statement(thd, query_start_status_ptr);
4879 }
4880
4881 thd->variables.option_bits &= ~OPTION_MASTER_SQL_ERROR;
4882
4883 /*
4884 Resetting the enable_slow_log thd variable.
4885
4886 We need to reset it back to the opt_log_slow_slave_statements
4887 value after the statement execution (and slow logging
4888 is done). It might have changed if the statement was an
4889 admin statement (in which case, down in mysql_parse execution
4890 thd->enable_slow_log is set to the value of
4891 opt_log_slow_admin_statements).
4892 */
4893 thd->enable_slow_log = opt_log_slow_slave_statements;
4894 } else {
4895 /*
4896 The query got a really bad error on the master (thread killed etc),
4897 which could be inconsistent. Parse it to test the table names: if the
4898 replicate-*-do|ignore-table rules say "this query must be ignored" then
4899 we exit gracefully; otherwise we warn about the bad error and tell DBA
4900 to check/fix it.
4901 */
4902 if (mysql_test_parse_for_slave(thd))
4903 clear_all_errors(
4904 thd, const_cast<Relay_log_info *>(rli)); /* Can ignore query */
4905 else {
4906 rli->report(ERROR_LEVEL, ER_ERROR_ON_MASTER,
4907 ER_THD(thd, ER_ERROR_ON_MASTER), expected_error,
4908 thd->query().str);
4909 thd->is_slave_error = true;
4910 }
4911 goto end;
4912 }
4913 /* If the query was not ignored, it is printed to the general log */
4914 if (!thd->is_error() ||
4915 thd->get_stmt_da()->mysql_errno() != ER_SLAVE_IGNORED_TABLE) {
4916 /*
4917 Log the rewritten query if the query was rewritten
4918 and the option to log raw was not set.
4919
4920 There is an assumption here. We assume that query log
4921 events can never have multi-statement queries, thus the
4922 parsed statement is the same as the raw one.
4923 */
4924 if (opt_general_log_raw || thd->rewritten_query().length() == 0)
4925 query_logger.general_log_write(thd, COM_QUERY, thd->query().str,
4926 thd->query().length);
4927 else
4928 query_logger.general_log_write(thd, COM_QUERY,
4929 thd->rewritten_query().ptr(),
4930 thd->rewritten_query().length());
4931 }
4932
4933 compare_errors:
4934 /* Parser errors shall be ignored when (GTID) skipping statements */
4935 if (thd->is_error() &&
4936 thd->get_stmt_da()->mysql_errno() == ER_PARSE_ERROR &&
4937 gtid_pre_statement_checks(thd) == GTID_STATEMENT_SKIP) {
4938 thd->get_stmt_da()->reset_diagnostics_area();
4939 }
4940 /*
4941 In the slave thread, we may sometimes execute some DROP / * 40005
4942 TEMPORARY * / TABLE that come from parts of binlogs (likely if we
4943 use RESET SLAVE or CHANGE MASTER TO), while the temporary table
4944 has already been dropped. To ignore such irrelevant "table does
4945 not exist errors", we silently clear the error if TEMPORARY was used.
4946 */
4947 if (thd->lex->sql_command == SQLCOM_DROP_TABLE &&
4948 thd->lex->drop_temporary && thd->is_error() &&
4949 thd->get_stmt_da()->mysql_errno() == ER_BAD_TABLE_ERROR &&
4950 !expected_error) {
4951 thd->get_stmt_da()->reset_diagnostics_area();
4952 // Flag drops for error-ignored DDL to advance execution coordinates.
4953 has_ddl_committed = false;
4954 }
4955 /*
4956 If we expected a non-zero error code, and we don't get the same error
4957 code, and it should be ignored or is related to a concurrency issue.
4958 */
4959 actual_error = thd->is_error() ? thd->get_stmt_da()->mysql_errno() : 0;
4960 DBUG_PRINT("info", ("expected_error: %d sql_errno: %d", expected_error,
4961 actual_error));
4962
4963 if (actual_error != 0 && expected_error == actual_error) {
4964 if (!has_ddl_committed && // Slave didn't commit a DDL
4965 ddl_xid == binary_log::INVALID_XID && // The event was not logged as
4966 // atomic DDL on master
4967 !thd->rli_slave->ddl_not_atomic && // The DDL was considered atomic
4968 // by the slave
4969 is_atomic_ddl(thd, true)) // The DDL is atomic for the local server
4970 {
4971 thd->get_stmt_da()->reset_diagnostics_area();
4972 my_error(ER_SLAVE_POSSIBLY_DIVERGED_AFTER_DDL, MYF(0), 0);
4973 actual_error = ER_SLAVE_POSSIBLY_DIVERGED_AFTER_DDL;
4974 }
4975 }
4976
4977 /*
4978 If a statement with expected error is received on slave and if the
4979 statement is not filtered on the slave, only then compare the expected
4980 error with the actual error that happened on slave.
4981 */
4982 if ((expected_error && rli->rpl_filter->db_ok(thd->db().str) &&
4983 expected_error != actual_error &&
4984 !concurrency_error_code(expected_error)) &&
4985 !ignored_error_code(actual_error) &&
4986 !ignored_error_code(expected_error)) {
4987 if (!ignored_error_code(ER_INCONSISTENT_ERROR)) {
4988 rli->report(
4989 ERROR_LEVEL, ER_INCONSISTENT_ERROR,
4990 ER_THD(thd, ER_INCONSISTENT_ERROR),
4991 ER_THD_NONCONST(thd, expected_error), expected_error,
4992 (actual_error ? thd->get_stmt_da()->message_text() : "no error"),
4993 actual_error, print_slave_db_safe(db), query_arg);
4994 thd->is_slave_error = true;
4995 } else {
4996 rli->report(INFORMATION_LEVEL, actual_error,
4997 "The actual error and expected error on slave are"
4998 " different that will result in ER_INCONSISTENT_ERROR but"
4999 " that is passed as an argument to slave_skip_errors so no"
5000 " error is thrown. "
5001 "The expected error was %s with, Error_code: %d. "
5002 "The actual error is %s with ",
5003 ER_THD_NONCONST(thd, expected_error), expected_error,
5004 thd->get_stmt_da()->message_text());
5005 clear_all_errors(thd, const_cast<Relay_log_info *>(rli));
5006 }
5007 }
5008 /*
5009 If we get the same error code as expected and it is not a concurrency
5010 issue, or should be ignored.
5011 */
5012 else if ((expected_error == actual_error &&
5013 !concurrency_error_code(expected_error)) ||
5014 ignored_error_code(actual_error)) {
5015 DBUG_PRINT("info", ("error ignored"));
5016 if (actual_error && ignored_error_code(actual_error)) {
5017 if (actual_error == ER_SLAVE_IGNORED_TABLE) {
5018 if (!slave_ignored_err_throttle.log())
5019 rli->report(INFORMATION_LEVEL, actual_error,
5020 "Could not execute %s event. Detailed error: %s;"
5021 " Error log throttle is enabled. This error will not be"
5022 " displayed for next %lu secs. It will be suppressed",
5023 get_type_str(), thd->get_stmt_da()->message_text(),
5024 (window_size / 1000000));
5025 } else
5026 rli->report(INFORMATION_LEVEL, actual_error,
5027 "Could not execute %s event. Detailed error: %s;",
5028 get_type_str(), thd->get_stmt_da()->message_text());
5029 }
5030 has_ddl_committed = false; // The same comments as above.
5031 clear_all_errors(thd, const_cast<Relay_log_info *>(rli));
5032 thd->killed = THD::NOT_KILLED;
5033 }
5034 /*
5035 Other cases: mostly we expected no error and get one.
5036 */
5037 else if (thd->is_slave_error || thd->is_fatal_error()) {
5038 if (!is_silent_error(thd)) {
5039 rli->report(ERROR_LEVEL, actual_error,
5040 "Error '%s' on query. Default database: '%s'. Query: '%s'",
5041 (actual_error ? thd->get_stmt_da()->message_text()
5042 : "unexpected success or fatal error"),
5043 print_slave_db_safe(thd->db().str), query_arg);
5044 }
5045 thd->is_slave_error = true;
5046 }
5047
5048 /*
5049 TODO: compare the values of "affected rows" around here. Something
5050 like:
5051 if ((uint32) affected_in_event != (uint32) affected_on_slave)
5052 {
5053 sql_print_error("Slave: did not get the expected number of affected \
5054 rows running query from master - expected %d, got %d (this numbers \
5055 should have matched modulo 4294967296).", 0, ...);
5056 thd->is_slave_error = 1;
5057 }
5058 We may also want an option to tell the slave to ignore "affected"
5059 mismatch. This mismatch could be implemented with a new ER_ code, and
5060 to ignore it you would use --slave-skip-errors...
5061
5062 To do the comparison we need to know the value of "affected" which the
5063 above mysql_parse() computed. And we need to know the value of
5064 "affected" in the master's binlog. Both will be implemented later. The
5065 important thing is that we now have the format ready to log the values
5066 of "affected" in the binlog. So we can release 5.0.0 before effectively
5067 logging "affected" and effectively comparing it.
5068 */
5069 } /* End of if (db_ok(... */
5070
5071 {
5072 /**
5073 The following failure injecion works in cooperation with tests
5074 setting @@global.debug= 'd,stop_slave_middle_group'.
5075 The sql thread receives the killed status and will proceed
5076 to shutdown trying to finish incomplete events group.
5077 */
5078
5079 // TODO: address the middle-group killing in MTS case
5080
5081 DBUG_EXECUTE_IF(
5082 "stop_slave_middle_group",
5083 if (strcmp("COMMIT", query) != 0 && strcmp("BEGIN", query) != 0) {
5084 if (thd->get_transaction()->cannot_safely_rollback(
5085 Transaction_ctx::SESSION))
5086 const_cast<Relay_log_info *>(rli)->abort_slave = 1;
5087 };);
5088 }
5089
5090 end:
5091
5092 if (thd->temporary_tables) detach_temp_tables_worker(thd, rli);
5093 /*
5094 Probably we have set thd->query, thd->db, thd->catalog to point to places
5095 in the data_buf of this event. Now the event is going to be deleted
5096 probably, so data_buf will be freed, so the thd->... listed above will be
5097 pointers to freed memory.
5098 So we must set them to 0, so that those bad pointers values are not later
5099 used. Note that "cleanup" queries like automatic DROP TEMPORARY TABLE
5100 don't suffer from these assignments to 0 as DROP TEMPORARY
5101 TABLE uses the db.table syntax.
5102 */
5103 thd->set_catalog(NULL_CSTR);
5104 thd->set_db(NULL_CSTR); /* will free the current database */
5105 thd->reset_query();
5106 thd->lex->sql_command = SQLCOM_END;
5107 DBUG_PRINT("info", ("end: query= 0"));
5108
5109 /* Mark the statement completed. */
5110 MYSQL_END_STATEMENT(thd->m_statement_psi, thd->get_stmt_da());
5111 thd->m_statement_psi = nullptr;
5112 thd->m_digest = nullptr;
5113
5114 /*
5115 As a disk space optimization, future masters will not log an event for
5116 LAST_INSERT_ID() if that function returned 0 (and thus they will be able
5117 to replace the THD::stmt_depends_on_first_successful_insert_id_in_prev_stmt
5118 variable by (THD->first_successful_insert_id_in_prev_stmt > 0) ; with the
5119 resetting below we are ready to support that.
5120 */
5121 thd->first_successful_insert_id_in_prev_stmt_for_binlog = 0;
5122 thd->first_successful_insert_id_in_prev_stmt = 0;
5123 thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt = false;
5124 free_root(thd->mem_root, MYF(MY_KEEP_PREALLOC));
5125 return thd->is_slave_error;
5126 }
5127
do_update_pos(Relay_log_info * rli)5128 int Query_log_event::do_update_pos(Relay_log_info *rli) {
5129 int ret = Log_event::do_update_pos(rli);
5130
5131 DBUG_EXECUTE_IF(
5132 "crash_after_commit_and_update_pos", if (!strcmp("COMMIT", query)) {
5133 sql_print_information("Crashing crash_after_commit_and_update_pos.");
5134 rli->flush_info(true);
5135 ha_flush_logs(0);
5136 DBUG_SUICIDE();
5137 });
5138
5139 return ret;
5140 }
5141
do_shall_skip(Relay_log_info * rli)5142 Log_event::enum_skip_reason Query_log_event::do_shall_skip(
5143 Relay_log_info *rli) {
5144 DBUG_TRACE;
5145 DBUG_PRINT("debug", ("query: %s; q_len: %d", query, static_cast<int>(q_len)));
5146 DBUG_ASSERT(query && q_len > 0);
5147
5148 if (rli->slave_skip_counter > 0) {
5149 if (strcmp("BEGIN", query) == 0) {
5150 thd->variables.option_bits |= OPTION_BEGIN;
5151 return Log_event::continue_group(rli);
5152 }
5153
5154 if (strcmp("COMMIT", query) == 0 || strcmp("ROLLBACK", query) == 0) {
5155 thd->variables.option_bits &= ~OPTION_BEGIN;
5156 return Log_event::EVENT_SKIP_COUNT;
5157 }
5158 }
5159 Log_event::enum_skip_reason ret = Log_event::do_shall_skip(rli);
5160 return ret;
5161 }
5162
5163 #endif
5164
5165 /**
5166 Return the query string pointer (and its size) from a Query log event
5167 using only the event buffer (we don't instantiate a Query_log_event
5168 object for this).
5169
5170 @param buf Pointer to the event buffer.
5171 @param length The size of the event buffer.
5172 @param fd_event The description event of the master which logged
5173 the event.
5174 @param[out] query_arg The pointer to receive the query pointer.
5175
5176 @return The size of the query.
5177 */
get_query(const char * buf,size_t length,const Format_description_event * fd_event,const char ** query_arg)5178 size_t Query_log_event::get_query(const char *buf, size_t length,
5179 const Format_description_event *fd_event,
5180 const char **query_arg) {
5181 DBUG_ASSERT((Log_event_type)buf[EVENT_TYPE_OFFSET] ==
5182 binary_log::QUERY_EVENT);
5183
5184 char db_len; /* size of db name */
5185 uint status_vars_len = 0; /* size of status_vars */
5186 size_t qlen; /* size of the query */
5187 int checksum_size = 0; /* size of trailing checksum */
5188 const char *end_of_query;
5189
5190 uint common_header_len = fd_event->common_header_len;
5191 uint query_header_len =
5192 fd_event->post_header_len[binary_log::QUERY_EVENT - 1];
5193
5194 /* Error if the event content is too small */
5195 if (length < (common_header_len + query_header_len)) goto err;
5196
5197 /* Skip the header */
5198 buf += common_header_len;
5199
5200 /* Check if there are status variables in the event */
5201 if ((query_header_len - QUERY_HEADER_MINIMAL_LEN) > 0) {
5202 status_vars_len = uint2korr(buf + Q_STATUS_VARS_LEN_OFFSET);
5203 }
5204
5205 /* Check if the event has trailing checksum */
5206 if (fd_event->footer()->checksum_alg != binary_log::BINLOG_CHECKSUM_ALG_OFF)
5207 checksum_size = 4;
5208
5209 db_len = (uchar)buf[Q_DB_LEN_OFFSET];
5210
5211 /* Error if the event content is too small */
5212 if (length < (common_header_len + query_header_len + db_len + 1 +
5213 status_vars_len + checksum_size))
5214 goto err;
5215
5216 *query_arg = buf + query_header_len + db_len + 1 + status_vars_len;
5217
5218 /* Calculate the query length */
5219 end_of_query = buf +
5220 (length - common_header_len) - /* we skipped the header */
5221 checksum_size;
5222 qlen = end_of_query - *query_arg;
5223 return qlen;
5224
5225 err:
5226 *query_arg = nullptr;
5227 return 0;
5228 }
5229
5230 /***************************************************************************
5231 Format_description_log_event methods
5232 ****************************************************************************/
5233
5234 /**
5235 Format_description_log_event 1st ctor.
5236
5237 Ctor. Can be used to create the event to write to the binary log (when the
5238 server starts or when FLUSH LOGS).
5239 */
Format_description_log_event()5240 Format_description_log_event::Format_description_log_event()
5241 : Format_description_event(BINLOG_VERSION, ::server_version),
5242 #ifdef MYSQL_SERVER
5243 Log_event(header(), footer(), Log_event::EVENT_INVALID_CACHE,
5244 Log_event::EVENT_INVALID_LOGGING)
5245 #else
5246 Log_event(header(), footer())
5247 #endif
5248 {
5249 common_header->set_is_valid(true);
5250 }
5251
5252 /**
5253 The problem with this constructor is that the fixed header may have a
5254 length different from this version, but we don't know this length as we
5255 have not read the Format_description_log_event which says it, yet. This
5256 length is in the post-header of the event, but we don't know where the
5257 post-header starts.
5258
5259 So this type of event HAS to:
5260 - either have the header's length at the beginning (in the header, at a
5261 fixed position which will never be changed), not in the post-header. That
5262 would make the header be "shifted" compared to other events.
5263 - or have a header of size LOG_EVENT_MINIMAL_HEADER_LEN (19), in all future
5264 versions, so that we know for sure.
5265
5266 I (Guilhem) chose the 2nd solution. Rotate has the same constraint (because
5267 it is sent before Format_description_log_event).
5268 */
5269
Format_description_log_event(const char * buf,const Format_description_event * description_event)5270 Format_description_log_event::Format_description_log_event(
5271 const char *buf, const Format_description_event *description_event)
5272 : Format_description_event(buf, description_event),
5273 Log_event(header(), footer()) {
5274 DBUG_TRACE;
5275 if (!is_valid()) return;
5276 common_header->type_code = binary_log::FORMAT_DESCRIPTION_EVENT;
5277 }
5278
5279 #ifndef MYSQL_SERVER
print(FILE *,PRINT_EVENT_INFO * print_event_info) const5280 void Format_description_log_event::print(
5281 FILE *, PRINT_EVENT_INFO *print_event_info) const {
5282 DBUG_TRACE;
5283
5284 IO_CACHE *const head = &print_event_info->head_cache;
5285
5286 if (!print_event_info->short_form) {
5287 print_header(head, print_event_info, false);
5288 my_b_printf(head, "\tStart: binlog v %d, server v %s created ",
5289 binlog_version, server_version);
5290 print_timestamp(head, nullptr);
5291 if (created) my_b_printf(head, " at startup");
5292 my_b_printf(head, "\n");
5293 if (common_header->flags & LOG_EVENT_BINLOG_IN_USE_F)
5294 my_b_printf(head,
5295 "# Warning: this binlog is either in use or was not "
5296 "closed properly.\n");
5297 }
5298
5299 if (is_relay_log_event()) {
5300 my_b_printf(head,
5301 "# This Format_description_event appears in a relay log "
5302 "and was generated by the slave thread.\n");
5303 return;
5304 }
5305
5306 if (!is_artificial_event() && created) {
5307 #ifdef WHEN_WE_HAVE_THE_RESET_CONNECTION_SQL_COMMAND
5308 /*
5309 This is for mysqlbinlog: like in replication, we want to delete the stale
5310 tmp files left by an unclean shutdown of mysqld (temporary tables)
5311 and rollback unfinished transaction.
5312 Probably this can be done with RESET CONNECTION (syntax to be defined).
5313 */
5314 my_b_printf(head, "RESET CONNECTION%s\n", print_event_info->delimiter);
5315 #else
5316 my_b_printf(head, "ROLLBACK%s\n", print_event_info->delimiter);
5317 #endif
5318 }
5319 if (temp_buf && print_event_info->base64_output_mode != BASE64_OUTPUT_NEVER &&
5320 !print_event_info->short_form) {
5321 if (print_event_info->base64_output_mode != BASE64_OUTPUT_DECODE_ROWS)
5322 my_b_printf(head, "BINLOG '\n");
5323 print_base64(head, print_event_info, false);
5324 print_event_info->printed_fd_event = true;
5325
5326 /*
5327 If --skip-gtids is given, the server when it replays the output
5328 should generate a new GTID if gtid_mode=ON. However, when the
5329 server reads the base64-encoded Format_description_log_event, it
5330 will cleverly detect that this is a binlog to be replayed, and
5331 act a little bit like the replication thread, in the following
5332 sense: if the thread does not see any 'SET GTID_NEXT' statement,
5333 it will assume the binlog was created by an old server and try
5334 to preserve transactions as anonymous. This is the opposite of
5335 what we want when passing the --skip-gtids flag, so therefore we
5336 output the following statement.
5337
5338 The behavior where the client preserves transactions following a
5339 Format_description_log_event as anonymous was introduced in
5340 5.6.16.
5341 */
5342 if (print_event_info->skip_gtids)
5343 my_b_printf(head, "/*!50616 SET @@SESSION.GTID_NEXT='AUTOMATIC'*/%s\n",
5344 print_event_info->delimiter);
5345 }
5346 }
5347 #endif /* !MYSQL_SERVER */
5348
5349 #ifdef MYSQL_SERVER
pack_info(Protocol * protocol)5350 int Format_description_log_event::pack_info(Protocol *protocol) {
5351 char buf[12 + ST_SERVER_VER_LEN + 14 + 22], *pos;
5352 pos = my_stpcpy(buf, "Server ver: ");
5353 pos = my_stpcpy(pos, server_version);
5354 pos = my_stpcpy(pos, ", Binlog ver: ");
5355 pos = longlong10_to_str(binlog_version, pos, 10);
5356 protocol->store_string(buf, (uint)(pos - buf), &my_charset_bin);
5357 return 0;
5358 }
5359
write(Basic_ostream * ostream)5360 bool Format_description_log_event::write(Basic_ostream *ostream) {
5361 bool ret;
5362 bool no_checksum;
5363 uchar buff[Binary_log_event::FORMAT_DESCRIPTION_HEADER_LEN +
5364 BINLOG_CHECKSUM_ALG_DESC_LEN];
5365 size_t rec_size = sizeof(buff);
5366 int2store(buff + ST_BINLOG_VER_OFFSET, binlog_version);
5367 memcpy((char *)buff + ST_SERVER_VER_OFFSET, server_version,
5368 ST_SERVER_VER_LEN);
5369 if (!dont_set_created) created = get_time();
5370 int4store(buff + ST_CREATED_OFFSET, static_cast<uint32>(created));
5371 buff[ST_COMMON_HEADER_LEN_OFFSET] = LOG_EVENT_HEADER_LEN;
5372
5373 size_t number_of_events = 0;
5374 int post_header_len_size = static_cast<int>(post_header_len.size());
5375
5376 if (post_header_len_size == Binary_log_event::LOG_EVENT_TYPES)
5377 // Replicating between master and slave with same version.
5378 // number_of_events will be same as Binary_log_event::LOG_EVENT_TYPES
5379 number_of_events = Binary_log_event::LOG_EVENT_TYPES;
5380 else if (post_header_len_size > Binary_log_event::LOG_EVENT_TYPES)
5381 /*
5382 Replicating between new master and old slave.
5383 In that case there won't be any memory issues, as there won't be
5384 any out of memory read.
5385 */
5386 number_of_events = Binary_log_event::LOG_EVENT_TYPES;
5387 else
5388 /*
5389 Replicating between old master and new slave.
5390 In that case it might lead to different number_of_events on master and
5391 slave. When the relay log is rotated, the FDE from master is used to
5392 create the FDE event on slave, which is being written here. In that case
5393 we might end up reading more bytes as
5394 post_header_len.size() < Binary_log_event::LOG_EVENT_TYPES;
5395 casuing memory issues.
5396 */
5397 number_of_events = post_header_len_size;
5398
5399 memcpy((char *)buff + ST_COMMON_HEADER_LEN_OFFSET + 1,
5400 &post_header_len.front(), number_of_events);
5401 /*
5402 if checksum is requested
5403 record the checksum-algorithm descriptor next to
5404 post_header_len vector which will be followed by the checksum value.
5405 Master is supposed to trigger checksum computing by binlog_checksum_options,
5406 slave does it via marking the event according to
5407 FD_queue checksum_alg value.
5408 */
5409 static_assert(BINLOG_CHECKSUM_ALG_DESC_LEN == 1, "");
5410 #ifndef DBUG_OFF
5411 common_header->data_written = 0; // to prepare for need_checksum assert
5412 #endif
5413 buff[Binary_log_event::FORMAT_DESCRIPTION_HEADER_LEN] =
5414 need_checksum() ? (uint8)common_footer->checksum_alg
5415 : (uint8)binary_log::BINLOG_CHECKSUM_ALG_OFF;
5416 /*
5417 FD of checksum-aware server is always checksum-equipped, (V) is in,
5418 regardless of @@global.binlog_checksum policy.
5419 Thereby a combination of (A) == 0, (V) != 0 means
5420 it's the checksum-aware server's FD event that heads checksum-free binlog
5421 file.
5422 Here 0 stands for checksumming OFF to evaluate (V) as 0 is that case.
5423 A combination of (A) != 0, (V) != 0 denotes FD of the checksum-aware server
5424 heading the checksummed binlog.
5425 (A), (V) presence in FD of the checksum-aware server makes the event
5426 1 + 4 bytes bigger comparing to the former FD.
5427 */
5428
5429 if ((no_checksum = (common_footer->checksum_alg ==
5430 binary_log::BINLOG_CHECKSUM_ALG_OFF))) {
5431 // Forcing (V) room to fill anyway
5432 common_footer->checksum_alg = binary_log::BINLOG_CHECKSUM_ALG_CRC32;
5433 }
5434 ret = (write_header(ostream, rec_size) ||
5435 wrapper_my_b_safe_write(ostream, buff, rec_size) ||
5436 write_footer(ostream));
5437 if (no_checksum)
5438 common_footer->checksum_alg = binary_log::BINLOG_CHECKSUM_ALG_OFF;
5439 return ret;
5440 }
5441
do_apply_event(Relay_log_info const * rli)5442 int Format_description_log_event::do_apply_event(Relay_log_info const *rli) {
5443 int ret = 0;
5444 DBUG_TRACE;
5445
5446 /*
5447 As a transaction NEVER spans on 2 or more binlogs:
5448 if we have an active transaction at this point, the master died
5449 while writing the transaction to the binary log, i.e. while
5450 flushing the binlog cache to the binlog. XA guarantees that master has
5451 rolled back. So we roll back.
5452 Note: this event could be sent by the master to inform us of the
5453 format of its binlog; in other words maybe it is not at its
5454 original place when it comes to us; we'll know this by checking
5455 log_pos ("artificial" events have log_pos == 0).
5456 */
5457 if (!thd->rli_fake && !is_artificial_event() && created &&
5458 thd->get_transaction()->is_active(Transaction_ctx::SESSION)) {
5459 /* This is not an error (XA is safe), just an information */
5460 rli->report(INFORMATION_LEVEL, 0,
5461 "Rolling back unfinished transaction (no COMMIT "
5462 "or ROLLBACK in relay log). A probable cause is that "
5463 "the master died while writing the transaction to "
5464 "its binary log, thus rolled back too.");
5465 const_cast<Relay_log_info *>(rli)->cleanup_context(thd, true);
5466 }
5467
5468 /* If this event comes from ourself, there is no cleaning task to perform. */
5469 if (server_id != (uint32)::server_id) {
5470 if (created && !thd->variables.require_row_format) {
5471 ret = close_temporary_tables(thd);
5472 cleanup_load_tmpdir();
5473 } else {
5474 /*
5475 Set all temporary tables thread references to the current thread
5476 as they may point to the "old" SQL slave thread in case of its
5477 restart.
5478 */
5479 TABLE *table;
5480 for (table = thd->temporary_tables; table; table = table->next)
5481 table->in_use = thd;
5482 }
5483 }
5484
5485 if (!ret) {
5486 /* Save the information describing this binlog */
5487 ret = const_cast<Relay_log_info *>(rli)->set_rli_description_event(this);
5488 }
5489
5490 return ret;
5491 }
5492
do_update_pos(Relay_log_info * rli)5493 int Format_description_log_event::do_update_pos(Relay_log_info *rli) {
5494 if (server_id == (uint32)::server_id) {
5495 /*
5496 We only increase the relay log position if we are skipping
5497 events and do not touch any group_* variables, nor flush the
5498 relay log info. If there is a crash, we will have to re-skip
5499 the events again, but that is a minor issue.
5500
5501 If we do not skip stepping the group log position (and the
5502 server id was changed when restarting the server), it might well
5503 be that we start executing at a position that is invalid, e.g.,
5504 at a Rows_log_event or a Query_log_event preceeded by a
5505 Intvar_log_event instead of starting at a Table_map_log_event or
5506 the Intvar_log_event respectively.
5507 */
5508 rli->inc_event_relay_log_pos();
5509 return 0;
5510 } else {
5511 return Log_event::do_update_pos(rli);
5512 }
5513 }
5514
do_shall_skip(Relay_log_info *)5515 Log_event::enum_skip_reason Format_description_log_event::do_shall_skip(
5516 Relay_log_info *) {
5517 return Log_event::EVENT_SKIP_NOT;
5518 }
5519
5520 /**************************************************************************
5521 Rotate_log_event methods
5522 **************************************************************************/
5523
5524 /*
5525 Rotate_log_event::pack_info()
5526 */
5527
pack_info(Protocol * protocol)5528 int Rotate_log_event::pack_info(Protocol *protocol) {
5529 char buf1[256], buf[22];
5530 String tmp(buf1, sizeof(buf1), log_cs);
5531 tmp.length(0);
5532 tmp.append(new_log_ident, ident_len);
5533 tmp.append(STRING_WITH_LEN(";pos="));
5534 tmp.append(llstr(pos, buf));
5535 protocol->store_string(tmp.ptr(), tmp.length(), &my_charset_bin);
5536 return 0;
5537 }
5538 #endif // MYSQL_SERVER
5539
5540 /*
5541 Rotate_log_event::print()
5542 */
5543
5544 #ifndef MYSQL_SERVER
print(FILE *,PRINT_EVENT_INFO * print_event_info) const5545 void Rotate_log_event::print(FILE *, PRINT_EVENT_INFO *print_event_info) const {
5546 char buf[22];
5547 IO_CACHE *const head = &print_event_info->head_cache;
5548
5549 if (print_event_info->short_form) return;
5550 print_header(head, print_event_info, false);
5551 my_b_printf(head, "\tRotate to ");
5552 if (new_log_ident)
5553 my_b_write(head, pointer_cast<const uchar *>(new_log_ident),
5554 (uint)ident_len);
5555 my_b_printf(head, " pos: %s\n", llstr(pos, buf));
5556 }
5557 #endif /* !MYSQL_SERVER */
5558
5559 /*
5560 Rotate_log_event::Rotate_log_event() (2 constructors)
5561 */
5562
5563 #ifdef MYSQL_SERVER
Rotate_log_event(const char * new_log_ident_arg,size_t ident_len_arg,ulonglong pos_arg,uint flags_arg)5564 Rotate_log_event::Rotate_log_event(const char *new_log_ident_arg,
5565 size_t ident_len_arg, ulonglong pos_arg,
5566 uint flags_arg)
5567 : binary_log::Rotate_event(new_log_ident_arg, ident_len_arg, flags_arg,
5568 pos_arg),
5569 Log_event(header(), footer(), Log_event::EVENT_NO_CACHE,
5570 Log_event::EVENT_IMMEDIATE_LOGGING) {
5571 #ifndef DBUG_OFF
5572 DBUG_TRACE;
5573 #endif
5574 new_log_ident = new_log_ident_arg;
5575 pos = pos_arg;
5576 ident_len = ident_len_arg ? ident_len_arg : (uint)strlen(new_log_ident_arg);
5577 flags = flags_arg;
5578
5579 #ifndef DBUG_OFF
5580 char buff[22];
5581 DBUG_PRINT("enter", ("new_log_ident: %s pos: %s flags: %lu",
5582 new_log_ident_arg, llstr(pos_arg, buff), (ulong)flags));
5583 #endif
5584 if (flags & DUP_NAME)
5585 new_log_ident = my_strndup(key_memory_log_event, new_log_ident_arg,
5586 ident_len, MYF(MY_WME));
5587 common_header->set_is_valid(new_log_ident != nullptr);
5588 if (flags & RELAY_LOG) set_relay_log_event();
5589 }
5590 #endif // MYSQL_SERVER
5591
Rotate_log_event(const char * buf,const Format_description_event * description_event)5592 Rotate_log_event::Rotate_log_event(
5593 const char *buf, const Format_description_event *description_event)
5594 : binary_log::Rotate_event(buf, description_event),
5595 Log_event(header(), footer()) {
5596 DBUG_TRACE;
5597 if (!is_valid()) return;
5598 DBUG_PRINT("debug", ("new_log_ident: '%s'", new_log_ident));
5599 }
5600
5601 /*
5602 Rotate_log_event::write()
5603 */
5604
5605 #ifdef MYSQL_SERVER
write(Basic_ostream * ostream)5606 bool Rotate_log_event::write(Basic_ostream *ostream) {
5607 char buf[Binary_log_event::ROTATE_HEADER_LEN];
5608 int8store(buf + R_POS_OFFSET, pos);
5609 return (
5610 write_header(ostream, Binary_log_event::ROTATE_HEADER_LEN + ident_len) ||
5611 wrapper_my_b_safe_write(ostream, (uchar *)buf,
5612 Binary_log_event::ROTATE_HEADER_LEN) ||
5613 wrapper_my_b_safe_write(ostream,
5614 pointer_cast<const uchar *>(new_log_ident),
5615 (uint)ident_len) ||
5616 write_footer(ostream));
5617 }
5618
5619 /*
5620 Got a rotate log event from the master.
5621
5622 This is mainly used so that we can later figure out the logname and
5623 position for the master.
5624
5625 We can't rotate the slave's BINlog as this will cause infinitive rotations
5626 in a A -> B -> A setup.
5627 The NOTES below is a wrong comment which will disappear when 4.1 is merged.
5628
5629 This must only be called from the Slave SQL thread, since it calls
5630 flush_relay_log_info().
5631
5632 @retval
5633 0 ok
5634 */
do_update_pos(Relay_log_info * rli)5635 int Rotate_log_event::do_update_pos(Relay_log_info *rli) {
5636 int error = 0;
5637 DBUG_TRACE;
5638 #ifndef DBUG_OFF
5639 char buf[32];
5640 #endif
5641
5642 DBUG_PRINT("info", ("server_id=%lu; ::server_id=%lu", (ulong)this->server_id,
5643 (ulong)::server_id));
5644 DBUG_PRINT("info", ("new_log_ident: %s", this->new_log_ident));
5645 DBUG_PRINT("info", ("pos: %s", llstr(this->pos, buf)));
5646
5647 /*
5648 If we are in a transaction or in a group: the only normal case is
5649 when the I/O thread was copying a big transaction, then it was
5650 stopped and restarted: we have this in the relay log:
5651
5652 BEGIN
5653 ...
5654 ROTATE (a fake one)
5655 ...
5656 COMMIT or ROLLBACK
5657
5658 In that case, we don't want to touch the coordinates which
5659 correspond to the beginning of the transaction. Starting from
5660 5.0.0, there also are some rotates from the slave itself, in the
5661 relay log, which shall not change the group positions.
5662 */
5663
5664 /*
5665 The way we check if SQL thread is currently in a group is different
5666 for STS and MTS.
5667 */
5668 bool in_group = rli->is_parallel_exec()
5669 ? (rli->mts_group_status == Relay_log_info::MTS_IN_GROUP)
5670 : rli->is_in_group();
5671
5672 if ((server_id != ::server_id || rli->replicate_same_server_id) &&
5673 !is_relay_log_event() && !in_group) {
5674 if (!is_mts_db_partitioned(rli) && server_id != ::server_id) {
5675 // force the coordinator to start a new binlog segment.
5676 static_cast<Mts_submode_logical_clock *>(rli->current_mts_submode)
5677 ->start_new_group();
5678 }
5679 if (rli->is_parallel_exec()) {
5680 /*
5681 Rotate events are special events that are handled as a
5682 synchronization point. For that reason, the checkpoint
5683 routine is being called here.
5684 */
5685 if ((error = mts_checkpoint_routine(rli, false))) goto err;
5686 }
5687
5688 mysql_mutex_lock(&rli->data_lock);
5689 DBUG_PRINT("info", ("old group_master_log_name: '%s' "
5690 "old group_master_log_pos: %lu",
5691 rli->get_group_master_log_name(),
5692 (ulong)rli->get_group_master_log_pos()));
5693
5694 memcpy(const_cast<char *>(rli->get_group_master_log_name()), new_log_ident,
5695 ident_len + 1);
5696 rli->notify_group_master_log_name_update();
5697 /*
5698 Execution coordinate update by Rotate itself needs forced flush
5699 otherwise in crash case MTS won't be able to find the starting point
5700 for recovery.
5701 It is safe to update the last executed coordinates because all Worker
5702 assignments prior to Rotate has been already processed (as well as
5703 above call to @c mts_checkpoint_routine has harvested their
5704 contribution to the last executed coordinates).
5705 */
5706 if ((error = rli->inc_group_relay_log_pos(
5707 pos, false /* need_data_lock=false */, true /* force flush */))) {
5708 mysql_mutex_unlock(&rli->data_lock);
5709 goto err;
5710 }
5711
5712 DBUG_PRINT("info", ("new group_master_log_name: '%s' "
5713 "new group_master_log_pos: %lu",
5714 rli->get_group_master_log_name(),
5715 (ulong)rli->get_group_master_log_pos()));
5716 mysql_mutex_unlock(&rli->data_lock);
5717 if (rli->is_parallel_exec()) {
5718 bool real_event = server_id && !is_artificial_event();
5719 rli->reset_notified_checkpoint(
5720 0, real_event ? common_header->when.tv_sec + (time_t)exec_time : 0,
5721 real_event);
5722 }
5723
5724 /*
5725 Reset thd->variables.option_bits and sql_mode etc, because this could be
5726 the signal of a master's downgrade from 5.0 to 4.0. However, no need to
5727 reset rli_description_event: indeed, if the next master is 5.0
5728 (even 5.0.1) we will soon get a Format_desc; if the next master is 4.0
5729 then the events are in the slave's format (conversion).
5730 */
5731 set_slave_thread_options(thd);
5732 set_slave_thread_default_charset(thd, rli);
5733 thd->variables.sql_mode = global_system_variables.sql_mode;
5734 thd->variables.auto_increment_increment =
5735 thd->variables.auto_increment_offset = 1;
5736 /*
5737 Rotate_log_events are generated on Slaves with server_id=0
5738 for all the ignored events, so that the positions in the repository
5739 is updated properly even for ignored events.
5740
5741 This kind of Rotate_log_event is generated when
5742
5743 1) the event is generated on the same host and reached due
5744 to circular replication (server_id == ::server_id)
5745
5746 2) the event is from the host which is listed in ignore_server_ids
5747
5748 3) IO thread is receiving HEARTBEAT event from the master
5749
5750 4) IO thread is receiving PREVIOUS_GTID_LOG_EVENT from the master.
5751
5752 We have to free thd's mem_root here after we update the positions
5753 in the repository table. Otherwise, imagine a situation where
5754 Slave is keep getting ignored events only and no other (non-ignored)
5755 events from the Master, Slave never executes free_root (that generally
5756 happens from Query_log_event::do_apply_event or
5757 Rows_log_event::do_apply_event when they find end of the group event).
5758 */
5759 if (server_id == 0) free_root(thd->mem_root, MYF(MY_KEEP_PREALLOC));
5760 } else
5761 rli->inc_event_relay_log_pos();
5762
5763 err:
5764 return error;
5765 }
5766
do_shall_skip(Relay_log_info * rli)5767 Log_event::enum_skip_reason Rotate_log_event::do_shall_skip(
5768 Relay_log_info *rli) {
5769 enum_skip_reason reason = Log_event::do_shall_skip(rli);
5770
5771 switch (reason) {
5772 case Log_event::EVENT_SKIP_NOT:
5773 case Log_event::EVENT_SKIP_COUNT:
5774 return Log_event::EVENT_SKIP_NOT;
5775
5776 case Log_event::EVENT_SKIP_IGNORE:
5777 return Log_event::EVENT_SKIP_IGNORE;
5778 }
5779 DBUG_ASSERT(0);
5780 return Log_event::EVENT_SKIP_NOT; // To keep compiler happy
5781 }
5782
5783 /**************************************************************************
5784 Intvar_log_event methods
5785 **************************************************************************/
5786
5787 /*
5788 Intvar_log_event::pack_info()
5789 */
5790
pack_info(Protocol * protocol)5791 int Intvar_log_event::pack_info(Protocol *protocol) {
5792 char buf[256], *pos;
5793 pos = strmake(buf, (get_var_type_string()).c_str(), sizeof(buf) - 23);
5794 *pos++ = '=';
5795 pos = longlong10_to_str(val, pos, -10);
5796 protocol->store_string(buf, (uint)(pos - buf), &my_charset_bin);
5797 return 0;
5798 }
5799 #endif // MYSQL_SERVER
5800
5801 /*
5802 Intvar_log_event::Intvar_log_event()
5803 */
Intvar_log_event(const char * buf,const Format_description_event * description_event)5804 Intvar_log_event::Intvar_log_event(
5805 const char *buf, const Format_description_event *description_event)
5806 : binary_log::Intvar_event(buf, description_event),
5807 Log_event(header(), footer()) {
5808 DBUG_TRACE;
5809 }
5810
5811 /*
5812 Intvar_log_event::write()
5813 */
5814
5815 #ifdef MYSQL_SERVER
write(Basic_ostream * ostream)5816 bool Intvar_log_event::write(Basic_ostream *ostream) {
5817 uchar buf[9];
5818 buf[I_TYPE_OFFSET] = (uchar)type;
5819 int8store(buf + I_VAL_OFFSET, val);
5820 return (write_header(ostream, sizeof(buf)) ||
5821 wrapper_my_b_safe_write(ostream, buf, sizeof(buf)) ||
5822 write_footer(ostream));
5823 }
5824 #endif
5825
5826 /*
5827 Intvar_log_event::print()
5828 */
5829
5830 #ifndef MYSQL_SERVER
print(FILE *,PRINT_EVENT_INFO * print_event_info) const5831 void Intvar_log_event::print(FILE *, PRINT_EVENT_INFO *print_event_info) const {
5832 char llbuff[22] = {0};
5833 const char *msg = nullptr;
5834 IO_CACHE *const head = &print_event_info->head_cache;
5835
5836 if (!print_event_info->short_form) {
5837 print_header(head, print_event_info, false);
5838 my_b_printf(head, "\tIntvar\n");
5839 }
5840
5841 my_b_printf(head, "SET ");
5842 switch (type) {
5843 case LAST_INSERT_ID_EVENT:
5844 msg = "LAST_INSERT_ID";
5845 break;
5846 case INSERT_ID_EVENT:
5847 msg = "INSERT_ID";
5848 break;
5849 case INVALID_INT_EVENT:
5850 default: // cannot happen
5851 msg = "INVALID_INT";
5852 break;
5853 }
5854 my_b_printf(head, "%s=%s%s\n", msg, llstr(val, llbuff),
5855 print_event_info->delimiter);
5856 }
5857 #endif
5858
5859 #if defined(MYSQL_SERVER)
5860
5861 /*
5862 Intvar_log_event::do_apply_event()
5863 */
5864
do_apply_event(Relay_log_info const * rli)5865 int Intvar_log_event::do_apply_event(Relay_log_info const *rli) {
5866 /*
5867 We are now in a statement until the associated query log event has
5868 been processed.
5869 */
5870 const_cast<Relay_log_info *>(rli)->set_flag(Relay_log_info::IN_STMT);
5871
5872 if (rli->deferred_events_collecting) return rli->deferred_events->add(this);
5873
5874 switch (type) {
5875 case LAST_INSERT_ID_EVENT:
5876 thd->first_successful_insert_id_in_prev_stmt = val;
5877 break;
5878 case INSERT_ID_EVENT:
5879 thd->force_one_auto_inc_interval(val);
5880 break;
5881 }
5882 return 0;
5883 }
5884
do_update_pos(Relay_log_info * rli)5885 int Intvar_log_event::do_update_pos(Relay_log_info *rli) {
5886 rli->inc_event_relay_log_pos();
5887 return 0;
5888 }
5889
do_shall_skip(Relay_log_info * rli)5890 Log_event::enum_skip_reason Intvar_log_event::do_shall_skip(
5891 Relay_log_info *rli) {
5892 /*
5893 It is a common error to set the slave skip counter to 1 instead of
5894 2 when recovering from an insert which used a auto increment,
5895 rand, or user var. Therefore, if the slave skip counter is 1, we
5896 just say that this event should be skipped by ignoring it, meaning
5897 that we do not change the value of the slave skip counter since it
5898 will be decreased by the following insert event.
5899 */
5900 return continue_group(rli);
5901 }
5902
5903 /**************************************************************************
5904 Rand_log_event methods
5905 **************************************************************************/
5906
pack_info(Protocol * protocol)5907 int Rand_log_event::pack_info(Protocol *protocol) {
5908 char buf1[256], *pos;
5909 pos = my_stpcpy(buf1, "rand_seed1=");
5910 pos = longlong10_to_str(seed1, pos, 10);
5911 pos = my_stpcpy(pos, ",rand_seed2=");
5912 pos = longlong10_to_str(seed2, pos, 10);
5913 protocol->store_string(buf1, (uint)(pos - buf1), &my_charset_bin);
5914 return 0;
5915 }
5916 #endif // MYSQL_SERVER
5917
Rand_log_event(const char * buf,const Format_description_event * description_event)5918 Rand_log_event::Rand_log_event(
5919 const char *buf, const Format_description_event *description_event)
5920 : binary_log::Rand_event(buf, description_event),
5921 Log_event(header(), footer()) {
5922 DBUG_TRACE;
5923 }
5924
5925 #ifdef MYSQL_SERVER
write(Basic_ostream * ostream)5926 bool Rand_log_event::write(Basic_ostream *ostream) {
5927 uchar buf[16];
5928 int8store(buf + RAND_SEED1_OFFSET, seed1);
5929 int8store(buf + RAND_SEED2_OFFSET, seed2);
5930 return (write_header(ostream, sizeof(buf)) ||
5931 wrapper_my_b_safe_write(ostream, buf, sizeof(buf)) ||
5932 write_footer(ostream));
5933 }
5934 #endif
5935
5936 #ifndef MYSQL_SERVER
print(FILE *,PRINT_EVENT_INFO * print_event_info) const5937 void Rand_log_event::print(FILE *, PRINT_EVENT_INFO *print_event_info) const {
5938 IO_CACHE *const head = &print_event_info->head_cache;
5939
5940 char llbuff[22], llbuff2[22];
5941 if (!print_event_info->short_form) {
5942 print_header(head, print_event_info, false);
5943 my_b_printf(head, "\tRand\n");
5944 }
5945 my_b_printf(head, "SET @@RAND_SEED1=%s, @@RAND_SEED2=%s%s\n",
5946 llstr(seed1, llbuff), llstr(seed2, llbuff2),
5947 print_event_info->delimiter);
5948 }
5949 #endif /* !MYSQL_SERVER */
5950
5951 #if defined(MYSQL_SERVER)
do_apply_event(Relay_log_info const * rli)5952 int Rand_log_event::do_apply_event(Relay_log_info const *rli) {
5953 /*
5954 We are now in a statement until the associated query log event has
5955 been processed.
5956 */
5957 const_cast<Relay_log_info *>(rli)->set_flag(Relay_log_info::IN_STMT);
5958
5959 if (rli->deferred_events_collecting) return rli->deferred_events->add(this);
5960
5961 thd->rand.seed1 = (ulong)seed1;
5962 thd->rand.seed2 = (ulong)seed2;
5963 return 0;
5964 }
5965
do_update_pos(Relay_log_info * rli)5966 int Rand_log_event::do_update_pos(Relay_log_info *rli) {
5967 rli->inc_event_relay_log_pos();
5968 return 0;
5969 }
5970
do_shall_skip(Relay_log_info * rli)5971 Log_event::enum_skip_reason Rand_log_event::do_shall_skip(Relay_log_info *rli) {
5972 /*
5973 It is a common error to set the slave skip counter to 1 instead of
5974 2 when recovering from an insert which used a auto increment,
5975 rand, or user var. Therefore, if the slave skip counter is 1, we
5976 just say that this event should be skipped by ignoring it, meaning
5977 that we do not change the value of the slave skip counter since it
5978 will be decreased by the following insert event.
5979 */
5980 return continue_group(rli);
5981 }
5982
5983 /**
5984 Exec deferred Int-, Rand- and User- var events prefixing
5985 a Query-log-event event.
5986
5987 @param thd THD handle
5988
5989 @return false on success, true if a failure in an event applying occurred.
5990 */
slave_execute_deferred_events(THD * thd)5991 bool slave_execute_deferred_events(THD *thd) {
5992 bool res = false;
5993 Relay_log_info *rli = thd->rli_slave;
5994
5995 DBUG_ASSERT(rli &&
5996 (!rli->deferred_events_collecting || rli->deferred_events));
5997
5998 if (!rli->deferred_events_collecting || rli->deferred_events->is_empty())
5999 return res;
6000
6001 res = rli->deferred_events->execute(rli);
6002 rli->deferred_events->rewind();
6003 return res;
6004 }
6005
6006 /**************************************************************************
6007 Xid_log_event methods
6008 **************************************************************************/
6009
pack_info(Protocol * protocol)6010 int Xid_log_event::pack_info(Protocol *protocol) {
6011 char buf[128], *pos;
6012 pos = my_stpcpy(buf, "COMMIT /* xid=");
6013 pos = longlong10_to_str(xid, pos, 10);
6014 pos = my_stpcpy(pos, " */");
6015 protocol->store_string(buf, (uint)(pos - buf), &my_charset_bin);
6016 return 0;
6017 }
6018 #endif // MYSQL_SERVER
6019
Xid_log_event(const char * buf,const Format_description_event * description_event)6020 Xid_log_event::Xid_log_event(const char *buf,
6021 const Format_description_event *description_event)
6022 : binary_log::Xid_event(buf, description_event),
6023 Xid_apply_log_event(header(), footer()) {
6024 DBUG_TRACE;
6025 }
6026
6027 #ifdef MYSQL_SERVER
write(Basic_ostream * ostream)6028 bool Xid_log_event::write(Basic_ostream *ostream) {
6029 DBUG_EXECUTE_IF("do_not_write_xid", return 0;);
6030 return (write_header(ostream, sizeof(xid)) ||
6031 wrapper_my_b_safe_write(ostream, (uchar *)&xid, sizeof(xid)) ||
6032 write_footer(ostream));
6033 }
6034 #endif
6035
6036 #ifndef MYSQL_SERVER
print(FILE *,PRINT_EVENT_INFO * print_event_info) const6037 void Xid_log_event::print(FILE *, PRINT_EVENT_INFO *print_event_info) const {
6038 IO_CACHE *const head = &print_event_info->head_cache;
6039
6040 if (!print_event_info->short_form) {
6041 char buf[64];
6042 longlong10_to_str(xid, buf, 10);
6043
6044 print_header(head, print_event_info, false);
6045 my_b_printf(head, "\tXid = %s\n", buf);
6046 }
6047 my_b_printf(head, "COMMIT%s\n", print_event_info->delimiter);
6048 }
6049 #endif /* !MYSQL_SERVER */
6050
6051 #if defined(MYSQL_SERVER)
6052 /**
6053 The methods combines few commit actions to make it useable
6054 as in the single- so multi- threaded case.
6055
6056 @param thd_arg a pointer to THD handle
6057 @return false as success and
6058 true as an error
6059 */
6060
do_commit(THD * thd_arg)6061 bool Xid_log_event::do_commit(THD *thd_arg) {
6062 DBUG_EXECUTE_IF("dbug.reached_commit",
6063 { DBUG_SET("+d,dbug.enabled_commit"); });
6064 bool error = trans_commit(thd_arg); /* Automatically rolls back on error. */
6065 DBUG_EXECUTE_IF("crash_after_apply",
6066 sql_print_information("Crashing crash_after_apply.");
6067 DBUG_SUICIDE(););
6068 thd_arg->mdl_context.release_transactional_locks();
6069
6070 error |= mysql_bin_log.gtid_end_transaction(thd_arg);
6071
6072 /*
6073 The parser executing a SQLCOM_COMMIT or SQLCOM_ROLLBACK will reset the
6074 tx isolation level and access mode when the statement is finishing a
6075 transaction.
6076
6077 For replicated workload, when dealing with pure transactional workloads,
6078 there will be no QUERY(COMMIT) finishing a transaction, but a
6079 Xid_log_event instead.
6080
6081 So, if the slave applier changed the current transaction isolation level,
6082 it needs to be restored to the session default value once the current
6083 transaction has been committed.
6084 */
6085 trans_reset_one_shot_chistics(thd);
6086
6087 /*
6088 Increment the global status commit count variable
6089 */
6090 if (!error) thd_arg->status_var.com_stat[SQLCOM_COMMIT]++;
6091
6092 return error;
6093 }
6094
6095 /**
6096 Worker commits Xid transaction and in case of its transactional
6097 info table marks the current group as done in the Coordinator's
6098 Group Assigned Queue.
6099
6100 @return zero as success or non-zero as an error
6101 */
do_apply_event_worker(Slave_worker * w)6102 int Xid_apply_log_event::do_apply_event_worker(Slave_worker *w) {
6103 DBUG_TRACE;
6104 int error = 0;
6105 bool skipped_commit_pos = true;
6106
6107 lex_start(thd);
6108 mysql_reset_thd_for_next_command(thd);
6109 Slave_committed_queue *coordinator_gaq = w->c_rli->gaq;
6110
6111 /* For a slave Xid_log_event is COMMIT */
6112 query_logger.general_log_print(thd, COM_QUERY,
6113 "COMMIT /* implicit, from Xid_log_event */");
6114
6115 DBUG_PRINT(
6116 "mts",
6117 ("do_apply group master %s %llu group relay %s %llu event %s %llu.",
6118 w->get_group_master_log_name(), w->get_group_master_log_pos(),
6119 w->get_group_relay_log_name(), w->get_group_relay_log_pos(),
6120 w->get_event_relay_log_name(), w->get_event_relay_log_pos()));
6121
6122 DBUG_EXECUTE_IF("crash_before_update_pos",
6123 sql_print_information("Crashing crash_before_update_pos.");
6124 DBUG_SUICIDE(););
6125
6126 ulong gaq_idx = mts_group_idx;
6127 Slave_job_group *ptr_group = coordinator_gaq->get_job_group(gaq_idx);
6128
6129 if (!thd->get_transaction()->xid_state()->check_in_xa(false) &&
6130 w->is_transactional()) {
6131 /*
6132 Regular (not XA) transaction updates the transactional info table
6133 along with the main transaction. Otherwise, the local flag turned
6134 and given its value the info table is updated after do_commit.
6135 todo: the flag won't be need upon the full xa crash-safety bug76233
6136 gets fixed.
6137 */
6138 skipped_commit_pos = false;
6139 if ((error = w->commit_positions(this, ptr_group, w->is_transactional())))
6140 goto err;
6141 }
6142
6143 DBUG_PRINT(
6144 "mts",
6145 ("do_apply group master %s %llu group relay %s %llu event %s %llu.",
6146 w->get_group_master_log_name(), w->get_group_master_log_pos(),
6147 w->get_group_relay_log_name(), w->get_group_relay_log_pos(),
6148 w->get_event_relay_log_name(), w->get_event_relay_log_pos()));
6149
6150 DBUG_EXECUTE_IF(
6151 "crash_after_update_pos_before_apply",
6152 sql_print_information("Crashing crash_after_update_pos_before_apply.");
6153 DBUG_SUICIDE(););
6154
6155 error = do_commit(thd);
6156 if (error) {
6157 if (!skipped_commit_pos) w->rollback_positions(ptr_group);
6158 } else if (skipped_commit_pos)
6159 error = w->commit_positions(this, ptr_group, w->is_transactional());
6160 err:
6161 return error;
6162 }
6163
do_apply_event(Relay_log_info const * rli)6164 int Xid_apply_log_event::do_apply_event(Relay_log_info const *rli) {
6165 DBUG_TRACE;
6166 int error = 0;
6167 char saved_group_master_log_name[FN_REFLEN];
6168 char saved_group_relay_log_name[FN_REFLEN];
6169 volatile my_off_t saved_group_master_log_pos;
6170 volatile my_off_t saved_group_relay_log_pos;
6171
6172 char new_group_master_log_name[FN_REFLEN];
6173 char new_group_relay_log_name[FN_REFLEN];
6174 volatile my_off_t new_group_master_log_pos;
6175 volatile my_off_t new_group_relay_log_pos;
6176
6177 lex_start(thd);
6178 mysql_reset_thd_for_next_command(thd);
6179 /*
6180 Anonymous GTID ownership may be released here if the last
6181 statement before XID updated a non-transactional table and was
6182 written to the binary log as a separate transaction (either
6183 because binlog_format=row or because
6184 binlog_direct_non_transactional_updates=1). So we need to
6185 re-acquire anonymous ownership.
6186 */
6187 gtid_reacquire_ownership_if_anonymous(thd);
6188 Relay_log_info *rli_ptr = const_cast<Relay_log_info *>(rli);
6189
6190 /* For a slave Xid_log_event is COMMIT */
6191 query_logger.general_log_print(thd, COM_QUERY,
6192 "COMMIT /* implicit, from Xid_log_event */");
6193
6194 mysql_mutex_lock(&rli_ptr->data_lock);
6195
6196 /*
6197 Save the rli positions. We need them to temporarily reset the positions
6198 just before the commit.
6199 */
6200 strmake(saved_group_master_log_name, rli_ptr->get_group_master_log_name(),
6201 FN_REFLEN - 1);
6202 saved_group_master_log_pos = rli_ptr->get_group_master_log_pos();
6203 strmake(saved_group_relay_log_name, rli_ptr->get_group_relay_log_name(),
6204 FN_REFLEN - 1);
6205 saved_group_relay_log_pos = rli_ptr->get_group_relay_log_pos();
6206
6207 DBUG_PRINT(
6208 "info",
6209 ("do_apply group master %s %llu group relay %s %llu event %s %llu\n",
6210 rli_ptr->get_group_master_log_name(),
6211 rli_ptr->get_group_master_log_pos(), rli_ptr->get_group_relay_log_name(),
6212 rli_ptr->get_group_relay_log_pos(), rli_ptr->get_event_relay_log_name(),
6213 rli_ptr->get_event_relay_log_pos()));
6214
6215 DBUG_EXECUTE_IF("crash_before_update_pos",
6216 sql_print_information("Crashing crash_before_update_pos.");
6217 DBUG_SUICIDE(););
6218
6219 /*
6220 We need to update the positions in here to make it transactional.
6221 */
6222 rli_ptr->inc_event_relay_log_pos();
6223 rli_ptr->set_group_relay_log_pos(rli_ptr->get_event_relay_log_pos());
6224 rli_ptr->set_group_relay_log_name(rli_ptr->get_event_relay_log_name());
6225
6226 if (common_header->log_pos) // 3.23 binlogs don't have log_posx
6227 rli_ptr->set_group_master_log_pos(common_header->log_pos);
6228
6229 /*
6230 rli repository being transactional means replication is crash safe.
6231 Positions are written into transactional tables ahead of commit and the
6232 changes are made permanent during commit.
6233 XA transactional does not actually commit so has to defer its flush_info().
6234 */
6235 if (!thd->get_transaction()->xid_state()->check_in_xa(false) &&
6236 rli_ptr->is_transactional()) {
6237 if ((error = rli_ptr->flush_info(true))) goto err;
6238 }
6239
6240 DBUG_PRINT(
6241 "info",
6242 ("do_apply group master %s %llu group relay %s %llu event %s %llu\n",
6243 rli_ptr->get_group_master_log_name(),
6244 rli_ptr->get_group_master_log_pos(), rli_ptr->get_group_relay_log_name(),
6245 rli_ptr->get_group_relay_log_pos(), rli_ptr->get_event_relay_log_name(),
6246 rli_ptr->get_event_relay_log_pos()));
6247
6248 DBUG_EXECUTE_IF(
6249 "crash_after_update_pos_before_apply",
6250 sql_print_information("Crashing crash_after_update_pos_before_apply.");
6251 DBUG_SUICIDE(););
6252
6253 /**
6254 Commit operation expects the global transaction state variable 'xa_state'to
6255 be set to 'XA_NOTR'. In order to simulate commit failure we set
6256 the 'xa_state' to 'XA_IDLE' so that the commit reports 'ER_XAER_RMFAIL'
6257 error.
6258 */
6259 DBUG_EXECUTE_IF("simulate_commit_failure", {
6260 thd->get_transaction()->xid_state()->set_state(XID_STATE::XA_IDLE);
6261 });
6262
6263 /*
6264 Save the new rli positions. These positions will be set back to group*
6265 positions on successful completion of the commit operation.
6266 */
6267 strmake(new_group_master_log_name, rli_ptr->get_group_master_log_name(),
6268 FN_REFLEN - 1);
6269 new_group_master_log_pos = rli_ptr->get_group_master_log_pos();
6270 strmake(new_group_relay_log_name, rli_ptr->get_group_relay_log_name(),
6271 FN_REFLEN - 1);
6272 new_group_relay_log_pos = rli_ptr->get_group_relay_log_pos();
6273 /*
6274 Rollback positions in memory just before commit. Position values will be
6275 reset to their new values only on successful commit operation.
6276 */
6277 rli_ptr->set_group_master_log_name(saved_group_master_log_name);
6278 rli_ptr->set_group_master_log_pos(saved_group_master_log_pos);
6279 rli_ptr->notify_group_master_log_name_update();
6280 rli_ptr->set_group_relay_log_name(saved_group_relay_log_name);
6281 rli_ptr->set_group_relay_log_pos(saved_group_relay_log_pos);
6282
6283 DBUG_PRINT("info", ("Rolling back to group master %s %llu group relay %s"
6284 " %llu\n",
6285 rli_ptr->get_group_master_log_name(),
6286 rli_ptr->get_group_master_log_pos(),
6287 rli_ptr->get_group_relay_log_name(),
6288 rli_ptr->get_group_relay_log_pos()));
6289 mysql_mutex_unlock(&rli_ptr->data_lock);
6290 error = do_commit(thd);
6291 mysql_mutex_lock(&rli_ptr->data_lock);
6292 if (error) {
6293 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
6294 "Error in Xid_log_event: Commit could not be completed, '%s'",
6295 thd->get_stmt_da()->message_text());
6296 } else {
6297 DBUG_EXECUTE_IF(
6298 "crash_after_commit_before_update_pos",
6299 sql_print_information("Crashing "
6300 "crash_after_commit_before_update_pos.");
6301 DBUG_SUICIDE(););
6302 /* Update positions on successful commit */
6303 rli_ptr->set_group_master_log_name(new_group_master_log_name);
6304 rli_ptr->set_group_master_log_pos(new_group_master_log_pos);
6305 rli_ptr->notify_group_master_log_name_update();
6306 rli_ptr->set_group_relay_log_name(new_group_relay_log_name);
6307 rli_ptr->set_group_relay_log_pos(new_group_relay_log_pos);
6308
6309 DBUG_PRINT("info", ("Updating positions on succesful commit to group master"
6310 " %s %llu group relay %s %llu\n",
6311 rli_ptr->get_group_master_log_name(),
6312 rli_ptr->get_group_master_log_pos(),
6313 rli_ptr->get_group_relay_log_name(),
6314 rli_ptr->get_group_relay_log_pos()));
6315
6316 /*
6317 For transactional repository the positions are flushed ahead of commit.
6318 Where as for non transactional rli repository the positions are flushed
6319 only on succesful commit.
6320 */
6321 if (!rli_ptr->is_transactional()) rli_ptr->flush_info(false);
6322 }
6323 err:
6324 // This is Bug#24588741 fix:
6325 if (rli_ptr->is_group_master_log_pos_invalid)
6326 rli_ptr->is_group_master_log_pos_invalid = false;
6327 mysql_cond_broadcast(&rli_ptr->data_cond);
6328 mysql_mutex_unlock(&rli_ptr->data_lock);
6329
6330 return error;
6331 }
6332
do_shall_skip(Relay_log_info * rli)6333 Log_event::enum_skip_reason Xid_apply_log_event::do_shall_skip(
6334 Relay_log_info *rli) {
6335 DBUG_TRACE;
6336 if (rli->slave_skip_counter > 0) {
6337 thd->variables.option_bits &= ~OPTION_BEGIN;
6338 return Log_event::EVENT_SKIP_COUNT;
6339 }
6340 return Log_event::do_shall_skip(rli);
6341 }
6342
6343 /**************************************************************************
6344 XA_prepare_log_event methods
6345 **************************************************************************/
6346
pack_info(Protocol * protocol)6347 int XA_prepare_log_event::pack_info(Protocol *protocol) {
6348 char buf[ser_buf_size];
6349 char query[sizeof("XA COMMIT ONE PHASE") + 1 + sizeof(buf)];
6350
6351 /* RHS of the following assert is unknown to client sources */
6352 static_assert(ser_buf_size == XID::ser_buf_size, "");
6353 serialize_xid(buf, my_xid.formatID, my_xid.gtrid_length, my_xid.bqual_length,
6354 my_xid.data);
6355 sprintf(query, (one_phase ? "XA COMMIT %s ONE PHASE" : "XA PREPARE %s"), buf);
6356
6357 protocol->store_string(query, strlen(query), &my_charset_bin);
6358 return 0;
6359 }
6360
write(Basic_ostream * ostream)6361 bool XA_prepare_log_event::write(Basic_ostream *ostream) {
6362 uint8 one_byte = one_phase;
6363 uchar buf_f[4];
6364 uchar buf_g[4];
6365 uchar buf_b[4];
6366 int4store(buf_f, static_cast<XID *>(xid)->get_format_id());
6367 int4store(buf_g, static_cast<XID *>(xid)->get_gtrid_length());
6368 int4store(buf_b, static_cast<XID *>(xid)->get_bqual_length());
6369
6370 DBUG_ASSERT(xid_bufs_size == sizeof(buf_f) + sizeof(buf_g) + sizeof(buf_b));
6371
6372 return write_header(ostream,
6373 sizeof(one_byte) + xid_bufs_size +
6374 static_cast<XID *>(xid)->get_gtrid_length() +
6375 static_cast<XID *>(xid)->get_bqual_length()) ||
6376 wrapper_my_b_safe_write(ostream, &one_byte, sizeof(one_byte)) ||
6377 wrapper_my_b_safe_write(ostream, buf_f, sizeof(buf_f)) ||
6378 wrapper_my_b_safe_write(ostream, buf_g, sizeof(buf_g)) ||
6379 wrapper_my_b_safe_write(ostream, buf_b, sizeof(buf_b)) ||
6380 wrapper_my_b_safe_write(
6381 ostream,
6382 pointer_cast<const uchar *>(static_cast<XID *>(xid)->get_data()),
6383 static_cast<XID *>(xid)->get_gtrid_length() +
6384 static_cast<XID *>(xid)->get_bqual_length()) ||
6385 write_footer(ostream);
6386 }
6387 #endif // MYSQL_SERVER
6388
6389 #ifndef MYSQL_SERVER
print(FILE *,PRINT_EVENT_INFO * print_event_info) const6390 void XA_prepare_log_event::print(FILE *,
6391 PRINT_EVENT_INFO *print_event_info) const {
6392 IO_CACHE *const head = &print_event_info->head_cache;
6393 char buf[ser_buf_size];
6394
6395 print_header(head, print_event_info, false);
6396 serialize_xid(buf, my_xid.formatID, my_xid.gtrid_length, my_xid.bqual_length,
6397 my_xid.data);
6398 my_b_printf(head, "\tXA PREPARE %s\n", buf);
6399 my_b_printf(
6400 head, one_phase ? "XA COMMIT %s ONE PHASE\n%s\n" : "XA PREPARE %s\n%s\n",
6401 buf, print_event_info->delimiter);
6402 }
6403 #endif /* !MYSQL_SERVER */
6404
6405 #if defined(MYSQL_SERVER)
6406
6407 /**
6408 Differs from Xid_log_event::do_commit in that it carries out
6409 XA prepare (not the commit).
6410 It also can commit on one phase when the event's member @c one_phase
6411 set to true.
6412
6413 @param thd_arg a pointer to THD handle
6414 @return false as success and
6415 true as an error
6416 */
6417
do_commit(THD * thd_arg)6418 bool XA_prepare_log_event::do_commit(THD *thd_arg) {
6419 enum_gtid_statement_status state = gtid_pre_statement_checks(thd_arg);
6420 if (state == GTID_STATEMENT_EXECUTE) {
6421 if (gtid_pre_statement_post_implicit_commit_checks(thd_arg))
6422 state = GTID_STATEMENT_CANCEL;
6423 }
6424 if (state == GTID_STATEMENT_CANCEL) {
6425 uint error = thd_arg->get_stmt_da()->mysql_errno();
6426 DBUG_ASSERT(error != 0);
6427 thd_arg->rli_slave->report(ERROR_LEVEL, error,
6428 "Error executing XA PREPARE event: '%s'",
6429 thd_arg->get_stmt_da()->message_text());
6430 thd_arg->is_slave_error = true;
6431 return true;
6432 } else if (state == GTID_STATEMENT_SKIP)
6433 return false;
6434
6435 bool error = false;
6436 xid_t xid;
6437 xid.set(my_xid.formatID, my_xid.data, my_xid.gtrid_length,
6438 my_xid.data + my_xid.gtrid_length, my_xid.bqual_length);
6439 if (!one_phase) {
6440 /*
6441 This is XA-prepare branch.
6442 */
6443 thd_arg->lex->sql_command = SQLCOM_XA_PREPARE;
6444 thd_arg->lex->m_sql_cmd = new (thd_arg->mem_root) Sql_cmd_xa_prepare(&xid);
6445 error = thd_arg->lex->m_sql_cmd->execute(thd_arg);
6446 } else {
6447 thd_arg->lex->sql_command = SQLCOM_XA_COMMIT;
6448 thd_arg->lex->m_sql_cmd =
6449 new (thd_arg->mem_root) Sql_cmd_xa_commit(&xid, XA_ONE_PHASE);
6450 error = thd_arg->lex->m_sql_cmd->execute(thd_arg);
6451 }
6452
6453 if (!error) error = mysql_bin_log.gtid_end_transaction(thd_arg);
6454
6455 return error;
6456 }
6457
6458 /**************************************************************************
6459 User_var_log_event methods
6460 **************************************************************************/
6461
pack_info(Protocol * protocol)6462 int User_var_log_event::pack_info(Protocol *protocol) {
6463 char *buf = nullptr;
6464 char quoted_id[1 + FN_REFLEN * 2 + 2]; // quoted identifier
6465 size_t id_len =
6466 my_strmov_quoted_identifier(this->thd, quoted_id, name, name_len);
6467 quoted_id[id_len] = '\0';
6468 size_t val_offset = 2 + id_len;
6469 size_t event_len = val_offset;
6470
6471 if (is_null) {
6472 if (!(buf = (char *)my_malloc(key_memory_log_event, val_offset + 5,
6473 MYF(MY_WME))))
6474 return 1;
6475 my_stpcpy(buf + val_offset, "NULL");
6476 event_len = val_offset + 4;
6477 } else {
6478 switch (type) {
6479 case REAL_RESULT:
6480 double real_val;
6481 real_val = float8get(val);
6482 if (!(buf = (char *)my_malloc(key_memory_log_event,
6483 val_offset + MY_GCVT_MAX_FIELD_WIDTH + 1,
6484 MYF(MY_WME))))
6485 return 1;
6486 event_len +=
6487 my_gcvt(real_val, MY_GCVT_ARG_DOUBLE, MY_GCVT_MAX_FIELD_WIDTH,
6488 buf + val_offset, nullptr);
6489 break;
6490 case INT_RESULT:
6491 if (!(buf = (char *)my_malloc(key_memory_log_event, val_offset + 22,
6492 MYF(MY_WME))))
6493 return 1;
6494 event_len = longlong10_to_str(
6495 uint8korr(val), buf + val_offset,
6496 ((flags & User_var_log_event::UNSIGNED_F) ? 10 : -10)) -
6497 buf;
6498 break;
6499 case DECIMAL_RESULT: {
6500 if (!(buf = (char *)my_malloc(key_memory_log_event,
6501 val_offset + DECIMAL_MAX_STR_LENGTH + 1,
6502 MYF(MY_WME))))
6503 return 1;
6504 String str(buf + val_offset, DECIMAL_MAX_STR_LENGTH + 1,
6505 &my_charset_bin);
6506 my_decimal dec;
6507 binary2my_decimal(E_DEC_FATAL_ERROR, (uchar *)(val + 2), &dec, val[0],
6508 val[1]);
6509 my_decimal2string(E_DEC_FATAL_ERROR, &dec, &str);
6510 event_len = str.length() + val_offset;
6511 break;
6512 }
6513 case STRING_RESULT:
6514 /* 15 is for 'COLLATE' and other chars */
6515 buf = (char *)my_malloc(
6516 key_memory_log_event,
6517 event_len + val_len * 2 + 1 + 2 * MY_CS_NAME_SIZE + 15,
6518 MYF(MY_WME));
6519 CHARSET_INFO *cs;
6520 if (!buf) return 1;
6521 if (!(cs = get_charset(charset_number, MYF(0)))) {
6522 my_stpcpy(buf + val_offset, "???");
6523 event_len += 3;
6524 } else {
6525 char *p = strxmov(buf + val_offset, "_", cs->csname, " ", NullS);
6526 p = str_to_hex(p, val, val_len);
6527 p = strxmov(p, " COLLATE ", cs->name, NullS);
6528 event_len = p - buf;
6529 }
6530 break;
6531 case ROW_RESULT:
6532 default:
6533 DBUG_ASSERT(false);
6534 return 1;
6535 }
6536 }
6537 buf[0] = '@';
6538 memcpy(buf + 1, quoted_id, id_len);
6539 buf[1 + id_len] = '=';
6540 protocol->store_string(buf, event_len, &my_charset_bin);
6541 my_free(buf);
6542 return 0;
6543 }
6544 #endif /* MYSQL_SERVER */
6545
User_var_log_event(const char * buf,const Format_description_event * description_event)6546 User_var_log_event::User_var_log_event(
6547 const char *buf, const Format_description_event *description_event)
6548 : binary_log::User_var_event(buf, description_event),
6549 Log_event(header(), footer())
6550 #ifdef MYSQL_SERVER
6551 ,
6552 deferred(false),
6553 query_id(0)
6554 #endif
6555 {
6556 DBUG_TRACE;
6557 }
6558
6559 #ifdef MYSQL_SERVER
write(Basic_ostream * ostream)6560 bool User_var_log_event::write(Basic_ostream *ostream) {
6561 char buf[UV_NAME_LEN_SIZE];
6562 char buf1[UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE + UV_CHARSET_NUMBER_SIZE +
6563 UV_VAL_LEN_SIZE];
6564 uchar buf2[std::max(8, DECIMAL_MAX_FIELD_SIZE + 2)], *pos = buf2;
6565 uint unsigned_len = 0;
6566 uint buf1_length;
6567 ulong event_length;
6568
6569 int4store(buf, name_len);
6570
6571 if ((buf1[0] = is_null)) {
6572 buf1_length = 1;
6573 val_len = 0; // Length of 'pos'
6574 } else {
6575 buf1[1] = type;
6576 int4store(buf1 + 2, charset_number);
6577
6578 switch (type) {
6579 case REAL_RESULT:
6580 float8store(buf2, *(double *)val);
6581 break;
6582 case INT_RESULT:
6583 int8store(buf2, *(longlong *)val);
6584 unsigned_len = 1;
6585 break;
6586 case DECIMAL_RESULT: {
6587 my_decimal *dec = (my_decimal *)val;
6588 dec->sanity_check();
6589 buf2[0] = (char)(dec->intg + dec->frac);
6590 buf2[1] = (char)dec->frac;
6591 decimal2bin(dec, buf2 + 2, buf2[0], buf2[1]);
6592 val_len = decimal_bin_size(buf2[0], buf2[1]) + 2;
6593 break;
6594 }
6595 case STRING_RESULT:
6596 pos = (uchar *)val;
6597 break;
6598 case ROW_RESULT:
6599 default:
6600 DBUG_ASSERT(false);
6601 return false;
6602 }
6603 int4store(buf1 + 2 + UV_CHARSET_NUMBER_SIZE, val_len);
6604 buf1_length = 10;
6605 }
6606
6607 event_length = sizeof(buf) + name_len + buf1_length + val_len + unsigned_len;
6608
6609 return (write_header(ostream, event_length) ||
6610 wrapper_my_b_safe_write(ostream, (uchar *)buf, sizeof(buf)) ||
6611 wrapper_my_b_safe_write(ostream, pointer_cast<const uchar *>(name),
6612 name_len) ||
6613 wrapper_my_b_safe_write(ostream, (uchar *)buf1, buf1_length) ||
6614 wrapper_my_b_safe_write(ostream, pos, val_len) ||
6615 wrapper_my_b_safe_write(ostream, &flags, unsigned_len) ||
6616 write_footer(ostream));
6617 }
6618 #endif
6619
6620 /*
6621 User_var_log_event::print()
6622 */
6623
6624 #ifndef MYSQL_SERVER
print(FILE *,PRINT_EVENT_INFO * print_event_info) const6625 void User_var_log_event::print(FILE *,
6626 PRINT_EVENT_INFO *print_event_info) const {
6627 IO_CACHE *const head = &print_event_info->head_cache;
6628 char quoted_id[1 + NAME_LEN * 2 + 2]; // quoted length of the identifier
6629 char name_id[NAME_LEN + 1];
6630 size_t quoted_len = 0;
6631
6632 if (!print_event_info->short_form) {
6633 print_header(head, print_event_info, false);
6634 my_b_printf(head, "\tUser_var\n");
6635 }
6636 my_stpcpy(name_id, name);
6637 name_id[name_len] = '\0';
6638 my_b_printf(head, "SET @");
6639 quoted_len =
6640 my_strmov_quoted_identifier((char *)quoted_id, (const char *)name_id);
6641 quoted_id[quoted_len] = '\0';
6642 my_b_write(head, (uchar *)quoted_id, quoted_len);
6643
6644 if (is_null) {
6645 my_b_printf(head, ":=NULL%s\n", print_event_info->delimiter);
6646 } else {
6647 switch (type) {
6648 case REAL_RESULT:
6649 double real_val;
6650 char real_buf[FMT_G_BUFSIZE(14)];
6651 real_val = float8get(val);
6652 sprintf(real_buf, "%.14g", real_val);
6653 my_b_printf(head, ":=%s%s\n", real_buf, print_event_info->delimiter);
6654 break;
6655 case INT_RESULT:
6656 char int_buf[22];
6657 longlong10_to_str(
6658 uint8korr(val), int_buf,
6659 ((flags & User_var_log_event::UNSIGNED_F) ? 10 : -10));
6660 my_b_printf(head, ":=%s%s\n", int_buf, print_event_info->delimiter);
6661 break;
6662 case DECIMAL_RESULT: {
6663 char str_buf[DECIMAL_MAX_STR_LENGTH + 1];
6664 int str_len = sizeof(str_buf);
6665 int precision = (int)val[0];
6666 int scale = (int)val[1];
6667 decimal_digit_t dec_buf[10];
6668 decimal_t dec;
6669 dec.len = 10;
6670 dec.buf = dec_buf;
6671
6672 bin2decimal((uchar *)val + 2, &dec, precision, scale);
6673 decimal2string(&dec, str_buf, &str_len);
6674 my_b_printf(head, ":=%s%s\n", str_buf, print_event_info->delimiter);
6675 break;
6676 }
6677 case STRING_RESULT: {
6678 /*
6679 Let's express the string in hex. That's the most robust way. If we
6680 print it in character form instead, we need to escape it with
6681 character_set_client which we don't know (we will know it in 5.0, but
6682 in 4.1 we don't know it easily when we are printing
6683 User_var_log_event). Explanation why we would need to bother with
6684 character_set_client (quoting Bar):
6685 > Note, the parser doesn't switch to another unescaping mode after
6686 > it has met a character set introducer.
6687 > For example, if an SJIS client says something like:
6688 > SET @a= _ucs2 \0a\0b'
6689 > the string constant is still unescaped according to SJIS, not
6690 > according to UCS2.
6691 */
6692 char *hex_str;
6693 CHARSET_INFO *cs;
6694
6695 hex_str = (char *)my_malloc(key_memory_log_event, 2 * val_len + 1 + 2,
6696 MYF(MY_WME)); // 2 hex digits / byte
6697 if (!hex_str) return;
6698 str_to_hex(hex_str, val, val_len);
6699 /*
6700 For proper behaviour when mysqlbinlog|mysql, we need to explicitely
6701 specify the variable's collation. It will however cause problems when
6702 people want to mysqlbinlog|mysql into another server not supporting
6703 the character set. But there's not much to do about this and it's
6704 unlikely.
6705 */
6706 if (!(cs = get_charset(charset_number, MYF(0))))
6707 /*
6708 Generate an unusable command (=> syntax error) is probably the best
6709 thing we can do here.
6710 */
6711 my_b_printf(head, ":=???%s\n", print_event_info->delimiter);
6712 else
6713 my_b_printf(head, ":=_%s %s COLLATE `%s`%s\n", cs->csname, hex_str,
6714 cs->name, print_event_info->delimiter);
6715 my_free(hex_str);
6716 } break;
6717 case ROW_RESULT:
6718 default:
6719 DBUG_ASSERT(false);
6720 return;
6721 }
6722 }
6723 }
6724 #endif
6725
6726 /*
6727 User_var_log_event::do_apply_event()
6728 */
6729
6730 #if defined(MYSQL_SERVER)
do_apply_event(Relay_log_info const * rli)6731 int User_var_log_event::do_apply_event(Relay_log_info const *rli) {
6732 DBUG_TRACE;
6733 Item *it = nullptr;
6734 CHARSET_INFO *charset;
6735 query_id_t sav_query_id = 0; /* memorize orig id when deferred applying */
6736
6737 if (rli->deferred_events_collecting) {
6738 set_deferred(current_thd->query_id);
6739 int ret = rli->deferred_events->add(this);
6740 return ret;
6741 } else if (is_deferred()) {
6742 sav_query_id = current_thd->query_id;
6743 current_thd->query_id = query_id; /* recreating original time context */
6744 }
6745
6746 if (!(charset = get_charset(charset_number, MYF(MY_WME)))) {
6747 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
6748 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
6749 "Invalid character set for User var event");
6750 return 1;
6751 }
6752 double real_val;
6753 longlong int_val;
6754
6755 /*
6756 We are now in a statement until the associated query log event has
6757 been processed.
6758 */
6759 const_cast<Relay_log_info *>(rli)->set_flag(Relay_log_info::IN_STMT);
6760
6761 if (is_null) {
6762 it = new Item_null();
6763 } else {
6764 switch (type) {
6765 case REAL_RESULT:
6766 if (val_len != 8) {
6767 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
6768 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
6769 "Invalid variable length at User var event");
6770 return 1;
6771 }
6772 real_val = float8get(val);
6773 it = new Item_float(real_val, 0);
6774 val = (char *)&real_val; // Pointer to value in native format
6775 val_len = 8;
6776 break;
6777 case INT_RESULT:
6778 if (val_len != 8) {
6779 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
6780 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
6781 "Invalid variable length at User var event");
6782 return 1;
6783 }
6784 int_val = (longlong)uint8korr(val);
6785 it = new Item_int(int_val);
6786 val = (char *)&int_val; // Pointer to value in native format
6787 val_len = 8;
6788 break;
6789 case DECIMAL_RESULT: {
6790 if (val_len < 3) {
6791 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
6792 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
6793 "Invalid variable length at User var event");
6794 return 1;
6795 }
6796 Item_decimal *dec = new Item_decimal((uchar *)val + 2, val[0], val[1]);
6797 it = dec;
6798 val = (char *)dec->val_decimal(nullptr);
6799 val_len = sizeof(my_decimal);
6800 break;
6801 }
6802 case STRING_RESULT:
6803 it = new Item_string(val, val_len, charset);
6804 break;
6805 case ROW_RESULT:
6806 default:
6807 DBUG_ASSERT(false);
6808 return 0;
6809 }
6810 }
6811 Item_func_set_user_var *e =
6812 new Item_func_set_user_var(Name_string(name, name_len, false), it, false);
6813 /*
6814 Item_func_set_user_var can't substitute something else on its place =>
6815 0 can be passed as last argument (reference on item)
6816
6817 Fix_fields() can fail, in which case a call of update_hash() might
6818 crash the server, so if fix fields fails, we just return with an
6819 error.
6820 */
6821 if (e->fix_fields(thd, nullptr)) return 1;
6822
6823 /*
6824 A variable can just be considered as a table with
6825 a single record and with a single column. Thus, like
6826 a column value, it could always have IMPLICIT derivation.
6827 */
6828 e->update_hash(val, val_len, (Item_result)type, charset, DERIVATION_IMPLICIT,
6829 (flags & binary_log::User_var_event::UNSIGNED_F));
6830 if (!is_deferred())
6831 free_root(thd->mem_root, 0);
6832 else
6833 current_thd->query_id = sav_query_id; /* restore current query's context */
6834
6835 return 0;
6836 }
6837
do_update_pos(Relay_log_info * rli)6838 int User_var_log_event::do_update_pos(Relay_log_info *rli) {
6839 rli->inc_event_relay_log_pos();
6840 return 0;
6841 }
6842
do_shall_skip(Relay_log_info * rli)6843 Log_event::enum_skip_reason User_var_log_event::do_shall_skip(
6844 Relay_log_info *rli) {
6845 /*
6846 It is a common error to set the slave skip counter to 1 instead
6847 of 2 when recovering from an insert which used a auto increment,
6848 rand, or user var. Therefore, if the slave skip counter is 1, we
6849 just say that this event should be skipped by ignoring it, meaning
6850 that we do not change the value of the slave skip counter since it
6851 will be decreased by the following insert event.
6852 */
6853 return continue_group(rli);
6854 }
6855 #endif /* MYSQL_SERVER */
6856
6857 /**************************************************************************
6858 Unknown_log_event methods
6859 **************************************************************************/
6860
6861 #ifndef MYSQL_SERVER
print(FILE *,PRINT_EVENT_INFO * print_event_info) const6862 void Unknown_log_event::print(FILE *,
6863 PRINT_EVENT_INFO *print_event_info) const {
6864 if (print_event_info->short_form) return;
6865 print_header(&print_event_info->head_cache, print_event_info, false);
6866 my_b_printf(&print_event_info->head_cache, "\n# %s", "Unknown event\n");
6867 }
6868
6869 /**************************************************************************
6870 Stop_log_event methods
6871 **************************************************************************/
6872
6873 /*
6874 Stop_log_event::print()
6875 */
6876
print(FILE *,PRINT_EVENT_INFO * print_event_info) const6877 void Stop_log_event::print(FILE *, PRINT_EVENT_INFO *print_event_info) const {
6878 if (print_event_info->short_form) return;
6879
6880 print_header(&print_event_info->head_cache, print_event_info, false);
6881 my_b_printf(&print_event_info->head_cache, "\tStop\n");
6882 }
6883 #endif /* !MYSQL_SERVER */
6884
6885 #ifdef MYSQL_SERVER
6886 /*
6887 The master stopped. We used to clean up all temporary tables but
6888 this is useless as, as the master has shut down properly, it has
6889 written all DROP TEMPORARY TABLE (prepared statements' deletion is
6890 TODO only when we binlog prep stmts). We used to clean up
6891 slave_load_tmpdir, but this is useless as it has been cleared at the
6892 end of LOAD DATA INFILE. So we have nothing to do here. The place
6893 were we must do this cleaning is in
6894 Start_log_event_v3::do_apply_event(), not here. Because if we come
6895 here, the master was sane.
6896
6897 This must only be called from the Slave SQL thread, since it calls
6898 flush_relay_log_info().
6899 */
do_update_pos(Relay_log_info * rli)6900 int Stop_log_event::do_update_pos(Relay_log_info *rli) {
6901 int error_inc = 0;
6902 int error_flush = 0;
6903 /*
6904 We do not want to update master_log pos because we get a rotate event
6905 before stop, so by now group_master_log_name is set to the next log.
6906 If we updated it, we will have incorrect master coordinates and this
6907 could give false triggers in MASTER_POS_WAIT() that we have reached
6908 the target position when in fact we have not.
6909 The group position is always unchanged in MTS mode because the event
6910 is never executed so can't be scheduled to a Worker.
6911 */
6912 if ((thd->variables.option_bits & OPTION_BEGIN) || rli->is_parallel_exec())
6913 rli->inc_event_relay_log_pos();
6914 else {
6915 error_inc = rli->inc_group_relay_log_pos(0, true /*need_data_lock=true*/);
6916 error_flush = rli->flush_info(true);
6917 }
6918 return (error_inc || error_flush);
6919 }
6920
6921 /**************************************************************************
6922 Append_block_log_event methods
6923 **************************************************************************/
6924
6925 /*
6926 Append_block_log_event ctor
6927 */
6928
Append_block_log_event(THD * thd_arg,const char * db_arg,uchar * block_arg,uint block_len_arg,bool using_trans)6929 Append_block_log_event::Append_block_log_event(THD *thd_arg, const char *db_arg,
6930 uchar *block_arg,
6931 uint block_len_arg,
6932 bool using_trans)
6933 : binary_log::Append_block_event(db_arg, block_arg, block_len_arg,
6934 thd_arg->file_id),
6935 Log_event(thd_arg, 0,
6936 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE
6937 : Log_event::EVENT_STMT_CACHE,
6938 Log_event::EVENT_NORMAL_LOGGING, header(), footer()) {
6939 common_header->set_is_valid(block != nullptr);
6940 }
6941 #endif // MYSQL_SERVER
6942
6943 /*
6944 Append_block_log_event ctor
6945 */
6946
Append_block_log_event(const char * buf,const Format_description_event * description_event)6947 Append_block_log_event::Append_block_log_event(
6948 const char *buf, const Format_description_event *description_event)
6949 : binary_log::Append_block_event(buf, description_event),
6950 Log_event(header(), footer()) {
6951 DBUG_TRACE;
6952 }
6953
6954 /*
6955 Append_block_log_event::write()
6956 */
6957
6958 #ifdef MYSQL_SERVER
write(Basic_ostream * ostream)6959 bool Append_block_log_event::write(Basic_ostream *ostream) {
6960 uchar buf[Binary_log_event::APPEND_BLOCK_HEADER_LEN];
6961 int4store(buf + AB_FILE_ID_OFFSET, file_id);
6962 return (write_header(ostream,
6963 Binary_log_event::APPEND_BLOCK_HEADER_LEN + block_len) ||
6964 wrapper_my_b_safe_write(ostream, buf,
6965 Binary_log_event::APPEND_BLOCK_HEADER_LEN) ||
6966 wrapper_my_b_safe_write(ostream, block, block_len) ||
6967 write_footer(ostream));
6968 }
6969 #endif
6970
6971 /*
6972 Append_block_log_event::print()
6973 */
6974
6975 #ifndef MYSQL_SERVER
print(FILE *,PRINT_EVENT_INFO * print_event_info) const6976 void Append_block_log_event::print(FILE *,
6977 PRINT_EVENT_INFO *print_event_info) const {
6978 if (print_event_info->short_form) return;
6979 print_header(&print_event_info->head_cache, print_event_info, false);
6980 my_b_printf(&print_event_info->head_cache,
6981 "\n#%s: file_id: %d block_len: %d\n", get_type_str(), file_id,
6982 block_len);
6983 }
6984 #endif /* !MYSQL_SERVER */
6985
6986 /*
6987 Append_block_log_event::pack_info()
6988 */
6989
6990 #if defined(MYSQL_SERVER)
pack_info(Protocol * protocol)6991 int Append_block_log_event::pack_info(Protocol *protocol) {
6992 char buf[256];
6993 size_t length;
6994 length = snprintf(buf, sizeof(buf), ";file_id=%u;block_len=%u", file_id,
6995 block_len);
6996 protocol->store_string(buf, length, &my_charset_bin);
6997 return 0;
6998 }
6999
7000 /*
7001 Append_block_log_event::get_create_or_append()
7002 */
7003
get_create_or_append() const7004 int Append_block_log_event::get_create_or_append() const {
7005 return 0; /* append to the file, fail if not exists */
7006 }
7007
7008 /*
7009 Append_block_log_event::do_apply_event()
7010 */
7011
do_apply_event(Relay_log_info const * rli)7012 int Append_block_log_event::do_apply_event(Relay_log_info const *rli) {
7013 char fname[FN_REFLEN + TEMP_FILE_MAX_LEN];
7014 int fd;
7015 int error = 1;
7016 DBUG_TRACE;
7017
7018 Applier_security_context_guard security_context{rli, thd};
7019 if (DBUG_EVALUATE_IF("skip_the_priv_check_in_begin_load", false, true)) {
7020 if (!security_context.skip_priv_checks()) {
7021 if (!security_context.has_access({FILE_ACL})) {
7022 rli->report_privilege_check_error(
7023 ERROR_LEVEL,
7024 Relay_log_info::enum_priv_checks_status::
7025 LOAD_DATA_EVENT_NOT_ALLOWED,
7026 false /* to client */);
7027 return ER_FILE_PRIVILEGE_FOR_REPLICATION_CHECKS;
7028 }
7029 }
7030 }
7031 #ifndef DBUG_OFF
7032 else { // Let's ensure that we actually skipped the privilege check since the
7033 // error code caugth in test scripts would be the same as the no-skip
7034 // case. Test scripts should wait on the below signal, if
7035 // `skip_the_priv_check_in_begin_load` has been set.
7036 const char act[] = "now SIGNAL skipped_the_priv_check_in_begin_load";
7037 DBUG_ASSERT(!debug_sync_set_action(current_thd, STRING_WITH_LEN(act)));
7038 }
7039 #endif
7040
7041 THD_STAGE_INFO(thd, stage_making_temp_file_append_before_load_data);
7042 slave_load_file_stem(fname, file_id, server_id, ".data");
7043 if (get_create_or_append()) {
7044 /*
7045 Usually lex_start() is called by mysql_parse(), but we need it here
7046 as the present method does not call mysql_parse().
7047 */
7048 lex_start(thd);
7049 mysql_reset_thd_for_next_command(thd);
7050 /* old copy may exist already */
7051 mysql_file_delete(key_file_log_event_data, fname, MYF(0));
7052 DBUG_EXECUTE_IF("simulate_file_create_error_Append_block_event",
7053 { strcat(fname, "/"); });
7054 if ((fd = mysql_file_create(key_file_log_event_data, fname, CREATE_MODE,
7055 O_WRONLY | O_EXCL | O_NOFOLLOW, MYF(MY_WME))) <
7056 0) {
7057 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
7058 "Error in %s event: could not create file '%s', '%s'",
7059 get_type_str(), fname, thd->get_stmt_da()->message_text());
7060 goto err;
7061 }
7062 } else if ((fd = mysql_file_open(key_file_log_event_data, fname,
7063 O_WRONLY | O_APPEND | O_NOFOLLOW,
7064 MYF(MY_WME))) < 0) {
7065 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
7066 "Error in %s event: could not open file '%s', '%s'",
7067 get_type_str(), fname, thd->get_stmt_da()->message_text());
7068 goto err;
7069 }
7070 DBUG_EXECUTE_IF("remove_slave_load_file_before_write",
7071 { my_delete_allow_opened(fname, MYF(0)); });
7072
7073 DBUG_EXECUTE_IF("simulate_file_write_error_Append_block_event",
7074 { mysql_file_close(fd, MYF(0)); });
7075 if (mysql_file_write(fd, block, block_len, MYF(MY_WME + MY_NABP))) {
7076 rli->report(ERROR_LEVEL, thd->get_stmt_da()->mysql_errno(),
7077 "Error in %s event: write to '%s' failed, '%s'", get_type_str(),
7078 fname, thd->get_stmt_da()->message_text());
7079 goto err;
7080 }
7081 error = 0;
7082
7083 err:
7084 if (fd >= 0) mysql_file_close(fd, MYF(0));
7085 return error;
7086 }
7087
7088 /**************************************************************************
7089 Delete_file_log_event methods
7090 **************************************************************************/
7091
7092 /*
7093 Delete_file_log_event ctor
7094 */
7095
Delete_file_log_event(THD * thd_arg,const char * db_arg,bool using_trans)7096 Delete_file_log_event::Delete_file_log_event(THD *thd_arg, const char *db_arg,
7097 bool using_trans)
7098 : binary_log::Delete_file_event(thd_arg->file_id, db_arg),
7099 Log_event(thd_arg, 0,
7100 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE
7101 : Log_event::EVENT_STMT_CACHE,
7102 Log_event::EVENT_NORMAL_LOGGING, header(), footer()) {
7103 common_header->set_is_valid(file_id != 0);
7104 }
7105 #endif // MYSQL_SERVER
7106
7107 /*
7108 Delete_file_log_event ctor
7109 */
7110
Delete_file_log_event(const char * buf,const Format_description_event * description_event)7111 Delete_file_log_event::Delete_file_log_event(
7112 const char *buf, const Format_description_event *description_event)
7113 : binary_log::Delete_file_event(buf, description_event),
7114 Log_event(header(), footer()) {
7115 DBUG_TRACE;
7116 }
7117
7118 /*
7119 Delete_file_log_event::write()
7120 */
7121
7122 #ifdef MYSQL_SERVER
write(Basic_ostream * ostream)7123 bool Delete_file_log_event::write(Basic_ostream *ostream) {
7124 uchar buf[Binary_log_event::DELETE_FILE_HEADER_LEN];
7125 int4store(buf + DF_FILE_ID_OFFSET, file_id);
7126 return (write_header(ostream, sizeof(buf)) ||
7127 wrapper_my_b_safe_write(ostream, buf, sizeof(buf)) ||
7128 write_footer(ostream));
7129 }
7130 #endif
7131
7132 /*
7133 Delete_file_log_event::print()
7134 */
7135
7136 #ifndef MYSQL_SERVER
print(FILE *,PRINT_EVENT_INFO * print_event_info) const7137 void Delete_file_log_event::print(FILE *,
7138 PRINT_EVENT_INFO *print_event_info) const {
7139 if (print_event_info->short_form) return;
7140 print_header(&print_event_info->head_cache, print_event_info, false);
7141 my_b_printf(&print_event_info->head_cache, "\n#Delete_file: file_id=%u\n",
7142 file_id);
7143 }
7144 #endif /* !MYSQL_SERVER */
7145
7146 /*
7147 Delete_file_log_event::pack_info()
7148 */
7149
7150 #if defined(MYSQL_SERVER)
pack_info(Protocol * protocol)7151 int Delete_file_log_event::pack_info(Protocol *protocol) {
7152 char buf[64];
7153 size_t length;
7154 length = snprintf(buf, sizeof(buf), ";file_id=%u", (uint)file_id);
7155 protocol->store_string(buf, length, &my_charset_bin);
7156 return 0;
7157 }
7158
7159 /*
7160 Delete_file_log_event::do_apply_event()
7161 */
7162
do_apply_event(Relay_log_info const * rli)7163 int Delete_file_log_event::do_apply_event(Relay_log_info const *rli) {
7164 char fname[FN_REFLEN + TEMP_FILE_MAX_LEN];
7165 lex_start(thd);
7166
7167 Applier_security_context_guard security_context{rli, thd};
7168 if (!security_context.skip_priv_checks()) {
7169 if (!security_context.has_access({FILE_ACL})) {
7170 rli->report_privilege_check_error(
7171 ERROR_LEVEL,
7172 Relay_log_info::enum_priv_checks_status::LOAD_DATA_EVENT_NOT_ALLOWED,
7173 false /* to client */);
7174 return ER_FILE_PRIVILEGE_FOR_REPLICATION_CHECKS;
7175 }
7176 }
7177
7178 mysql_reset_thd_for_next_command(thd);
7179 char *ext = slave_load_file_stem(fname, file_id, server_id, ".data");
7180 mysql_file_delete(key_file_log_event_data, fname, MYF(MY_WME));
7181 my_stpcpy(ext, ".info");
7182 mysql_file_delete(key_file_log_event_info, fname, MYF(MY_WME));
7183 return 0;
7184 }
7185
7186 /**************************************************************************
7187 Begin_load_query_log_event methods
7188 **************************************************************************/
7189
Begin_load_query_log_event(THD * thd_arg,const char * db_arg,uchar * block_arg,uint block_len_arg,bool using_trans)7190 Begin_load_query_log_event::Begin_load_query_log_event(THD *thd_arg,
7191 const char *db_arg,
7192 uchar *block_arg,
7193 uint block_len_arg,
7194 bool using_trans)
7195 : binary_log::Append_block_event(db_arg, block_arg, block_len_arg,
7196 thd_arg->file_id),
7197 Append_block_log_event(thd_arg, db_arg, block_arg, block_len_arg,
7198 using_trans),
7199 binary_log::Begin_load_query_event() {
7200 common_header->type_code = binary_log::BEGIN_LOAD_QUERY_EVENT;
7201 file_id = thd_arg->file_id = mysql_bin_log.next_file_id();
7202 }
7203 #endif // MYSQL_SERVER
7204
Begin_load_query_log_event(const char * buf,const Format_description_event * desc_event)7205 Begin_load_query_log_event::Begin_load_query_log_event(
7206 const char *buf, const Format_description_event *desc_event)
7207 : binary_log::Append_block_event(buf, desc_event),
7208 Append_block_log_event(buf, desc_event),
7209 binary_log::Begin_load_query_event(buf, desc_event) {
7210 DBUG_TRACE;
7211 }
7212
7213 #if defined(MYSQL_SERVER)
get_create_or_append() const7214 int Begin_load_query_log_event::get_create_or_append() const {
7215 return 1; /* create the file */
7216 }
7217
do_shall_skip(Relay_log_info * rli)7218 Log_event::enum_skip_reason Begin_load_query_log_event::do_shall_skip(
7219 Relay_log_info *rli) {
7220 /*
7221 If the slave skip counter is 1, then we should not start executing
7222 on the next event.
7223 */
7224 return continue_group(rli);
7225 }
7226
7227 /**************************************************************************
7228 Execute_load_query_log_event methods
7229 **************************************************************************/
7230
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)7231 Execute_load_query_log_event::Execute_load_query_log_event(
7232 THD *thd_arg, const char *query_arg, ulong query_length_arg,
7233 uint fn_pos_start_arg, uint fn_pos_end_arg,
7234 binary_log::enum_load_dup_handling dup_handling_arg, bool using_trans,
7235 bool immediate, bool suppress_use, int errcode)
7236 : binary_log::Query_event(
7237 query_arg, thd_arg->catalog().str, thd_arg->db().str,
7238 query_length_arg, thd_arg->thread_id(), thd_arg->variables.sql_mode,
7239 thd_arg->variables.auto_increment_increment,
7240 thd_arg->variables.auto_increment_offset,
7241 thd_arg->variables.lc_time_names->number,
7242 (ulonglong)thd_arg->table_map_for_update, errcode),
7243 Query_log_event(thd_arg, query_arg, query_length_arg, using_trans,
7244 immediate, suppress_use, errcode),
7245 binary_log::Execute_load_query_event(thd_arg->file_id, fn_pos_start_arg,
7246 fn_pos_end_arg, dup_handling_arg) {
7247 common_header->set_is_valid(Query_log_event::is_valid() && file_id != 0);
7248 common_header->type_code = binary_log::EXECUTE_LOAD_QUERY_EVENT;
7249 }
7250 #endif /* MYSQL_SERVER */
7251
Execute_load_query_log_event(const char * buf,const Format_description_event * desc_event)7252 Execute_load_query_log_event::Execute_load_query_log_event(
7253 const char *buf, const Format_description_event *desc_event)
7254 : binary_log::Query_event(buf, desc_event,
7255 binary_log::EXECUTE_LOAD_QUERY_EVENT),
7256 Query_log_event(buf, desc_event, binary_log::EXECUTE_LOAD_QUERY_EVENT),
7257 binary_log::Execute_load_query_event(buf, desc_event) {
7258 DBUG_TRACE;
7259 if (!is_valid()) return;
7260 if (!Query_log_event::is_valid()) {
7261 // clear all the variables set in execute_load_query_event
7262 file_id = 0;
7263 fn_pos_start = 0;
7264 fn_pos_end = 0;
7265 dup_handling = binary_log::LOAD_DUP_ERROR;
7266 }
7267 common_header->set_is_valid(Query_log_event::is_valid() && file_id != 0);
7268 }
7269
get_post_header_size_for_derived()7270 ulong Execute_load_query_log_event::get_post_header_size_for_derived() {
7271 return Binary_log_event::EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN;
7272 }
7273
7274 #ifdef MYSQL_SERVER
write_post_header_for_derived(Basic_ostream * ostream)7275 bool Execute_load_query_log_event::write_post_header_for_derived(
7276 Basic_ostream *ostream) {
7277 uchar buf[Binary_log_event::EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN];
7278 int4store(buf, file_id);
7279 int4store(buf + 4, fn_pos_start);
7280 int4store(buf + 4 + 4, fn_pos_end);
7281 *(buf + 4 + 4 + 4) = (uchar)dup_handling;
7282
7283 return wrapper_my_b_safe_write(
7284 ostream, buf, Binary_log_event::EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN);
7285 }
7286 #endif
7287
7288 #ifndef MYSQL_SERVER
print(FILE * file,PRINT_EVENT_INFO * print_event_info) const7289 void Execute_load_query_log_event::print(
7290 FILE *file, PRINT_EVENT_INFO *print_event_info) const {
7291 print(file, print_event_info, nullptr);
7292 }
7293
7294 /**
7295 Prints the query as LOAD DATA LOCAL and with rewritten filename.
7296 */
print(FILE *,PRINT_EVENT_INFO * print_event_info,const char * local_fname) const7297 void Execute_load_query_log_event::print(FILE *,
7298 PRINT_EVENT_INFO *print_event_info,
7299 const char *local_fname) const {
7300 IO_CACHE *const head = &print_event_info->head_cache;
7301
7302 print_query_header(head, print_event_info);
7303 /**
7304 reduce the size of io cache so that the write function is called
7305 for every call to my_b_printf().
7306 */
7307 DBUG_EXECUTE_IF("simulate_execute_event_write_error", {
7308 head->write_pos = head->write_end;
7309 DBUG_SET("+d,simulate_file_write_error");
7310 });
7311
7312 if (local_fname) {
7313 my_b_write(head, pointer_cast<const uchar *>(query), fn_pos_start);
7314 my_b_printf(head, " LOCAL INFILE ");
7315 pretty_print_str(head, local_fname, strlen(local_fname));
7316
7317 if (dup_handling == binary_log::LOAD_DUP_REPLACE)
7318 my_b_printf(head, " REPLACE");
7319 my_b_printf(head, " INTO");
7320 my_b_write(head, pointer_cast<const uchar *>(query) + fn_pos_end,
7321 q_len - fn_pos_end);
7322 my_b_printf(head, "\n%s\n", print_event_info->delimiter);
7323 } else {
7324 my_b_write(head, pointer_cast<const uchar *>(query), q_len);
7325 my_b_printf(head, "\n%s\n", print_event_info->delimiter);
7326 }
7327
7328 if (!print_event_info->short_form)
7329 my_b_printf(head, "# file_id: %d \n", file_id);
7330 }
7331 #endif
7332
7333 #if defined(MYSQL_SERVER)
pack_info(Protocol * protocol)7334 int Execute_load_query_log_event::pack_info(Protocol *protocol) {
7335 char *buf, *pos;
7336 if (!(buf = (char *)my_malloc(key_memory_log_event,
7337 9 + (db_len * 2) + 2 + q_len + 10 + 21,
7338 MYF(MY_WME))))
7339 return 1;
7340 pos = buf;
7341 if (db && db_len) {
7342 /*
7343 Statically allocates room to store '\0' and an identifier
7344 that may have NAME_LEN * 2 due to quoting and there are
7345 two quoting characters that wrap them.
7346 */
7347 char quoted_db[1 + NAME_LEN * 2 + 2]; // quoted length of the identifier
7348 size_t size = 0;
7349 size = my_strmov_quoted_identifier(this->thd, quoted_db, db, 0);
7350 pos = my_stpcpy(buf, "use ");
7351 memcpy(pos, quoted_db, size);
7352 pos = my_stpcpy(pos + size, "; ");
7353 }
7354 if (query && q_len) {
7355 memcpy(pos, query, q_len);
7356 pos += q_len;
7357 }
7358 pos = my_stpcpy(pos, " ;file_id=");
7359 pos = longlong10_to_str(file_id, pos, 10);
7360 protocol->store_string(buf, pos - buf, &my_charset_bin);
7361 my_free(buf);
7362 return 0;
7363 }
7364
do_apply_event(Relay_log_info const * rli)7365 int Execute_load_query_log_event::do_apply_event(Relay_log_info const *rli) {
7366 char *p;
7367 char *buf;
7368 char *fname;
7369 char *fname_end;
7370 int error;
7371
7372 Applier_security_context_guard security_context{rli, thd};
7373 if (!security_context.skip_priv_checks()) {
7374 if (!security_context.has_access({FILE_ACL})) {
7375 rli->report_privilege_check_error(
7376 ERROR_LEVEL,
7377 Relay_log_info::enum_priv_checks_status::LOAD_DATA_EVENT_NOT_ALLOWED,
7378 false /* to client */);
7379 return ER_FILE_PRIVILEGE_FOR_REPLICATION_CHECKS;
7380 }
7381 }
7382
7383 buf = (char *)my_malloc(key_memory_log_event,
7384 q_len + 1 - (fn_pos_end - fn_pos_start) +
7385 (FN_REFLEN + TEMP_FILE_MAX_LEN) + 10 + 8 + 5,
7386 MYF(MY_WME));
7387
7388 DBUG_EXECUTE_IF("LOAD_DATA_INFILE_has_fatal_error", my_free(buf);
7389 buf = nullptr;);
7390
7391 /* Replace filename and LOCAL keyword in query before executing it */
7392 if (buf == nullptr) {
7393 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
7394 ER_THD(thd, ER_SLAVE_FATAL_ERROR), "Not enough memory");
7395 return 1;
7396 }
7397
7398 p = buf;
7399 memcpy(p, query, fn_pos_start);
7400 p += fn_pos_start;
7401 fname = (p = strmake(p, STRING_WITH_LEN(" INFILE \'")));
7402 p = slave_load_file_stem(p, file_id, server_id, ".data");
7403 fname_end = p = strend(p); // Safer than p=p+5
7404 *(p++) = '\'';
7405 switch (dup_handling) {
7406 case binary_log::LOAD_DUP_IGNORE:
7407 p = strmake(p, STRING_WITH_LEN(" IGNORE"));
7408 break;
7409 case binary_log::LOAD_DUP_REPLACE:
7410 p = strmake(p, STRING_WITH_LEN(" REPLACE"));
7411 break;
7412 default:
7413 /* Ordinary load data */
7414 break;
7415 }
7416 p = strmake(p, STRING_WITH_LEN(" INTO "));
7417 p = strmake(p, query + fn_pos_end, q_len - fn_pos_end);
7418
7419 error = Query_log_event::do_apply_event(rli, buf, p - buf);
7420
7421 /* Forging file name for deletion in same buffer */
7422 *fname_end = 0;
7423
7424 /*
7425 If there was an error the slave is going to stop, leave the
7426 file so that we can re-execute this event at START SLAVE.
7427 */
7428 if (!error) mysql_file_delete(key_file_log_event_data, fname, MYF(MY_WME));
7429
7430 my_free(buf);
7431 return error;
7432 }
7433
7434 /*****************************************************************************
7435 Load_query_generator is used to generate the LOAD DATA statement for binlog
7436 ******************************************************************************/
7437
Load_query_generator(THD * thd_arg,const sql_exchange * ex,const char * db_arg,const char * table_name_arg,bool is_concurrent_arg,bool replace,bool ignore)7438 Load_query_generator::Load_query_generator(THD *thd_arg, const sql_exchange *ex,
7439 const char *db_arg,
7440 const char *table_name_arg,
7441 bool is_concurrent_arg, bool replace,
7442 bool ignore)
7443 : str((char *)buf, BUF_SIZE, &my_charset_bin),
7444 thd(thd_arg),
7445 sql_ex(ex),
7446 db(db_arg),
7447 table_name(table_name_arg ? table_name_arg : ""),
7448 fname(ex->file_name),
7449 is_concurrent(is_concurrent_arg),
7450 has_replace(replace),
7451 has_ignore(ignore) {
7452 str.length(0);
7453 }
7454
generate(size_t * fn_start,size_t * fn_end)7455 const String *Load_query_generator::generate(size_t *fn_start, size_t *fn_end) {
7456 DBUG_ASSERT(thd->lex->sql_command == SQLCOM_LOAD);
7457 auto cmd = down_cast<Sql_cmd_load_table *>(thd->lex->m_sql_cmd);
7458
7459 str.append("LOAD DATA ");
7460
7461 if (is_concurrent) str.append("CONCURRENT ");
7462
7463 if (fn_start) *fn_start = str.length() - 1;
7464
7465 if (cmd->m_is_local_file) str.append("LOCAL ");
7466 str.append("INFILE ");
7467 pretty_print_str(&str, fname, strlen(fname));
7468 str.append(" ");
7469
7470 if (has_replace)
7471 str.append("REPLACE ");
7472 else if (has_ignore)
7473 str.append("IGNORE ");
7474
7475 str.append("INTO");
7476 if (fn_end) *fn_end = str.length();
7477
7478 str.append(" TABLE ");
7479 str.append(table_name);
7480
7481 if (sql_ex->cs != nullptr) {
7482 str.append(" CHARACTER SET ");
7483 str.append(sql_ex->cs->csname);
7484 }
7485
7486 /* We have to create all optional fields as the default is not empty */
7487 str.append(" FIELDS TERMINATED BY ");
7488 pretty_print_str(&str, sql_ex->field.field_term);
7489
7490 if (sql_ex->field.opt_enclosed) str.append(" OPTIONALLY ");
7491 str.append(" ENCLOSED BY ");
7492 pretty_print_str(&str, sql_ex->field.enclosed);
7493
7494 str.append(" ESCAPED BY ");
7495 pretty_print_str(&str, sql_ex->field.escaped);
7496
7497 str.append(" LINES TERMINATED BY ");
7498 pretty_print_str(&str, sql_ex->line.line_term);
7499 if (sql_ex->line.line_start->length() > 0) {
7500 str.append(" STARTING BY ");
7501 pretty_print_str(&str, sql_ex->line.line_start);
7502 }
7503
7504 if (sql_ex->skip_lines > 0) {
7505 str.append(" IGNORE ");
7506 str.append_ulonglong(sql_ex->skip_lines);
7507 str.append(" LINES ");
7508 }
7509
7510 /* prepare fields-list */
7511 if (!cmd->m_opt_fields_or_vars.is_empty()) {
7512 List_iterator<Item> li(cmd->m_opt_fields_or_vars);
7513 Item *item;
7514 str.append(" (");
7515
7516 while ((item = li++)) {
7517 if (item->type() == Item::FIELD_ITEM || item->type() == Item::REF_ITEM)
7518 append_identifier(thd, &str, item->item_name.ptr(),
7519 strlen(item->item_name.ptr()));
7520 else
7521 item->print(thd, &str, QT_ORDINARY);
7522 str.append(", ");
7523 }
7524 // remvoe the last ", "
7525 str.length(str.length() - 2);
7526 str.append(')');
7527 }
7528
7529 if (!cmd->m_opt_set_fields.is_empty()) {
7530 List_iterator<Item> lu(cmd->m_opt_set_fields);
7531 List_iterator<String> ls(*cmd->m_opt_set_expr_strings);
7532 Item *item;
7533
7534 str.append(" SET ");
7535
7536 while ((item = lu++)) {
7537 String *s = ls++;
7538
7539 append_identifier(thd, &str, item->item_name.ptr(),
7540 strlen(item->item_name.ptr()));
7541 str.append(*s);
7542 str.append(", ");
7543 }
7544 // remvoe the last ", "
7545 str.length(str.length() - 2);
7546 }
7547
7548 return &str;
7549 }
7550
7551 #endif // MYSQL_SERVER
7552 #ifndef DBUG_OFF
7553 #ifdef MYSQL_SERVER
7554 static uchar dbug_extra_row_ndb_info_val = 0;
7555
7556 /**
7557 set_extra_data
7558
7559 Called during self-test to generate various
7560 self-consistent binlog row event extra
7561 thread data structures which can be checked
7562 when reading the binlog.
7563
7564 @param arr Buffer to use
7565 */
set_extra_data(uchar * arr)7566 static const uchar *set_extra_data(uchar *arr) {
7567 uchar val = (dbug_extra_row_ndb_info_val++) %
7568 (EXTRA_ROW_INFO_MAX_PAYLOAD + 1); /* 0 .. MAX_PAYLOAD + 1 */
7569 arr[EXTRA_ROW_INFO_LEN_OFFSET] = val + EXTRA_ROW_INFO_HEADER_LENGTH;
7570 arr[EXTRA_ROW_INFO_FORMAT_OFFSET] = val;
7571 for (uchar i = 0; i < val; i++) arr[EXTRA_ROW_INFO_HEADER_LENGTH + i] = val;
7572
7573 return arr;
7574 }
7575
7576 #endif // #ifdef MYSQL_SERVER
7577
7578 /**
7579 check_extra_row_ndb_info
7580
7581 Called during self-test to check that
7582 binlog row event extra data is self-
7583 consistent as defined by the set_extra_data
7584 function above.
7585
7586 Will assert(false) if not.
7587 */
check_extra_row_ndb_info(uchar * extra_row_ndb_info)7588 static void check_extra_row_ndb_info(uchar *extra_row_ndb_info) {
7589 assert(extra_row_ndb_info);
7590 size_t len = extra_row_ndb_info[EXTRA_ROW_INFO_LEN_OFFSET];
7591 size_t val = len - EXTRA_ROW_INFO_HEADER_LENGTH;
7592 assert(extra_row_ndb_info[EXTRA_ROW_INFO_FORMAT_OFFSET] == val);
7593 for (size_t i = 0; i < val; i++) {
7594 assert(extra_row_ndb_info[EXTRA_ROW_INFO_HEADER_LENGTH + i] == val);
7595 }
7596 }
7597
7598 #endif // #ifndef DBUG_OFF
7599
get_rpl_part_id(partition_info * part_info)7600 int get_rpl_part_id(partition_info *part_info) {
7601 uint32_t part_id = binary_log::Rows_event::Extra_row_info::UNDEFINED;
7602 longlong func_value;
7603 if (part_info != nullptr) {
7604 part_info->get_partition_id(part_info, &part_id, &func_value);
7605 }
7606 return static_cast<int>(part_id);
7607 }
7608
7609 /**************************************************************************
7610 Rows_log_event member functions
7611 **************************************************************************/
7612
7613 #ifdef MYSQL_SERVER
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 unsigned char * extra_row_ndb_info)7614 Rows_log_event::Rows_log_event(THD *thd_arg, TABLE *tbl_arg,
7615 const Table_id &tid, MY_BITMAP const *cols,
7616 bool using_trans, Log_event_type event_type,
7617 const unsigned char *extra_row_ndb_info)
7618 : binary_log::Rows_event(event_type),
7619 Log_event(thd_arg, 0,
7620 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE
7621 : Log_event::EVENT_STMT_CACHE,
7622 Log_event::EVENT_NORMAL_LOGGING, header(), footer()),
7623 m_curr_row(nullptr),
7624 m_curr_row_end(nullptr),
7625 m_key(nullptr),
7626 m_key_info(nullptr),
7627 m_distinct_keys(Key_compare(&m_key_info)),
7628 m_distinct_key_spare_buf(nullptr),
7629 m_fields{tbl_arg, Replicated_columns_view::OUTBOUND} {
7630 DBUG_TRACE;
7631 common_header->type_code = event_type;
7632 m_row_count = 0;
7633 m_table_id = tid;
7634 m_width = tbl_arg ? this->m_fields.filtered_size() : 1;
7635 m_rows_buf = nullptr;
7636 m_rows_cur = nullptr;
7637 m_rows_end = nullptr;
7638 m_flags = 0;
7639 m_type = event_type;
7640
7641 DBUG_ASSERT(tbl_arg && tbl_arg->s && tid.is_valid());
7642
7643 if (thd_arg->variables.option_bits & OPTION_NO_FOREIGN_KEY_CHECKS)
7644 set_flags(NO_FOREIGN_KEY_CHECKS_F);
7645 if (thd_arg->variables.option_bits & OPTION_RELAXED_UNIQUE_CHECKS)
7646 set_flags(RELAXED_UNIQUE_CHECKS_F);
7647 #ifndef DBUG_OFF
7648 uchar extra_data[255];
7649 DBUG_EXECUTE_IF("extra_row_ndb_info_set",
7650 /* Set extra row data to a known value */
7651 extra_row_ndb_info = set_extra_data(extra_data););
7652 #endif
7653 partition_info *part_info = tbl_arg->part_info;
7654 auto part_id = get_rpl_part_id(part_info);
7655 if (part_id != binary_log::Rows_event::Extra_row_info::UNDEFINED) {
7656 m_extra_row_info.set_partition_id(part_id);
7657 }
7658 /* Copy Extra ndb data from thd into new event */
7659 if (extra_row_ndb_info) {
7660 /* Copy Extra data from thd into new event */
7661 int extra_row_ndb_info_len = extra_row_ndb_info[EXTRA_ROW_INFO_LEN_OFFSET];
7662 DBUG_ASSERT(extra_row_ndb_info_len >= EXTRA_ROW_INFO_HEADER_LENGTH);
7663
7664 m_extra_row_info.set_ndb_info(extra_row_ndb_info, extra_row_ndb_info_len);
7665 }
7666
7667 /* if bitmap_init fails, caught in is_valid() */
7668 if (likely(!bitmap_init(&m_cols,
7669 m_width <= sizeof(m_bitbuf) * 8 ? m_bitbuf : nullptr,
7670 m_width))) {
7671 /* Cols can be zero if this is a dummy binrows event */
7672 if (likely(cols != nullptr)) {
7673 memcpy(m_cols.bitmap, cols->bitmap, no_bytes_in_map(cols));
7674 create_last_word_mask(&m_cols);
7675 }
7676 } else {
7677 // Needed because bitmap_init() does not set it to null on failure
7678 m_cols.bitmap = nullptr;
7679 }
7680
7681 if (bitmap_init(&write_set_backup, nullptr, tbl_arg->s->fields)) {
7682 write_set_backup.bitmap = nullptr; /* purecov: deadcode */
7683 }
7684
7685 /*
7686 -Check that malloc() succeeded in allocating memory for the rows
7687 buffer and the COLS vector.
7688 -Checking that an Update_rows_log_event
7689 is valid is done while setting the Update_rows_log_event::is_valid
7690 */
7691 common_header->set_is_valid(m_rows_buf && m_cols.bitmap &&
7692 write_set_backup.bitmap);
7693 }
7694 #endif
7695
Rows_log_event(const char * buf,const Format_description_event * description_event)7696 Rows_log_event::Rows_log_event(
7697 const char *buf, const Format_description_event *description_event)
7698 : binary_log::Rows_event(buf, description_event),
7699 Log_event(header(), footer()),
7700 m_row_count(0),
7701 #ifdef MYSQL_SERVER
7702 m_table(nullptr),
7703 #endif
7704 m_rows_buf(nullptr),
7705 m_rows_cur(nullptr),
7706 m_rows_end(nullptr)
7707 #if defined(MYSQL_SERVER)
7708 ,
7709 m_curr_row(nullptr),
7710 m_curr_row_end(nullptr),
7711 m_key(nullptr),
7712 m_key_info(nullptr),
7713 m_distinct_keys(Key_compare(&m_key_info)),
7714 m_distinct_key_spare_buf(nullptr),
7715 m_fields(Replicated_columns_view::INBOUND)
7716 #endif
7717 {
7718 DBUG_TRACE;
7719 if (!is_valid()) return;
7720
7721 DBUG_ASSERT(header()->type_code == m_type);
7722
7723 if (m_extra_row_info.have_ndb_info())
7724 DBUG_EXECUTE_IF("extra_row_ndb_info_check",
7725 /* Check extra data has expected value */
7726 check_extra_row_ndb_info(m_extra_row_info.get_ndb_info()););
7727
7728 /*
7729 m_cols and m_cols_ai are of the type MY_BITMAP, which are members of
7730 class Rows_log_event, and are used while applying the row events on
7731 the slave.
7732 The bitmap integer is initialized by copying the contents of the
7733 vector column_before_image for m_cols.bitamp, and vector
7734 column_after_image for m_cols_ai.bitmap. m_cols_ai is only initialized
7735 for UPDATE_ROWS_EVENTS, else it is equal to the before image.
7736 */
7737 /* if bitmap_init fails, is_valid will be set to false */
7738 if (likely(!bitmap_init(&m_cols,
7739 m_width <= sizeof(m_bitbuf) * 8 ? m_bitbuf : nullptr,
7740 m_width))) {
7741 if (!columns_before_image.empty()) {
7742 memcpy(m_cols.bitmap, &columns_before_image[0], n_bits_len);
7743 create_last_word_mask(&m_cols);
7744 DBUG_DUMP("m_cols", (uchar *)m_cols.bitmap, no_bytes_in_map(&m_cols));
7745 } // end if columns_before_image.empty()
7746 else {
7747 if (m_cols.bitmap != m_bitbuf) bitmap_free(&m_cols);
7748 m_cols.bitmap = nullptr;
7749 }
7750 } else {
7751 // Needed because bitmap_init() does not set it to null on failure
7752 m_cols.bitmap = nullptr;
7753 common_header->set_is_valid(false);
7754 return;
7755 }
7756 m_cols_ai.bitmap =
7757 m_cols.bitmap; // See explanation below while setting is_valid.
7758
7759 if (m_type == binary_log::UPDATE_ROWS_EVENT ||
7760 m_type == binary_log::UPDATE_ROWS_EVENT_V1 ||
7761 m_type == binary_log::PARTIAL_UPDATE_ROWS_EVENT) {
7762 /* if bitmap_init fails, is_valid will be set to false*/
7763 if (likely(!bitmap_init(
7764 &m_cols_ai,
7765 m_width <= sizeof(m_bitbuf_ai) * 8 ? m_bitbuf_ai : nullptr,
7766 m_width))) {
7767 if (!columns_after_image.empty()) {
7768 memcpy(m_cols_ai.bitmap, &columns_after_image[0], n_bits_len);
7769 create_last_word_mask(&m_cols_ai);
7770 DBUG_DUMP("m_cols_ai", (uchar *)m_cols_ai.bitmap,
7771 no_bytes_in_map(&m_cols_ai));
7772 } else {
7773 if (m_cols_ai.bitmap != m_bitbuf_ai) bitmap_free(&m_cols_ai);
7774 m_cols_ai.bitmap = nullptr;
7775 }
7776 } else {
7777 // Needed because bitmap_init() does not set it to null on failure
7778 m_cols_ai.bitmap = nullptr;
7779 common_header->set_is_valid(false);
7780 return;
7781 }
7782 }
7783
7784 /*
7785 m_rows_buf, m_curr_row and m_rows_end are pointers to the vector rows.
7786 m_rows_buf is the pointer to the first byte of first row in the event.
7787 m_curr_row points to current row being applied on the slave. Initially,
7788 this points to the same element as m_rows_buf in the vector.
7789 m_rows_end points to the last byte in the last row in the event.
7790
7791 These pointers are used while applying the events on to the slave, and
7792 are not required for decoding.
7793 */
7794 if (likely(!row.empty())) {
7795 m_rows_buf = &row[0];
7796 #if defined(MYSQL_SERVER)
7797 m_curr_row = m_rows_buf;
7798 #endif
7799 m_rows_end = m_rows_buf + row.size() - 1;
7800 m_rows_cur = m_rows_end;
7801 }
7802
7803 if (bitmap_init(&write_set_backup, nullptr, m_cols.n_bits)) {
7804 write_set_backup.bitmap = nullptr; /* purecov: deadcode */
7805 }
7806
7807 /*
7808 -Check that malloc() succeeded in allocating memory for the row
7809 buffer and the COLS vector.
7810 */
7811 common_header->set_is_valid(m_rows_buf && m_cols.bitmap &&
7812 write_set_backup.bitmap);
7813 }
7814
~Rows_log_event()7815 Rows_log_event::~Rows_log_event() {
7816 if (m_cols.bitmap) {
7817 if (m_cols.bitmap == m_bitbuf) // no my_malloc happened
7818 m_cols.bitmap = nullptr; // so no my_free in bitmap_free
7819 bitmap_free(&m_cols); // To pair with bitmap_init().
7820 }
7821 if (this->m_local_cols_ai.bitmap != nullptr &&
7822 this->m_local_cols_ai.bitmap != this->m_local_cols.bitmap) {
7823 bitmap_free(&this->m_local_cols_ai);
7824 }
7825 if (this->m_local_cols.bitmap != nullptr) {
7826 bitmap_free(&this->m_local_cols);
7827 }
7828
7829 if (write_set_backup.bitmap) {
7830 bitmap_free(&write_set_backup);
7831 }
7832 }
7833
7834 #ifdef MYSQL_SERVER
unpack_current_row(const Relay_log_info * const rli,MY_BITMAP const * cols,bool is_after_image,bool only_seek)7835 int Rows_log_event::unpack_current_row(const Relay_log_info *const rli,
7836 MY_BITMAP const *cols,
7837 bool is_after_image, bool only_seek) {
7838 DBUG_ASSERT(m_table);
7839
7840 enum_row_image_type row_image_type;
7841 if (is_after_image) {
7842 DBUG_ASSERT(get_general_type_code() != binary_log::DELETE_ROWS_EVENT);
7843 row_image_type = (get_general_type_code() == binary_log::UPDATE_ROWS_EVENT)
7844 ? enum_row_image_type::UPDATE_AI
7845 : enum_row_image_type::WRITE_AI;
7846 } else {
7847 DBUG_ASSERT(get_general_type_code() != binary_log::WRITE_ROWS_EVENT);
7848 row_image_type = (get_general_type_code() == binary_log::UPDATE_ROWS_EVENT)
7849 ? enum_row_image_type::UPDATE_BI
7850 : enum_row_image_type::DELETE_BI;
7851 }
7852 bool has_value_options =
7853 (get_type_code() == binary_log::PARTIAL_UPDATE_ROWS_EVENT);
7854 ASSERT_OR_RETURN_ERROR(m_curr_row <= m_rows_end, HA_ERR_CORRUPT_EVENT);
7855 if (::unpack_row(rli, m_table, m_width, m_curr_row, cols, &m_curr_row_end,
7856 m_rows_end, row_image_type, has_value_options, only_seek)) {
7857 int error = thd->get_stmt_da()->mysql_errno();
7858 DBUG_ASSERT(error);
7859 return error;
7860 }
7861
7862 // After the row is unpacked, we need to update all hidden generated columns
7863 // for functional indexes since those values are not included in the binlog
7864 // in any mode of binlog_row_image.
7865 if (is_after_image &&
7866 !bitmap_is_clear_all(&m_table->fields_for_functional_indexes)) {
7867 // If there are a different number of columns on the master and slave, we
7868 // need to adjust the backup bitmap since the bitmap was initialized with
7869 // the number of columns on the master.
7870 if (write_set_backup.n_bits != m_table->s->fields) {
7871 bitmap_free(&write_set_backup);
7872 if (bitmap_init(&write_set_backup, nullptr, m_table->s->fields)) {
7873 return HA_ERR_OUT_OF_MEM; /* purecov: deadcode */
7874 }
7875 }
7876
7877 // Make a copy of the write set, and mark all hidden generated columns.
7878 bitmap_copy(&write_set_backup, m_table->write_set);
7879 bitmap_union(m_table->write_set, &m_table->fields_for_functional_indexes);
7880
7881 // Calculate the values for all hidden generated columns.
7882 bool res = update_generated_write_fields(
7883 &m_table->fields_for_functional_indexes, m_table);
7884
7885 // Restore the write set.
7886 bitmap_copy(m_table->write_set, &write_set_backup);
7887 if (res) {
7888 return thd->get_stmt_da()->mysql_errno(); /* purecov: deadcode */
7889 }
7890 }
7891
7892 return 0;
7893 }
7894 #endif // ifdef MYSQL_SERVER
7895
get_data_size()7896 size_t Rows_log_event::get_data_size() {
7897 int const general_type_code = get_general_type_code();
7898
7899 uchar buf[sizeof(m_width) + 1];
7900 uchar *end = net_store_length(buf, m_width);
7901
7902 DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master",
7903 return 6 + no_bytes_in_map(&m_cols) + (end - buf) +
7904 (general_type_code == binary_log::UPDATE_ROWS_EVENT
7905 ? no_bytes_in_map(&m_cols_ai)
7906 : 0) +
7907 (m_rows_cur - m_rows_buf););
7908
7909 int data_size = 0;
7910 bool is_v2_event =
7911 common_header->type_code > binary_log::DELETE_ROWS_EVENT_V1;
7912 if (is_v2_event) {
7913 data_size = Binary_log_event::ROWS_HEADER_LEN_V2;
7914 if (m_extra_row_info.have_ndb_info())
7915 data_size +=
7916 EXTRA_ROW_INFO_TYPECODE_LENGTH + m_extra_row_info.get_ndb_length();
7917
7918 if (m_extra_row_info.have_part())
7919 data_size +=
7920 EXTRA_ROW_INFO_TYPECODE_LENGTH + m_extra_row_info.get_part_length();
7921 } else {
7922 data_size = Binary_log_event::ROWS_HEADER_LEN_V1;
7923 }
7924 data_size += no_bytes_in_map(&m_cols);
7925 data_size += (uint)(end - buf);
7926
7927 if (general_type_code == binary_log::UPDATE_ROWS_EVENT)
7928 data_size += no_bytes_in_map(&m_cols_ai);
7929
7930 data_size += (uint)(m_rows_cur - m_rows_buf);
7931 return data_size;
7932 }
7933
7934 #ifdef MYSQL_SERVER
do_add_row_data(uchar * row_data,size_t length)7935 int Rows_log_event::do_add_row_data(uchar *row_data, size_t length) {
7936 /*
7937 When the table has a primary key, we would probably want, by default, to
7938 log only the primary key value instead of the entire "before image". This
7939 would save binlog space. TODO
7940 */
7941 DBUG_TRACE;
7942 DBUG_PRINT("enter", ("row_data: %p length: %lu", row_data, (ulong)length));
7943
7944 /*
7945 If length is zero, there is nothing to write, so we just
7946 return. Note that this is not an optimization, since calling
7947 realloc() with size 0 means free().
7948 */
7949 if (length == 0) {
7950 m_row_count++;
7951 return 0;
7952 }
7953
7954 DBUG_DUMP("row_data", row_data, min<size_t>(length, 32));
7955
7956 DBUG_ASSERT(m_rows_buf <= m_rows_cur);
7957 DBUG_ASSERT(!m_rows_buf || (m_rows_end && m_rows_buf < m_rows_end));
7958 DBUG_ASSERT(m_rows_cur <= m_rows_end);
7959
7960 /* The cast will always work since m_rows_cur <= m_rows_end */
7961 if (static_cast<size_t>(m_rows_end - m_rows_cur) <= length) {
7962 size_t const block_size = 1024;
7963 ulong cur_size = m_rows_cur - m_rows_buf;
7964 DBUG_EXECUTE_IF("simulate_too_big_row_case1",
7965 cur_size = UINT_MAX32 - (block_size * 10);
7966 length = UINT_MAX32 - (block_size * 10););
7967 DBUG_EXECUTE_IF("simulate_too_big_row_case2",
7968 cur_size = UINT_MAX32 - (block_size * 10);
7969 length = block_size * 10;);
7970 DBUG_EXECUTE_IF("simulate_too_big_row_case3", cur_size = block_size * 10;
7971 length = UINT_MAX32 - (block_size * 10););
7972 DBUG_EXECUTE_IF("simulate_too_big_row_case4",
7973 cur_size = UINT_MAX32 - (block_size * 10);
7974 length = (block_size * 10) - block_size + 1;);
7975 ulong remaining_space = UINT_MAX32 - cur_size;
7976 /* Check that the new data fits within remaining space and we can add
7977 block_size without wrapping.
7978 */
7979 if (length > remaining_space || ((length + block_size) > remaining_space)) {
7980 LogErr(ERROR_LEVEL, ER_ROW_DATA_TOO_BIG_TO_WRITE_IN_BINLOG);
7981 return ER_BINLOG_ROW_LOGGING_FAILED;
7982 }
7983 const size_t new_alloc =
7984 block_size * ((cur_size + length + block_size - 1) / block_size);
7985 if (new_alloc) row.resize(new_alloc);
7986
7987 /* If the memory moved, we need to move the pointers */
7988 if (new_alloc && &row[0] != m_rows_buf) {
7989 m_rows_buf = &row[0];
7990 common_header->set_is_valid(m_rows_buf && m_cols.bitmap);
7991 m_rows_cur = m_rows_buf + cur_size;
7992 }
7993
7994 /*
7995 The end pointer should always be changed to point to the end of
7996 the allocated memory.
7997 */
7998 m_rows_end = m_rows_buf + new_alloc;
7999 }
8000
8001 DBUG_ASSERT(m_rows_cur + length <= m_rows_end);
8002 memcpy(m_rows_cur, row_data, length);
8003 m_rows_cur += length;
8004 m_row_count++;
8005 return 0;
8006 }
8007
8008 /**
8009 Checks if any of the columns in the given table is
8010 signaled in the bitmap.
8011
8012 For each column in the given table checks if it is
8013 signaled in the bitmap. This is most useful when deciding
8014 whether a before image (BI) can be used or not for
8015 searching a row. If no column is signaled, then the
8016 image cannot be used for searching a record (regardless
8017 of using position(), index scan or table scan). Here is
8018 an example:
8019
8020 MASTER> SET @@binlog_row_image='MINIMAL';
8021 MASTER> CREATE TABLE t1 (a int, b int, c int, primary key(c));
8022 SLAVE> CREATE TABLE t1 (a int, b int);
8023 MASTER> INSERT INTO t1 VALUES (1,2,3);
8024 MASTER> UPDATE t1 SET a=2 WHERE b=2;
8025
8026 For the update statement only the PK (column c) is
8027 logged in the before image (BI). As such, given that
8028 the slave has no column c, it will not be able to
8029 find the row, because BI has no values for the columns
8030 the slave knows about (column a and b).
8031
8032 @param table the table reference on the slave.
8033 @param cols the bitmap signaling columns available in
8034 the BI.
8035
8036 @return true if BI contains usable colums for searching,
8037 false otherwise.
8038 */
is_any_column_signaled_for_table(TABLE * table,MY_BITMAP * cols)8039 static bool is_any_column_signaled_for_table(TABLE *table, MY_BITMAP *cols) {
8040 DBUG_TRACE;
8041
8042 for (Field **ptr = table->field;
8043 *ptr && ((*ptr)->field_index() < cols->n_bits); ptr++) {
8044 if (bitmap_is_set(cols, (*ptr)->field_index())) return true;
8045 }
8046
8047 return false;
8048 }
8049
8050 /**
8051 Checks if the fields in the given key are signaled in
8052 the bitmap.
8053
8054 Validates whether the before image is usable for the
8055 given key. It can be the case that the before image
8056 does not contain values for the key (eg, master was
8057 using 'minimal' option for image logging and slave has
8058 different index structure on the table). Here is an
8059 example:
8060
8061 MASTER> SET @@binlog_row_image='MINIMAL';
8062 MASTER> CREATE TABLE t1 (a int, b int, c int, primary key(c));
8063 SLAVE> CREATE TABLE t1 (a int, b int, c int, key(a,c));
8064 MASTER> INSERT INTO t1 VALUES (1,2,3);
8065 MASTER> UPDATE t1 SET a=2 WHERE b=2;
8066
8067 When finding the row on the slave, one cannot use the
8068 index (a,c) to search for the row, because there is only
8069 data in the before image for column c. This function
8070 checks the fields needed for a given key and searches
8071 the bitmap to see if all the fields required are
8072 signaled.
8073
8074 @param keyinfo reference to key.
8075 @param cols the bitmap signaling which columns
8076 have available data.
8077
8078 @return true if all fields are signaled in the bitmap
8079 for the given key, false otherwise.
8080 */
are_all_columns_signaled_for_key(KEY * keyinfo,MY_BITMAP * cols)8081 static bool are_all_columns_signaled_for_key(KEY *keyinfo, MY_BITMAP *cols) {
8082 DBUG_TRACE;
8083
8084 for (uint i = 0; i < keyinfo->user_defined_key_parts; i++) {
8085 uint fieldnr = keyinfo->key_part[i].fieldnr - 1;
8086 if (fieldnr >= cols->n_bits || !bitmap_is_set(cols, fieldnr)) return false;
8087 }
8088
8089 return true;
8090 }
8091
8092 /**
8093 Searches the table for a given key that can be used
8094 according to the existing values, ie, columns set
8095 in the bitmap.
8096
8097 The caller can specify which type of key to find by
8098 setting the following flags in the key_type parameter:
8099
8100 - PRI_KEY_FLAG
8101 Returns the primary key.
8102
8103 - UNIQUE_KEY_FLAG
8104 Returns a unique key (flagged with HA_NOSAME)
8105
8106 - MULTIPLE_KEY_FLAG
8107 Returns a key that is not unique (flagged with HA_NOSAME
8108 and without HA_NULL_PART_KEY) nor PK.
8109
8110 The above flags can be used together, in which case, the
8111 search is conducted in the above listed order. Eg, the
8112 following flag:
8113
8114 (PRI_KEY_FLAG | UNIQUE_KEY_FLAG | MULTIPLE_KEY_FLAG)
8115
8116 means that a primary key is returned if it is suitable. If
8117 not then the unique keys are searched. If no unique key is
8118 suitable, then the keys are searched. Finally, if no key
8119 is suitable, MAX_KEY is returned.
8120
8121 @param table reference to the table.
8122 @param bi_cols a bitmap that filters out columns that should
8123 not be considered while searching the key.
8124 Columns that should be considered are set.
8125 @param key_type the type of key to search for.
8126
8127 @return MAX_KEY if no key, according to the key_type specified
8128 is suitable. Returns the key otherwise.
8129
8130 */
search_key_in_table(TABLE * table,MY_BITMAP * bi_cols,uint key_type)8131 static uint search_key_in_table(TABLE *table, MY_BITMAP *bi_cols,
8132 uint key_type) {
8133 DBUG_TRACE;
8134
8135 KEY *keyinfo;
8136 uint res = MAX_KEY;
8137 uint key;
8138
8139 if (key_type & PRI_KEY_FLAG && (table->s->primary_key < MAX_KEY)) {
8140 DBUG_PRINT("debug", ("Searching for PK"));
8141 keyinfo = table->s->key_info + table->s->primary_key;
8142 if (are_all_columns_signaled_for_key(keyinfo, bi_cols))
8143 return table->s->primary_key;
8144 }
8145
8146 if (key_type & UNIQUE_KEY_FLAG) {
8147 DBUG_PRINT("debug", ("Searching for UK"));
8148 for (key = 0, keyinfo = table->key_info;
8149 (key < table->s->keys) && (res == MAX_KEY); key++, keyinfo++) {
8150 /*
8151 - Unique keys cannot be disabled, thence we skip the check.
8152 - Skip unique keys with nullable parts
8153 - Skip primary keys
8154 - Skip functional indexes if the slave_rows_search_algorithms=INDEX_SCAN
8155 - Skip multi-valued keys as they have only part of value and can't
8156 fully identify a record
8157 */
8158 if (!((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME) ||
8159 (key == table->s->primary_key) ||
8160 ((slave_rows_search_algorithms_options & SLAVE_ROWS_INDEX_SCAN) &&
8161 keyinfo->is_functional_index()) ||
8162 keyinfo->flags & HA_MULTI_VALUED_KEY) {
8163 continue;
8164 }
8165 res = are_all_columns_signaled_for_key(keyinfo, bi_cols) ? key : MAX_KEY;
8166
8167 if (res < MAX_KEY) return res;
8168 }
8169 DBUG_PRINT("debug", ("UK has NULLABLE parts or not all columns signaled."));
8170 }
8171
8172 if (key_type & MULTIPLE_KEY_FLAG && table->s->keys) {
8173 DBUG_PRINT("debug", ("Searching for K."));
8174 for (key = 0, keyinfo = table->key_info;
8175 (key < table->s->keys) && (res == MAX_KEY); key++, keyinfo++) {
8176 /*
8177 The following indexes are skipped:
8178 - Inactive/invisible indexes.
8179 - UNIQUE NOT NULL indexes.
8180 - Indexes that do not support ha_index_next() e.g. full-text.
8181 - Primary key indexes.
8182 - Functional indexes if the slave_rows_search_algorithms=INDEX_SCAN
8183 - Skip multi-valued keys as they have only part of value and can't
8184 fully identify a record
8185 */
8186 if (!(table->s->usable_indexes(current_thd).is_set(key)) ||
8187 ((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY)) == HA_NOSAME) ||
8188 !(table->file->index_flags(key, 0, true) & HA_READ_NEXT) ||
8189 (key == table->s->primary_key) ||
8190 ((slave_rows_search_algorithms_options & SLAVE_ROWS_INDEX_SCAN) &&
8191 keyinfo->is_functional_index()) ||
8192 keyinfo->flags & HA_MULTI_VALUED_KEY) {
8193 continue;
8194 }
8195
8196 res = are_all_columns_signaled_for_key(keyinfo, bi_cols) ? key : MAX_KEY;
8197
8198 if (res < MAX_KEY) return res;
8199 }
8200 DBUG_PRINT("debug", ("Not all columns signaled for K."));
8201 }
8202
8203 return res;
8204 }
8205
decide_row_lookup_algorithm_and_key()8206 void Rows_log_event::decide_row_lookup_algorithm_and_key() {
8207 DBUG_TRACE;
8208
8209 /*
8210 Decision table:
8211 - I --> Index scan / search
8212 - T --> Table scan
8213 - Hi --> Hash over index
8214 - Ht --> Hash over the entire table
8215
8216 |--------------+-----------+------+------+------|
8217 | Index\Option | I , T , H | I, T | I, H | T, H |
8218 |--------------+-----------+------+------+------|
8219 | PK / UK | I | I | I | Hi |
8220 | K | Hi | I | Hi | Hi |
8221 | No Index | Ht | T | Ht | Ht |
8222 |--------------+-----------+------+------+------|
8223
8224 */
8225 TABLE *table = this->m_table;
8226 uint event_type = this->get_general_type_code();
8227 MY_BITMAP *cols = &this->m_cols;
8228 this->m_rows_lookup_algorithm = ROW_LOOKUP_NOT_NEEDED;
8229 this->m_key_index = MAX_KEY;
8230 this->m_key_info = nullptr;
8231
8232 if (event_type == binary_log::WRITE_ROWS_EVENT) // row lookup not needed
8233 return;
8234
8235 if (!(slave_rows_search_algorithms_options & SLAVE_ROWS_INDEX_SCAN))
8236 goto TABLE_OR_INDEX_HASH_SCAN;
8237
8238 /* PK or UK => use LOOKUP_INDEX_SCAN */
8239 this->m_key_index =
8240 search_key_in_table(table, cols, (PRI_KEY_FLAG | UNIQUE_KEY_FLAG));
8241 if (this->m_key_index != MAX_KEY) {
8242 DBUG_PRINT("info",
8243 ("decide_row_lookup_algorithm_and_key: decided - INDEX_SCAN"));
8244 this->m_rows_lookup_algorithm = ROW_LOOKUP_INDEX_SCAN;
8245 goto end;
8246 }
8247
8248 TABLE_OR_INDEX_HASH_SCAN:
8249
8250 /*
8251 NOTE: Engines like Blackhole cannot use HASH_SCAN, because
8252 they do not syncronize reads .
8253 */
8254 if (!(slave_rows_search_algorithms_options & SLAVE_ROWS_HASH_SCAN) ||
8255 (table->file->ha_table_flags() & HA_READ_OUT_OF_SYNC))
8256 goto TABLE_OR_INDEX_FULL_SCAN;
8257
8258 /* search for a key to see if we can narrow the lookup domain further. */
8259 this->m_key_index = search_key_in_table(
8260 table, cols, (PRI_KEY_FLAG | UNIQUE_KEY_FLAG | MULTIPLE_KEY_FLAG));
8261 this->m_rows_lookup_algorithm = ROW_LOOKUP_HASH_SCAN;
8262 if (m_key_index < MAX_KEY)
8263 m_distinct_key_spare_buf =
8264 (uchar *)thd->alloc(table->key_info[m_key_index].key_length);
8265 DBUG_PRINT("info",
8266 ("decide_row_lookup_algorithm_and_key: decided - HASH_SCAN"));
8267 goto end;
8268
8269 TABLE_OR_INDEX_FULL_SCAN:
8270
8271 this->m_key_index = MAX_KEY;
8272
8273 /* If we can use an index, try to narrow the scan a bit further. */
8274 if (slave_rows_search_algorithms_options & SLAVE_ROWS_INDEX_SCAN)
8275 this->m_key_index = search_key_in_table(
8276 table, cols, (PRI_KEY_FLAG | UNIQUE_KEY_FLAG | MULTIPLE_KEY_FLAG));
8277
8278 if (this->m_key_index != MAX_KEY) {
8279 DBUG_PRINT("info",
8280 ("decide_row_lookup_algorithm_and_key: decided - INDEX_SCAN"));
8281 this->m_rows_lookup_algorithm = ROW_LOOKUP_INDEX_SCAN;
8282 } else {
8283 DBUG_PRINT("info",
8284 ("decide_row_lookup_algorithm_and_key: decided - TABLE_SCAN"));
8285 this->m_rows_lookup_algorithm = ROW_LOOKUP_TABLE_SCAN;
8286 }
8287
8288 end:
8289 /* m_key_index is ready, set m_key_info now. */
8290 m_key_info = m_table->key_info + m_key_index;
8291 /*
8292 m_key_info will influence key comparison code in HASH_SCAN mode,
8293 so the m_distinct_keys set should still be empty.
8294 */
8295 DBUG_ASSERT(m_distinct_keys.empty());
8296
8297 #ifndef DBUG_OFF
8298 const char *s =
8299 ((m_rows_lookup_algorithm == Rows_log_event::ROW_LOOKUP_TABLE_SCAN)
8300 ? "TABLE_SCAN"
8301 : ((m_rows_lookup_algorithm == Rows_log_event::ROW_LOOKUP_HASH_SCAN)
8302 ? "HASH_SCAN"
8303 : "INDEX_SCAN"));
8304
8305 // only for testing purposes
8306 slave_rows_last_search_algorithm_used = m_rows_lookup_algorithm;
8307 DBUG_PRINT("debug", ("Row lookup method: %s", s));
8308 #endif
8309 }
8310
8311 /*
8312 Encapsulates the operations to be done before applying
8313 row events for update and delete.
8314
8315 @ret value error code
8316 0 success
8317 */
row_operations_scan_and_key_setup()8318 int Rows_log_event::row_operations_scan_and_key_setup() {
8319 int error = 0;
8320 DBUG_TRACE;
8321
8322 /*
8323 Prepare memory structures for search operations. If
8324 search is performed:
8325
8326 1. using hash search => initialize the hash
8327 2. using key => decide on key to use and allocate mem structures
8328 3. using table scan => do nothing
8329 */
8330 decide_row_lookup_algorithm_and_key();
8331
8332 switch (m_rows_lookup_algorithm) {
8333 case ROW_LOOKUP_HASH_SCAN: {
8334 if (m_hash.init()) error = HA_ERR_OUT_OF_MEM;
8335 goto err;
8336 }
8337 case ROW_LOOKUP_INDEX_SCAN: {
8338 DBUG_ASSERT(m_key_index < MAX_KEY);
8339 // Allocate buffer for key searches
8340 m_key = (uchar *)my_malloc(key_memory_log_event, m_key_info->key_length,
8341 MYF(MY_WME));
8342 if (!m_key) error = HA_ERR_OUT_OF_MEM;
8343 goto err;
8344 }
8345 case ROW_LOOKUP_TABLE_SCAN:
8346 default:
8347 break;
8348 }
8349 err:
8350 return error;
8351 }
8352
8353 /*
8354 Encapsulates the operations to be done after applying
8355 row events for update and delete.
8356
8357 @ret value error code
8358 0 success
8359 */
8360
row_operations_scan_and_key_teardown(int error)8361 int Rows_log_event::row_operations_scan_and_key_teardown(int error) {
8362 DBUG_TRACE;
8363
8364 DBUG_ASSERT(!m_table->file->inited);
8365 switch (m_rows_lookup_algorithm) {
8366 case ROW_LOOKUP_HASH_SCAN: {
8367 m_hash.deinit(); // we don't need the hash anymore.
8368 goto err;
8369 }
8370
8371 case ROW_LOOKUP_INDEX_SCAN: {
8372 if (m_table->s->keys > 0) {
8373 my_free(m_key); // Free for multi_malloc
8374 m_key = nullptr;
8375 m_key_index = MAX_KEY;
8376 m_key_info = nullptr;
8377 }
8378 goto err;
8379 }
8380
8381 case ROW_LOOKUP_TABLE_SCAN:
8382 default:
8383 break;
8384 }
8385
8386 err:
8387 m_rows_lookup_algorithm = ROW_LOOKUP_UNDEFINED;
8388 return error;
8389 }
8390
is_auto_inc_in_extra_columns()8391 bool Rows_log_event::is_auto_inc_in_extra_columns() {
8392 DBUG_ASSERT(m_table);
8393 return (m_table->next_number_field &&
8394 this->m_fields.translate_position(
8395 m_table->next_number_field->field_index()) >= m_width);
8396 }
8397
8398 /*
8399 Compares table->record[0] and table->record[1]
8400
8401 Returns true if different.
8402 */
record_compare(TABLE * table,MY_BITMAP * cols)8403 static bool record_compare(TABLE *table, MY_BITMAP *cols) {
8404 DBUG_TRACE;
8405
8406 /*
8407 Need to set the X bit and the filler bits in both records since
8408 there are engines that do not set it correctly.
8409
8410 In addition, since MyISAM checks that one hasn't tampered with the
8411 record, it is necessary to restore the old bytes into the record
8412 after doing the comparison.
8413
8414 TODO[record format ndb]: Remove it once NDB returns correct
8415 records. Check that the other engines also return correct records.
8416 */
8417
8418 DBUG_DUMP("record[0]", table->record[0], table->s->reclength);
8419 DBUG_DUMP("record[1]", table->record[1], table->s->reclength);
8420
8421 bool result = false;
8422 uchar saved_x[2] = {0, 0}, saved_filler[2] = {0, 0};
8423
8424 if (table->s->null_bytes > 0) {
8425 for (int i = 0; i < 2; ++i) {
8426 /*
8427 If we have an X bit then we need to take care of it.
8428 */
8429 if (!(table->s->db_options_in_use & HA_OPTION_PACK_RECORD)) {
8430 saved_x[i] = table->record[i][0];
8431 table->record[i][0] |= 1U;
8432 }
8433
8434 /*
8435 If (last_null_bit_pos == 0 && null_bytes > 1), then:
8436
8437 X bit (if any) + N nullable fields + M Field_bit fields = 8 bits
8438
8439 Ie, the entire byte is used.
8440 */
8441 if (table->s->last_null_bit_pos > 0) {
8442 saved_filler[i] = table->record[i][table->s->null_bytes - 1];
8443 table->record[i][table->s->null_bytes - 1] |=
8444 256U - (1U << table->s->last_null_bit_pos);
8445 }
8446 }
8447 }
8448
8449 /**
8450 Compare full record only if:
8451 - there are no blob fields (otherwise we would also need
8452 to compare blobs contents as well);
8453 - there are no varchar fields (otherwise we would also need
8454 to compare varchar contents as well);
8455 - there are no null fields, otherwise NULLed fields
8456 contents (i.e., the don't care bytes) may show arbitrary
8457 values, depending on how each engine handles internally.
8458 - if all the bitmap is set (both are full rows)
8459 */
8460 if ((table->s->blob_fields + table->s->varchar_fields +
8461 table->s->null_fields) == 0 &&
8462 bitmap_is_set_all(cols)) {
8463 result = cmp_record(table, record[1]);
8464 }
8465
8466 /*
8467 Fallback to field-by-field comparison:
8468 1. start by checking if the field is signaled:
8469 2. if it is, first compare the null bit if the field is nullable
8470 3. then compare the contents of the field, if it is not
8471 set to null
8472 */
8473 else {
8474 for (Field **ptr = table->field;
8475 *ptr && ((*ptr)->field_index() < cols->n_bits) && !result; ptr++) {
8476 Field *field = *ptr;
8477 if (bitmap_is_set(cols, field->field_index()) &&
8478 !field->is_virtual_gcol()) {
8479 /* compare null bit */
8480 if (field->is_null() != field->is_null_in_record(table->record[1]))
8481 result = true;
8482
8483 /* compare content, only if fields are not set to NULL */
8484 else if (!field->is_null())
8485 result = field->cmp_binary_offset(table->s->rec_buff_length);
8486 }
8487 }
8488 }
8489
8490 /*
8491 Restore the saved bytes.
8492
8493 TODO[record format ndb]: Remove this code once NDB returns the
8494 correct record format.
8495 */
8496 if (table->s->null_bytes > 0) {
8497 for (int i = 0; i < 2; ++i) {
8498 if (!(table->s->db_options_in_use & HA_OPTION_PACK_RECORD))
8499 table->record[i][0] = saved_x[i];
8500
8501 if (table->s->last_null_bit_pos)
8502 table->record[i][table->s->null_bytes - 1] = saved_filler[i];
8503 }
8504 }
8505
8506 return result;
8507 }
8508
do_post_row_operations(Relay_log_info const * rli,int error)8509 void Rows_log_event::do_post_row_operations(Relay_log_info const *rli,
8510 int error) {
8511 /*
8512 If m_curr_row_end was not set during event execution (e.g., because
8513 of errors) we can't proceed to the next row. If the error is transient
8514 (i.e., error==0 at this point) we must call unpack_current_row() to set
8515 m_curr_row_end.
8516 */
8517
8518 DBUG_PRINT("info", ("curr_row: %p; curr_row_end: %p; rows_end: %p",
8519 m_curr_row, m_curr_row_end, m_rows_end));
8520
8521 if (!m_curr_row_end && !error) {
8522 /*
8523 This function is always called immediately following a call to
8524 handle_idempotent_and_ignored_errors which returns 0. And
8525 handle_idempotent_and_ignored_errors can only return 0 when
8526 error==0. And when error==0, it means that the previous call to
8527 unpack_currrent_row was successful. And that means
8528 m_curr_row_end has been set to a valid pointer. So it is
8529 impossible that both error==0 and m_curr_row_end==0 under normal
8530 conditions. So this is probably a case of a corrupt event.
8531 */
8532 const uchar *previous_m_curr_row = m_curr_row;
8533 error = unpack_current_row(rli, &m_cols, true /*is AI*/);
8534
8535 if (!error && previous_m_curr_row == m_curr_row) {
8536 error = 1;
8537 }
8538 }
8539
8540 // at this moment m_curr_row_end should be set
8541 DBUG_ASSERT(error || m_curr_row_end != nullptr);
8542 DBUG_ASSERT(error || m_curr_row <= m_curr_row_end);
8543 DBUG_ASSERT(error || m_curr_row_end <= m_rows_end);
8544
8545 m_curr_row = m_curr_row_end;
8546
8547 if (error == 0 && !m_table->file->has_transactions()) {
8548 thd->get_transaction()->set_unsafe_rollback_flags(Transaction_ctx::SESSION,
8549 true);
8550 thd->get_transaction()->set_unsafe_rollback_flags(Transaction_ctx::STMT,
8551 true);
8552 }
8553
8554 #ifdef HAVE_PSI_STAGE_INTERFACE
8555 /*
8556 Count the number of rows processed unconditionally. Needed instrumentation
8557 may be toggled while a rows event is being processed.
8558 */
8559 m_psi_progress.inc_n_rows_applied(1);
8560
8561 if (m_curr_row > m_rows_buf) {
8562 /* Report progress. */
8563 m_psi_progress.update_work_estimated_and_completed(m_curr_row, m_rows_buf,
8564 m_rows_end);
8565 } else if (m_curr_row == m_rows_buf) {
8566 /*
8567 Master can generate an empty row, in the following situation:
8568 mysql> SET SESSION binlog_row_image=MINIMAL;
8569 mysql> CREATE TABLE t1 (c1 INT DEFAULT 100);
8570 mysql> INSERT INTO t1 VALUES ();
8571
8572 Otherwise, m_curr_row must be ahead of m_rows_buf, since we
8573 have processed the first row already.
8574
8575 No point in reporting progress, since this would show for a
8576 very small fraction of time - thence no point in speding extra
8577 CPU cycles for this.
8578
8579 Nevertheless assert that the event is a write event, otherwise,
8580 this should not happen.
8581 */
8582 DBUG_ASSERT(get_general_type_code() == binary_log::WRITE_ROWS_EVENT);
8583 } else
8584 /* Impossible */
8585 DBUG_ASSERT(false);
8586
8587 DBUG_EXECUTE_IF("dbug.rpl_apply_sync_barrier", {
8588 const char act[] =
8589 "now SIGNAL signal.rpl_row_apply_progress_updated "
8590 "WAIT_FOR signal.rpl_row_apply_process_next_row";
8591 DBUG_ASSERT(opt_debug_sync_timeout > 0);
8592 DBUG_ASSERT(!debug_sync_set_action(thd, STRING_WITH_LEN(act)));
8593 };);
8594 #endif /* HAVE_PSI_STAGE_INTERFACE */
8595 }
8596
handle_idempotent_and_ignored_errors(Relay_log_info const * rli,int * err)8597 int Rows_log_event::handle_idempotent_and_ignored_errors(
8598 Relay_log_info const *rli, int *err) {
8599 int error = *err;
8600 if (error) {
8601 int actual_error = convert_handler_error(error, thd, m_table);
8602 bool idempotent_error = (idempotent_error_code(error) &&
8603 (rbr_exec_mode == RBR_EXEC_MODE_IDEMPOTENT));
8604 bool ignored_error =
8605 (idempotent_error == 0 ? ignored_error_code(actual_error) : 0);
8606
8607 if (idempotent_error || ignored_error) {
8608 loglevel ll;
8609 if (idempotent_error)
8610 ll = WARNING_LEVEL;
8611 else
8612 ll = INFORMATION_LEVEL;
8613 slave_rows_error_report(
8614 ll, error, rli, thd, m_table, get_type_str(),
8615 const_cast<Relay_log_info *>(rli)->get_rpl_log_name(),
8616 (ulong)common_header->log_pos);
8617 thd->get_stmt_da()->reset_condition_info(thd);
8618 clear_all_errors(thd, const_cast<Relay_log_info *>(rli));
8619 *err = 0;
8620 if (idempotent_error == 0) return ignored_error;
8621 }
8622 }
8623
8624 return *err;
8625 }
8626
do_apply_row(Relay_log_info const * rli)8627 int Rows_log_event::do_apply_row(Relay_log_info const *rli) {
8628 DBUG_TRACE;
8629
8630 int error = 0;
8631
8632 /* in_use can have been set to NULL in close_tables_for_reopen */
8633 THD *old_thd = m_table->in_use;
8634 if (!m_table->in_use) m_table->in_use = thd;
8635
8636 error = do_exec_row(rli);
8637
8638 if (error) {
8639 DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
8640 DBUG_ASSERT(error != HA_ERR_RECORD_DELETED);
8641 }
8642 m_table->in_use = old_thd;
8643
8644 return error;
8645 }
8646
8647 /**
8648 Does the cleanup
8649 - closes the index if opened by open_record_scan
8650 - closes the table if opened for scanning.
8651 */
close_record_scan()8652 int Rows_log_event::close_record_scan() {
8653 DBUG_TRACE;
8654 int error = 0;
8655
8656 // if there is something to actually close
8657 if (m_key_index < MAX_KEY) {
8658 if (m_table->file->inited) error = m_table->file->ha_index_end();
8659 } else if (m_table->file->inited)
8660 error = m_table->file->ha_rnd_end();
8661
8662 return error;
8663 }
8664
8665 /**
8666 Fetches next row. If it is a HASH_SCAN over an index, it populates
8667 table->record[0] with the next row corresponding to the index. If
8668 the indexes are in non-contiguous ranges it fetches record corresponding
8669 to the key value in the next range.
8670
8671 @param first_read Signifying if this is the first time we are reading a row
8672 over an index.
8673 @retval error code when there are no more records to be fetched or some other
8674 error occurred
8675 @retval 0 otherwise.
8676 */
next_record_scan(bool first_read)8677 int Rows_log_event::next_record_scan(bool first_read) {
8678 DBUG_TRACE;
8679 DBUG_ASSERT(m_table->file->inited);
8680 TABLE *table = m_table;
8681 int error = 0;
8682
8683 if (m_key_index >= MAX_KEY)
8684 error = table->file->ha_rnd_next(table->record[0]);
8685 else {
8686 /*
8687 We need to set the null bytes to ensure that the filler bit are
8688 all set when returning. There are storage engines that just set
8689 the necessary bits on the bytes and don't set the filler bits
8690 correctly.
8691 */
8692 if (table->s->null_bytes > 0)
8693 table->record[0][table->s->null_bytes - 1] |=
8694 256U - (1U << table->s->last_null_bit_pos);
8695
8696 if (!first_read) {
8697 /*
8698 if we fail to fetch next record corresponding to a key value, we
8699 move to the next key value. If we are out of key values as well an error
8700 will be returned.
8701 */
8702 error = table->file->ha_index_next_same(table->record[0], m_key,
8703 m_key_info->key_length);
8704 if (m_rows_lookup_algorithm == ROW_LOOKUP_HASH_SCAN) {
8705 /*
8706 if we are out of rows for this particular key value, we reposition the
8707 marker according to the next key value that we have in the list.
8708 */
8709 if (error) {
8710 if (m_itr != m_distinct_keys.end()) {
8711 m_key = *m_itr;
8712 m_itr++;
8713 first_read = true;
8714 } else
8715 error = HA_ERR_KEY_NOT_FOUND;
8716 }
8717 }
8718 }
8719
8720 if (first_read)
8721 if ((error = table->file->ha_index_read_map(
8722 table->record[0], m_key, HA_WHOLE_KEY, HA_READ_KEY_EXACT))) {
8723 DBUG_PRINT("info", ("no record matching the key found in the table"));
8724 error = HA_ERR_KEY_NOT_FOUND;
8725 }
8726 }
8727
8728 return error;
8729 }
8730
8731 /**
8732 Initializes scanning of rows. Opens an index and initializes an iterator
8733 over a list of distinct keys (m_distinct_keys) if it is a HASH_SCAN
8734 over an index or the table if its a HASH_SCAN over the table.
8735 */
open_record_scan()8736 int Rows_log_event::open_record_scan() {
8737 int error = 0;
8738 TABLE *table = m_table;
8739 DBUG_TRACE;
8740
8741 if (m_key_index < MAX_KEY) {
8742 if (m_rows_lookup_algorithm == ROW_LOOKUP_HASH_SCAN) {
8743 /* initialize the iterator over the list of distinct keys that we have */
8744 m_itr = m_distinct_keys.begin();
8745
8746 /* get the first element from the list of keys and increment the
8747 iterator
8748 */
8749 m_key = *m_itr;
8750 m_itr++;
8751 } else {
8752 /* this is an INDEX_SCAN we need to store the key in m_key */
8753 DBUG_ASSERT((m_rows_lookup_algorithm == ROW_LOOKUP_INDEX_SCAN) && m_key);
8754 key_copy(m_key, m_table->record[0], m_key_info, 0);
8755 }
8756
8757 /*
8758 Save copy of the record in table->record[1]. It might be needed
8759 later if linear search is used to find exact match.
8760 */
8761 store_record(table, record[1]);
8762
8763 DBUG_PRINT("info", ("locating record using a key (index_read)"));
8764
8765 /* The m_key_index'th key is active and usable: search the table using the
8766 * index */
8767 if (!table->file->inited &&
8768 (error = table->file->ha_index_init(m_key_index, false))) {
8769 DBUG_PRINT("info", ("ha_index_init returns error %d", error));
8770 goto end;
8771 }
8772
8773 DBUG_DUMP("key data", m_key, m_key_info->key_length);
8774 } else {
8775 if ((error = table->file->ha_rnd_init(true))) {
8776 DBUG_PRINT("info", ("error initializing table scan"
8777 " (ha_rnd_init returns %d)",
8778 error));
8779 table->file->print_error(error, MYF(0));
8780 }
8781 }
8782
8783 end:
8784 return error;
8785 }
8786
8787 /**
8788 Populates the m_distinct_keys with unique keys to be modified
8789 during HASH_SCAN over keys.
8790 @retval 0 success
8791 */
add_key_to_distinct_keyset()8792 int Rows_log_event::add_key_to_distinct_keyset() {
8793 int error = 0;
8794 DBUG_TRACE;
8795 DBUG_ASSERT(m_key_index < MAX_KEY);
8796 key_copy(m_distinct_key_spare_buf, m_table->record[0], m_key_info, 0);
8797 std::pair<std::set<uchar *, Key_compare>::iterator, bool> ret =
8798 m_distinct_keys.insert(m_distinct_key_spare_buf);
8799 if (ret.second) {
8800 /* Insert is successful, so allocate a new buffer for next key */
8801 m_distinct_key_spare_buf = (uchar *)thd->alloc(m_key_info->key_length);
8802 if (!m_distinct_key_spare_buf) {
8803 error = HA_ERR_OUT_OF_MEM;
8804 goto err;
8805 }
8806 }
8807
8808 err:
8809 return error;
8810 }
8811
do_index_scan_and_update(Relay_log_info const * rli)8812 int Rows_log_event::do_index_scan_and_update(Relay_log_info const *rli) {
8813 DBUG_TRACE;
8814 DBUG_ASSERT(m_table && m_table->in_use != nullptr);
8815
8816 int error = 0;
8817 const uchar *saved_m_curr_row = m_curr_row;
8818
8819 /*
8820 rpl_row_tabledefs.test specifies that
8821 if the extra field on the slave does not have a default value
8822 and this is okay with Delete or Update events.
8823 Todo: fix wl3228 hld that requires defaults for all types of events
8824 */
8825
8826 prepare_record(m_table, &this->m_local_cols, false);
8827 if ((error = unpack_current_row(rli, &m_cols, false /*is not AI*/))) goto end;
8828
8829 /*
8830 Trying to do an index scan without a usable key
8831 This is a valid state because we allow the user
8832 to set Slave_rows_search_algorithm= 'INDEX_SCAN'.
8833
8834 Therefore on tables with no indexes we will end
8835 up here.
8836 */
8837 if (m_key_index >= MAX_KEY) {
8838 error = HA_ERR_END_OF_FILE;
8839 goto end;
8840 }
8841
8842 #ifndef DBUG_OFF
8843 DBUG_PRINT("info", ("looking for the following record"));
8844 DBUG_DUMP("record[0]", m_table->record[0], m_table->s->reclength);
8845 #endif
8846
8847 if (m_key_index != m_table->s->primary_key)
8848 /* we dont have a PK, or PK is not usable */
8849 goto INDEX_SCAN;
8850
8851 if ((m_table->file->ha_table_flags() & HA_READ_BEFORE_WRITE_REMOVAL)) {
8852 /*
8853 Read removal is possible since the engine supports write without
8854 previous read using full primary key
8855 */
8856 DBUG_PRINT("info", ("using read before write removal"));
8857 DBUG_ASSERT(m_key_index == m_table->s->primary_key);
8858
8859 /*
8860 Tell the handler to ignore if key exists or not, since it's
8861 not yet known if the key does exist(when using rbwr)
8862 */
8863 m_table->file->ha_extra(HA_EXTRA_IGNORE_NO_KEY);
8864
8865 goto end;
8866 }
8867
8868 if ((m_table->file->ha_table_flags() &
8869 HA_PRIMARY_KEY_REQUIRED_FOR_POSITION)) {
8870 /*
8871 Use a more efficient method to fetch the record given by
8872 table->record[0] if the engine allows it. We first compute a
8873 row reference using the position() member function (it will be
8874 stored in table->file->ref) and then use rnd_pos() to position
8875 the "cursor" (i.e., record[0] in this case) at the correct row.
8876
8877 TODO: Check that the correct record has been fetched by
8878 comparing it with the original record. Take into account that the
8879 record on the master and slave can be of different
8880 length. Something along these lines should work:
8881
8882 ADD>>> store_record(table,record[1]);
8883 int error= table->file->rnd_pos(table->record[0],
8884 table->file->ref); ADD>>> DBUG_ASSERT(memcmp(table->record[1],
8885 table->record[0], table->s->reclength) == 0);
8886
8887 */
8888
8889 DBUG_PRINT("info", ("locating record using primary key (position)"));
8890 if (m_table->file->inited && (error = m_table->file->ha_index_end()))
8891 goto end;
8892
8893 error = m_table->file->rnd_pos_by_record(m_table->record[0]);
8894
8895 if (error) {
8896 DBUG_PRINT("info", ("rnd_pos returns error %d", error));
8897 if (error == HA_ERR_RECORD_DELETED) error = HA_ERR_KEY_NOT_FOUND;
8898 }
8899
8900 goto end;
8901 }
8902
8903 // We can't use position() - try other methods.
8904
8905 INDEX_SCAN:
8906
8907 /* Use the m_key_index'th key */
8908
8909 if ((error = open_record_scan())) goto end;
8910
8911 error = next_record_scan(true);
8912 if (error) {
8913 DBUG_PRINT("info", ("no record matching the key found in the table"));
8914 if (error == HA_ERR_RECORD_DELETED) error = HA_ERR_KEY_NOT_FOUND;
8915 goto end;
8916 }
8917
8918 DBUG_PRINT("info", ("found first matching record"));
8919 DBUG_DUMP("record[0]", m_table->record[0], m_table->s->reclength);
8920 /*
8921 Below is a minor "optimization". If the key (i.e., key number
8922 0) has the HA_NOSAME flag set, we know that we have found the
8923 correct record (since there can be no duplicates); otherwise, we
8924 have to compare the record with the one found to see if it is
8925 the correct one.
8926
8927 CAVEAT! This behaviour is essential for the replication of,
8928 e.g., the mysql.proc table since the correct record *shall* be
8929 found using the primary key *only*. There shall be no
8930 comparison of non-PK columns to decide if the correct record is
8931 found. I can see no scenario where it would be incorrect to
8932 chose the row to change only using a PK or an UNNI.
8933 */
8934 if (m_key_info->flags & HA_NOSAME || m_key_index == m_table->s->primary_key) {
8935 /* Unique does not have non nullable part */
8936 if (!(m_key_info->flags & (HA_NULL_PART_KEY)))
8937 goto end; // record found
8938 else {
8939 /*
8940 Unique has nullable part. We need to check if there is any field in the
8941 BI image that is null and part of UNNI.
8942 */
8943 bool null_found = false;
8944 for (uint i = 0; i < m_key_info->user_defined_key_parts && !null_found;
8945 i++) {
8946 uint fieldnr = m_key_info->key_part[i].fieldnr - 1;
8947 Field **f = m_table->field + fieldnr;
8948 null_found = (*f)->is_null();
8949 }
8950
8951 if (!null_found) goto end; // record found
8952
8953 /* else fall through to index scan */
8954 }
8955 }
8956
8957 /*
8958 In case key is not unique, we still have to iterate over records found
8959 and find the one which is identical to the row given. A copy of the
8960 record we are looking for is stored in record[1].
8961 */
8962 DBUG_PRINT("info", ("non-unique index, scanning it to find matching record"));
8963
8964 while (record_compare(m_table, &this->m_local_cols)) {
8965 while ((error = next_record_scan(false))) {
8966 /* We just skip records that has already been deleted */
8967 if (error == HA_ERR_RECORD_DELETED) continue;
8968 DBUG_PRINT("info", ("no record matching the given row found"));
8969 goto end;
8970 }
8971 }
8972
8973 end:
8974
8975 DBUG_ASSERT(error != HA_ERR_RECORD_DELETED);
8976
8977 if (error && error != HA_ERR_RECORD_DELETED)
8978 m_table->file->print_error(error, MYF(0));
8979 else
8980 error = do_apply_row(rli);
8981
8982 if (!error)
8983 error = close_record_scan();
8984 else
8985 /*
8986 we are already with errors. Keep the error code and
8987 try to close the scan anyway.
8988 */
8989 (void)close_record_scan();
8990
8991 int unpack_error = skip_after_image_for_update_event(rli, saved_m_curr_row);
8992 if (!error) error = unpack_error;
8993
8994 m_table->default_column_bitmaps();
8995 return error;
8996 }
8997
skip_after_image_for_update_event(const Relay_log_info * rli,const uchar * curr_bi_start)8998 int Update_rows_log_event::skip_after_image_for_update_event(
8999 const Relay_log_info *rli, const uchar *curr_bi_start) {
9000 if (m_curr_row == curr_bi_start && m_curr_row_end != nullptr) {
9001 /*
9002 This handles the case that the BI was read successfully, but an
9003 error happened while looking up the row. In this case, the AI
9004 has not been read, so the read position is between the two
9005 images. In case the error is idempotent, we need to move the
9006 position to the end of the row, and therefore we skip past the
9007 AI.
9008
9009 The normal behavior is:
9010
9011 When unpack_row reads a row image, and there is no error,
9012 unpack_row sets m_curr_row_end to point to the end of the image,
9013 and leaves m_curr_row to point at the beginning.
9014
9015 The AI is read from Update_rows_log_event::do_exec_row. Before
9016 calling unpack_row, do_exec_row sets m_curr_row=m_curr_row_end,
9017 so that it actually reads the AI. And again, if there is no
9018 error, unpack_row sets m_curr_row_end to point to the end of the
9019 AI.
9020
9021 Thus, the positions are moved as follows:
9022
9023 +--------------+--------------+
9024 | BI | AI | NULL
9025 +--------------+--------------+
9026 0. Initial values ^m_curr_row ^m_curr_row_end
9027 1. Read BI, no error
9028 ^m_curr_row ^m_curr_row_end
9029 2. Lookup BI
9030 3. Set m_curr_row
9031 ^m_curr_row
9032 ^m_curr_row_end
9033 4. Read AI, no error
9034 ^m_curr_row ^m_curr_row_end
9035
9036 If an error happened while reading the BI (e.g. corruption),
9037 then we should not try to read the AI here. Therefore we do not
9038 read the AI if m_curr_row_end==NULL.
9039
9040 If an error happened while looking up BI, then we should try to
9041 read AI here. Then we know m_curr_row_end points to beginning of
9042 AI, so we come here, set m_curr_row=m_curr_row_end, and read the
9043 AI.
9044
9045 If an error happened while reading the AI, then we should not
9046 try to read the AI again. Therefore we do not read the AI if
9047 m_curr_row==curr_bi_start.
9048 */
9049 m_curr_row = m_curr_row_end;
9050 return unpack_current_row(rli, &m_cols_ai, true /*is AI*/,
9051 true /*only_seek*/);
9052 }
9053 return 0;
9054 }
9055
do_hash_row(Relay_log_info const * rli)9056 int Rows_log_event::do_hash_row(Relay_log_info const *rli) {
9057 DBUG_TRACE;
9058 DBUG_ASSERT(m_table && m_table->in_use != nullptr);
9059 int error = 0;
9060
9061 /* create an empty entry to add to the hash table */
9062 HASH_ROW_ENTRY *entry = m_hash.make_entry();
9063
9064 /* Prepare the record, unpack and save positions. */
9065 entry->positions->bi_start = m_curr_row; // save the bi start pos
9066 prepare_record(m_table, &this->m_local_cols, false);
9067 if ((error = unpack_current_row(rli, &m_cols, false /*is not AI*/))) {
9068 hash_slave_rows_free_entry freer;
9069 freer(entry);
9070 goto end;
9071 }
9072 entry->positions->bi_ends = m_curr_row_end; // save the bi end pos
9073
9074 /*
9075 Now that m_table->record[0] is filled in, we can add the entry
9076 to the hash table. Note that the put operation calculates the
9077 key based on record[0] contents (including BLOB fields).
9078 */
9079 m_hash.put(m_table, &this->m_local_cols, entry);
9080
9081 if (m_key_index < MAX_KEY) add_key_to_distinct_keyset();
9082
9083 /*
9084 We need to unpack the AI to advance the positions, so we
9085 know when we have reached m_rows_end and that we do not
9086 unpack the AI in the next iteration as if it was a BI.
9087 */
9088 if (get_general_type_code() == binary_log::UPDATE_ROWS_EVENT) {
9089 /* Save a copy of the BI. */
9090 store_record(m_table, record[1]);
9091
9092 /*
9093 This is the situation after hashing the BI:
9094
9095 ===|=== before image ====|=== after image ===|===
9096 ^ ^
9097 m_curr_row m_curr_row_end
9098 */
9099
9100 /* Set the position to the start of the record to be unpacked. */
9101 m_curr_row = m_curr_row_end;
9102
9103 /* We shouldn't need this, but lets not leave loose ends */
9104 prepare_record(m_table, &this->m_local_cols, false);
9105 error =
9106 unpack_current_row(rli, &m_cols_ai, true /*is AI*/, true /*only_seek*/);
9107
9108 /*
9109 This is the situation after unpacking the AI:
9110
9111 ===|=== before image ====|=== after image ===|===
9112 ^ ^
9113 m_curr_row m_curr_row_end
9114 */
9115
9116 /* Restore back the copy of the BI. */
9117 restore_record(m_table, record[1]);
9118 }
9119
9120 end:
9121 return error;
9122 }
9123
do_scan_and_update(Relay_log_info const * rli)9124 int Rows_log_event::do_scan_and_update(Relay_log_info const *rli) {
9125 DBUG_TRACE;
9126 DBUG_ASSERT(m_table && m_table->in_use != nullptr);
9127 DBUG_ASSERT(m_hash.is_empty() == false);
9128 TABLE *table = m_table;
9129 int error = 0;
9130 const uchar *saved_last_m_curr_row = nullptr;
9131 const uchar *saved_last_m_curr_row_end = nullptr;
9132 /* create an empty entry to add to the hash table */
9133 HASH_ROW_ENTRY *entry = nullptr;
9134 int idempotent_errors = 0;
9135 int i = 0;
9136
9137 saved_last_m_curr_row = m_curr_row;
9138 saved_last_m_curr_row_end = m_curr_row_end;
9139
9140 DBUG_PRINT("info", ("Hash was populated with %d records!", m_hash.size()));
9141
9142 /* open table or index depending on whether we have set m_key_index or not. */
9143 if ((error = open_record_scan())) goto err;
9144
9145 /*
9146 Scan the table only once and compare against entries in hash.
9147 When a match is found, apply the changes.
9148 */
9149 do {
9150 /* get the next record from the table */
9151 error = next_record_scan(i == 0);
9152 i++;
9153
9154 if (error) DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
9155 switch (error) {
9156 case 0: {
9157 entry = m_hash.get(table, &this->m_local_cols);
9158 /**
9159 The do..while loop takes care of the scenario of same row being
9160 updated more than once within a single Update_rows_log_event by
9161 performing the hash lookup for the updated_row(by taking the AI stored
9162 in table->record[0] after the ha_update_row()) when table has no
9163 primary key.
9164
9165 This can happen when update is called from a stored function.
9166 Ex:
9167 CREATE FUNCTION f1 () RETURNS INT BEGIN
9168 UPDATE t1 SET a = 2 WHERE a = 1;
9169 UPDATE t1 SET a = 3 WHERE a = 2;
9170 RETURN 0;
9171 END
9172 */
9173 do {
9174 store_record(table, record[1]);
9175
9176 /**
9177 If there are collisions we need to be sure that this is
9178 indeed the record we want. Loop through all records for
9179 the given key and explicitly compare them against the
9180 record we got from the storage engine.
9181 */
9182 while (entry) {
9183 m_curr_row = entry->positions->bi_start;
9184 m_curr_row_end = entry->positions->bi_ends;
9185
9186 prepare_record(table, &this->m_local_cols, false);
9187 if ((error = unpack_current_row(rli, &m_cols, false /*is not AI*/)))
9188 goto close_table;
9189
9190 if (record_compare(table, &this->m_local_cols))
9191 m_hash.next(&entry);
9192 else
9193 break; // we found a match
9194 }
9195
9196 /**
9197 We found the entry we needed, just apply the changes.
9198 */
9199 if (entry) {
9200 // just to be safe, copy the record from the SE to table->record[0]
9201 restore_record(table, record[1]);
9202
9203 /**
9204 At this point, both table->record[0] and
9205 table->record[1] have the SE row that matched the one
9206 in the hash table.
9207
9208 Thence if this is a DELETE we wouldn't need to mess
9209 around with positions anymore, but since this can be an
9210 update, we need to provide positions so that AI is
9211 unpacked correctly to table->record[0] in UPDATE
9212 implementation of do_exec_row().
9213 */
9214 m_curr_row = entry->positions->bi_start;
9215 m_curr_row_end = entry->positions->bi_ends;
9216
9217 /* we don't need this entry anymore, just delete it */
9218 if ((error = m_hash.del(entry))) goto err;
9219
9220 if ((error = do_apply_row(rli))) {
9221 if (handle_idempotent_and_ignored_errors(rli, &error))
9222 goto close_table;
9223
9224 do_post_row_operations(rli, error);
9225 }
9226 }
9227 } while (this->get_type_code() == binary_log::UPDATE_ROWS_EVENT &&
9228 table->s->primary_key >= MAX_KEY &&
9229 (entry = m_hash.get(table, &m_cols)));
9230 } break;
9231
9232 case HA_ERR_RECORD_DELETED:
9233 // get next
9234 continue;
9235
9236 case HA_ERR_KEY_NOT_FOUND:
9237 /* If the slave exec mode is idempotent or the error is
9238 skipped error, then don't break */
9239 if (handle_idempotent_and_ignored_errors(rli, &error)) goto close_table;
9240 idempotent_errors++;
9241 continue;
9242
9243 case HA_ERR_END_OF_FILE:
9244 default:
9245 // exception (hash is not empty and we have reached EOF or
9246 // other error happened)
9247 goto close_table;
9248 }
9249 }
9250 /**
9251 if the rbr_exec_mode is set to Idempotent, we cannot expect the hash to
9252 be empty. In such cases we count the number of idempotent errors and check
9253 if it is equal to or greater than the number of rows left in the hash.
9254 */
9255 while (((idempotent_errors < m_hash.size()) && !m_hash.is_empty()) &&
9256 (!error || (error == HA_ERR_RECORD_DELETED)));
9257
9258 close_table:
9259 DBUG_PRINT("info", ("m_hash.size()=%d error=%d idempotent_errors=%d",
9260 m_hash.size(), error, idempotent_errors));
9261 if (error == HA_ERR_RECORD_DELETED) error = 0;
9262
9263 if (error) {
9264 table->file->print_error(error, MYF(0));
9265 DBUG_PRINT("info", ("Failed to get next record"
9266 " (ha_rnd_next returns %d)",
9267 error));
9268 /*
9269 we are already with errors. Keep the error code and
9270 try to close the scan anyway.
9271 */
9272 (void)close_record_scan();
9273 } else
9274 error = close_record_scan();
9275
9276 err:
9277
9278 if ((m_hash.is_empty() && !error) || (idempotent_errors >= m_hash.size())) {
9279 /**
9280 Reset the last positions, because the positions are lost while
9281 handling entries in the hash.
9282 */
9283 m_curr_row = saved_last_m_curr_row;
9284 m_curr_row_end = saved_last_m_curr_row_end;
9285 }
9286
9287 return error;
9288 }
9289
do_hash_scan_and_update(Relay_log_info const * rli)9290 int Rows_log_event::do_hash_scan_and_update(Relay_log_info const *rli) {
9291 DBUG_TRACE;
9292 DBUG_ASSERT(m_table && m_table->in_use != nullptr);
9293
9294 // HASHING PART
9295
9296 /* unpack the BI (and AI, if it exists) and add it to the hash map. */
9297 if (int error = this->do_hash_row(rli)) return error;
9298
9299 /* We have not yet hashed all rows in the buffer. Do not proceed to the SCAN
9300 * part. */
9301 if (m_curr_row_end < m_rows_end) return 0;
9302
9303 DBUG_PRINT("info", ("Hash was populated with %d records!", m_hash.size()));
9304 DBUG_ASSERT(m_curr_row_end == m_rows_end);
9305
9306 // SCANNING & UPDATE PART
9307
9308 return this->do_scan_and_update(rli);
9309 }
9310
do_table_scan_and_update(Relay_log_info const * rli)9311 int Rows_log_event::do_table_scan_and_update(Relay_log_info const *rli) {
9312 int error = 0;
9313 const uchar *saved_m_curr_row = m_curr_row;
9314 TABLE *table = m_table;
9315
9316 DBUG_TRACE;
9317 DBUG_ASSERT(m_curr_row != m_rows_end);
9318 DBUG_PRINT("info", ("locating record using table scan (ha_rnd_next)"));
9319
9320 saved_m_curr_row = m_curr_row;
9321
9322 /** unpack the before image */
9323 prepare_record(table, &this->m_local_cols, false);
9324 if (!(error = unpack_current_row(rli, &m_cols, false /*is not AI*/))) {
9325 /** save a copy so that we can compare against it later */
9326 store_record(m_table, record[1]);
9327
9328 int restart_count = 0; // Number of times scanning has restarted from top
9329
9330 if ((error = m_table->file->ha_rnd_init(true))) {
9331 DBUG_PRINT("info", ("error initializing table scan"
9332 " (ha_rnd_init returns %d)",
9333 error));
9334 goto end;
9335 }
9336
9337 /* Continue until we find the right record or have made a full loop */
9338 do {
9339 restart_ha_rnd_next:
9340 error = m_table->file->ha_rnd_next(m_table->record[0]);
9341 if (error) DBUG_PRINT("info", ("error: %s", HA_ERR(error)));
9342 switch (error) {
9343 case HA_ERR_END_OF_FILE:
9344 // restart scan from top
9345 if (++restart_count < 2) {
9346 if ((error = m_table->file->ha_rnd_init(true))) goto end;
9347 goto restart_ha_rnd_next;
9348 }
9349 break;
9350
9351 case HA_ERR_RECORD_DELETED:
9352 // fetch next
9353 goto restart_ha_rnd_next;
9354 case 0:
9355 // we're good, check if record matches
9356 break;
9357
9358 default:
9359 // exception
9360 goto end;
9361 }
9362 } while (restart_count < 2 && record_compare(m_table, &this->m_local_cols));
9363 }
9364
9365 end:
9366
9367 DBUG_ASSERT(error != HA_ERR_RECORD_DELETED);
9368
9369 /* either we report error or apply the changes */
9370 if (error && error != HA_ERR_RECORD_DELETED) {
9371 DBUG_PRINT("info", ("Failed to get next record"
9372 " (ha_rnd_next returns %d)",
9373 error));
9374 m_table->file->print_error(error, MYF(0));
9375 } else
9376 error = do_apply_row(rli);
9377
9378 if (!error)
9379 error = close_record_scan();
9380 else
9381 /*
9382 we are already with errors. Keep the error code and
9383 try to close the scan anyway.
9384 */
9385 (void)close_record_scan();
9386
9387 int unpack_error = skip_after_image_for_update_event(rli, saved_m_curr_row);
9388 if (!error) error = unpack_error;
9389
9390 table->default_column_bitmaps();
9391 return error;
9392 }
9393
do_apply_event(Relay_log_info const * rli)9394 int Rows_log_event::do_apply_event(Relay_log_info const *rli) {
9395 DBUG_TRACE;
9396 TABLE *table = nullptr;
9397 int error = 0;
9398
9399 /*
9400 'thd' has been set by exec_relay_log_event(), just before calling
9401 do_apply_event(). We still check here to prevent future coding
9402 errors.
9403 */
9404 DBUG_ASSERT(rli->info_thd == thd);
9405
9406 /*
9407 If there is no locks taken, this is the first binrow event seen
9408 after the table map events. We should then lock all the tables
9409 used in the transaction and proceed with execution of the actual
9410 event.
9411 */
9412 if (!thd->lock) {
9413 /*
9414 Lock_tables() reads the contents of thd->lex, so they must be
9415 initialized.
9416
9417 We also call the mysql_reset_thd_for_next_command(), since this
9418 is the logical start of the next "statement". Note that this
9419 call might reset the value of current_stmt_binlog_format, so
9420 we need to do any changes to that value after this function.
9421 */
9422 lex_start(thd);
9423 mysql_reset_thd_for_next_command(thd);
9424
9425 enum_gtid_statement_status state = gtid_pre_statement_checks(thd);
9426 if (state == GTID_STATEMENT_EXECUTE) {
9427 if (gtid_pre_statement_post_implicit_commit_checks(thd))
9428 state = GTID_STATEMENT_CANCEL;
9429 }
9430
9431 if (state == GTID_STATEMENT_CANCEL) {
9432 uint mysql_error = thd->get_stmt_da()->mysql_errno();
9433 DBUG_ASSERT(mysql_error != 0);
9434 rli->report(ERROR_LEVEL, mysql_error, "Error executing row event: '%s'",
9435 thd->get_stmt_da()->message_text());
9436 thd->is_slave_error = true;
9437 return -1;
9438 } else if (state == GTID_STATEMENT_SKIP)
9439 goto end;
9440
9441 /*
9442 The current statement is just about to begin and
9443 has not yet modified anything. Note, all.modified is reset
9444 by mysql_reset_thd_for_next_command.
9445 */
9446 thd->get_transaction()->reset_unsafe_rollback_flags(Transaction_ctx::STMT);
9447 /*
9448 This is a row injection, so we flag the "statement" as
9449 such. Note that this code is called both when the slave does row
9450 injections and when the BINLOG statement is used to do row
9451 injections.
9452 */
9453 thd->lex->set_stmt_row_injection();
9454
9455 /*
9456 There are a few flags that are replicated with each row event.
9457 Make sure to set/clear them before executing the main body of
9458 the event.
9459 */
9460 if (get_flags(NO_FOREIGN_KEY_CHECKS_F))
9461 thd->variables.option_bits |= OPTION_NO_FOREIGN_KEY_CHECKS;
9462 else
9463 thd->variables.option_bits &= ~OPTION_NO_FOREIGN_KEY_CHECKS;
9464
9465 if (get_flags(RELAXED_UNIQUE_CHECKS_F))
9466 thd->variables.option_bits |= OPTION_RELAXED_UNIQUE_CHECKS;
9467 else
9468 thd->variables.option_bits &= ~OPTION_RELAXED_UNIQUE_CHECKS;
9469
9470 thd->binlog_row_event_extra_data = m_extra_row_info.get_ndb_info();
9471
9472 /* A small test to verify that objects have consistent types */
9473 DBUG_ASSERT(sizeof(thd->variables.option_bits) ==
9474 sizeof(OPTION_RELAXED_UNIQUE_CHECKS));
9475 DBUG_EXECUTE_IF("rows_log_event_before_open_table", {
9476 const char action[] =
9477 "now SIGNAL before_open_table WAIT_FOR go_ahead_sql";
9478 DBUG_ASSERT(!debug_sync_set_action(thd, STRING_WITH_LEN(action)));
9479 };);
9480 if (open_and_lock_tables(thd, rli->tables_to_lock, 0)) {
9481 if (thd->is_error()) {
9482 uint actual_error = thd->get_stmt_da()->mysql_errno();
9483 if (ignored_error_code(actual_error)) {
9484 if (log_error_verbosity >= 2)
9485 rli->report(WARNING_LEVEL, actual_error,
9486 "Error executing row event: '%s'",
9487 thd->get_stmt_da()->message_text());
9488 thd->get_stmt_da()->reset_condition_info(thd);
9489 clear_all_errors(thd, const_cast<Relay_log_info *>(rli));
9490 error = 0;
9491 goto end;
9492 } else {
9493 rli->report(ERROR_LEVEL, actual_error,
9494 "Error executing row event: '%s'",
9495 thd->get_stmt_da()->message_text());
9496 thd->is_slave_error = true;
9497 }
9498 }
9499 return 1;
9500 }
9501
9502 /*
9503 When the open and locking succeeded, we check all tables to
9504 ensure that they still have the correct type.
9505 */
9506
9507 {
9508 DBUG_PRINT("debug",
9509 ("Checking compability of tables to lock - tables_to_lock: %p",
9510 rli->tables_to_lock));
9511
9512 /**
9513 When using RBR and MyISAM MERGE tables the base tables that make
9514 up the MERGE table can be appended to the list of tables to lock.
9515
9516 Thus, we just check compatibility for those that tables that have
9517 a correspondent table map event (ie, those that are actually going
9518 to be accessed while applying the event). That's why the loop stops
9519 at rli->tables_to_lock_count .
9520
9521 NOTE: The base tables are added here are removed when
9522 close_thread_tables is called.
9523 */
9524 TABLE_LIST *table_list_ptr = rli->tables_to_lock;
9525 for (uint i = 0; table_list_ptr && (i < rli->tables_to_lock_count);
9526 table_list_ptr = table_list_ptr->next_global, i++) {
9527 /*
9528 Below if condition takes care of skipping base tables that
9529 make up the MERGE table (which are added by open_tables()
9530 call). They are added next to the merge table in the list.
9531 For eg: If RPL_TABLE_LIST is t3->t1->t2 (where t1 and t2
9532 are base tables for merge table 't3'), open_tables will modify
9533 the list by adding t1 and t2 again immediately after t3 in the
9534 list (*not at the end of the list*). New table_to_lock list will
9535 look like t3->t1'->t2'->t1->t2 (where t1' and t2' are TABLE_LIST
9536 objects added by open_tables() call). There is no flag(or logic) in
9537 open_tables() that can skip adding these base tables to the list.
9538 So the logic here should take care of skipping them.
9539
9540 tables_to_lock_count logic will take care of skipping base tables
9541 that are added at the end of the list.
9542 For eg: If RPL_TABLE_LIST is t1->t2->t3, open_tables will modify
9543 the list into t1->t2->t3->t1'->t2'. t1' and t2' will be skipped
9544 because tables_to_lock_count logic in this for loop.
9545 */
9546 if (table_list_ptr->parent_l) continue;
9547 /*
9548 We can use a down cast here since we know that every table added
9549 to the tables_to_lock is a RPL_TABLE_LIST (or child table which is
9550 skipped above).
9551 */
9552 RPL_TABLE_LIST *ptr = static_cast<RPL_TABLE_LIST *>(table_list_ptr);
9553 DBUG_ASSERT(ptr->m_tabledef_valid);
9554 TABLE *conv_table;
9555 if (!ptr->m_tabledef.compatible_with(thd,
9556 const_cast<Relay_log_info *>(rli),
9557 ptr->table, &conv_table)) {
9558 DBUG_PRINT("debug",
9559 ("Table: %s.%s is not compatible with master",
9560 ptr->table->s->db.str, ptr->table->s->table_name.str));
9561 if (thd->is_slave_error) {
9562 const_cast<Relay_log_info *>(rli)->slave_close_thread_tables(thd);
9563 return ERR_BAD_TABLE_DEF;
9564 } else {
9565 thd->get_stmt_da()->reset_condition_info(thd);
9566 clear_all_errors(thd, const_cast<Relay_log_info *>(rli));
9567 error = 0;
9568 goto end;
9569 }
9570 }
9571 DBUG_PRINT("debug", ("Table: %s.%s is compatible with master"
9572 " - conv_table: %p",
9573 ptr->table->s->db.str,
9574 ptr->table->s->table_name.str, conv_table));
9575 ptr->m_conv_table = conv_table;
9576 }
9577 }
9578
9579 /*
9580 ... and then we add all the tables to the table map and but keep
9581 them in the tables to lock list.
9582 */
9583 TABLE_LIST *ptr = rli->tables_to_lock;
9584 for (uint i = 0; ptr && (i < rli->tables_to_lock_count);
9585 ptr = ptr->next_global, i++) {
9586 /*
9587 Please see comment in above 'for' loop to know the reason
9588 for this if condition
9589 */
9590 if (ptr->parent_l) continue;
9591 const_cast<Relay_log_info *>(rli)->m_table_map.set_table(ptr->table_id,
9592 ptr->table);
9593 }
9594
9595 /*
9596 Validate applied binlog events with plugin requirements.
9597 */
9598 int out_value = 0;
9599 int hook_error =
9600 RUN_HOOK(binlog_relay_io, applier_log_event, (thd, out_value));
9601 if (hook_error || out_value) {
9602 char buf[256];
9603 uint applier_error = ER_APPLIER_LOG_EVENT_VALIDATION_ERROR;
9604
9605 if (hook_error) {
9606 applier_error = ER_RUN_HOOK_ERROR;
9607 strcpy(buf, "applier_log_event");
9608 } else {
9609 if (!thd->owned_gtid_is_empty() && thd->owned_gtid.sidno > 0) {
9610 thd->owned_gtid.to_string(thd->owned_sid, buf);
9611 } else {
9612 strcpy(buf, "ANONYMOUS");
9613 }
9614 }
9615
9616 if (thd->slave_thread) {
9617 rli->report(ERROR_LEVEL, applier_error,
9618 ER_THD_NONCONST(thd, applier_error), buf);
9619 thd->is_slave_error = true;
9620 const_cast<Relay_log_info *>(rli)->slave_close_thread_tables(thd);
9621 } else {
9622 /*
9623 For the cases in which a 'BINLOG' statement is set to
9624 execute in a user session
9625 */
9626 my_printf_error(applier_error, ER_THD_NONCONST(thd, applier_error),
9627 MYF(0), buf);
9628 }
9629 return applier_error;
9630 }
9631 }
9632
9633 table = m_table =
9634 const_cast<Relay_log_info *>(rli)->m_table_map.get_table(m_table_id);
9635
9636 DBUG_PRINT("debug",
9637 ("m_table: %p, m_table_id: %llu", m_table, m_table_id.id()));
9638
9639 /*
9640 A row event comprising of a P_S table
9641 - should not be replicated (i.e executed) by the slave SQL thread.
9642 - should not be executed by the client in the form BINLOG '...' stmts.
9643 */
9644 if (table && table->s->table_category == TABLE_CATEGORY_PERFORMANCE)
9645 table = nullptr;
9646
9647 if (table) {
9648 this->m_fields.set_thd(thd).set_table(table);
9649
9650 /*
9651 Translate received replicated column bitmaps into local table column
9652 bitmaps. This is needed when the table has columns that are to be excluded
9653 from replication - hidden generated columns, for instance.
9654 */
9655 this->m_fields.translate_bitmap(this->m_cols, this->m_local_cols);
9656 if (this->m_cols.bitmap != this->m_cols_ai.bitmap)
9657 this->m_fields.translate_bitmap(this->m_cols_ai, this->m_local_cols_ai);
9658 else
9659 this->m_local_cols_ai.bitmap = this->m_local_cols.bitmap;
9660
9661 /*
9662 table == NULL means that this table should not be replicated
9663 (this was set up by Table_map_log_event::do_apply_event()
9664 which tested replicate-* rules).
9665 */
9666
9667 Applier_security_context_guard security_context{rli, thd};
9668 const char *privilege_missing = nullptr;
9669 if (!security_context.skip_priv_checks()) {
9670 std::vector<std::tuple<ulong, const TABLE *, Rows_log_event *>> l;
9671 switch (get_general_type_code()) {
9672 case binary_log::WRITE_ROWS_EVENT: {
9673 l.push_back(std::make_tuple(INSERT_ACL, this->m_table, this));
9674 if (!security_context.has_access(l)) {
9675 privilege_missing = "INSERT";
9676 }
9677 break;
9678 }
9679 case binary_log::DELETE_ROWS_EVENT: {
9680 l.push_back(std::make_tuple(DELETE_ACL, this->m_table, this));
9681 if (!security_context.has_access(l)) {
9682 privilege_missing = "DELETE";
9683 }
9684 break;
9685 }
9686 case binary_log::UPDATE_ROWS_EVENT:
9687 case binary_log::PARTIAL_UPDATE_ROWS_EVENT: {
9688 l.push_back(std::make_tuple(UPDATE_ACL, this->m_table, this));
9689 if (!security_context.has_access(l)) {
9690 privilege_missing = "UPDATE";
9691 }
9692 break;
9693 }
9694 default: {
9695 DBUG_ASSERT(false);
9696 }
9697 }
9698 }
9699 if (privilege_missing != nullptr) {
9700 rli->report(ERROR_LEVEL, ER_TABLEACCESS_DENIED_ERROR,
9701 ER_THD(thd, ER_TABLEACCESS_DENIED_ERROR), privilege_missing,
9702 security_context.get_username().data(),
9703 security_context.get_hostname().data(),
9704 table->s->table_name.str);
9705 return ER_TABLEACCESS_DENIED_ERROR;
9706 }
9707
9708 bool no_columns_to_update = false;
9709 // set the database
9710 LEX_CSTRING thd_db;
9711 LEX_CSTRING current_db_name_saved = thd->db();
9712 thd_db.str = table->s->db.str;
9713 thd_db.length = table->s->db.length;
9714 thd->reset_db(thd_db);
9715 thd->set_command(COM_QUERY);
9716 PSI_stage_info *stage = nullptr;
9717
9718 /*
9719 It's not needed to set_time() but
9720 1) it continues the property that "Time" in SHOW PROCESSLIST shows how
9721 much slave is behind
9722 2) it will be needed when we allow replication from a table with no
9723 TIMESTAMP column to a table with one.
9724 So we call set_time(), like in SBR. Presently it changes nothing.
9725 */
9726 thd->set_time(&(common_header->when));
9727
9728 thd->binlog_row_event_extra_data = m_extra_row_info.get_ndb_info();
9729
9730 /*
9731 Now we are in a statement and will stay in a statement until we
9732 see a STMT_END_F.
9733
9734 We set this flag here, before actually applying any rows, in
9735 case the SQL thread is stopped and we need to detect that we're
9736 inside a statement and halting abruptly might cause problems
9737 when restarting.
9738 */
9739 const_cast<Relay_log_info *>(rli)->set_flag(Relay_log_info::IN_STMT);
9740
9741 if (m_width == this->m_fields.filtered_size() && bitmap_is_set_all(&m_cols))
9742 set_flags(COMPLETE_ROWS_F);
9743
9744 /*
9745 Set tables write and read sets.
9746
9747 Read_set contains all slave columns (in case we are going to fetch
9748 a complete record from slave)
9749
9750 Write_set equals the m_cols bitmap sent from master but it can be
9751 longer if slave has extra columns.
9752 */
9753
9754 bitmap_set_all(table->read_set);
9755 bitmap_set_all(table->write_set);
9756
9757 /*
9758 Call mark_generated_columns() to set read_set/write_set bits of the
9759 virtual generated columns as required in order to get these computed.
9760 This is needed since all columns need to have a value in the before
9761 image for the record when doing the update (some storage engines will
9762 use this for maintaining of secondary indexes). This call is required
9763 even for DELETE events to set write_set bit in order to satisfy
9764 ASSERTs in Field_*::store functions.
9765
9766 binlog_prepare_row_image() function, which will be called from
9767 binlogging functions (binlog_update_row() and binlog_delete_row())
9768 will take care of removing these spurious fields required during
9769 execution but not needed for binlogging. In case of inserts, there
9770 are no spurious fields (all generated columns are required to be written
9771 into the binlog).
9772 */
9773 switch (get_general_type_code()) {
9774 case binary_log::DELETE_ROWS_EVENT:
9775 bitmap_intersect(table->read_set, &this->m_local_cols);
9776 stage = &stage_rpl_apply_row_evt_delete;
9777 if (m_table->vfield) m_table->mark_generated_columns(false);
9778 break;
9779 case binary_log::UPDATE_ROWS_EVENT:
9780 bitmap_intersect(table->read_set, &this->m_local_cols);
9781 bitmap_intersect(table->write_set, &this->m_local_cols_ai);
9782 if (m_table->vfield) m_table->mark_generated_columns(true);
9783 /* Skip update rows events that don't have data for this server's table.
9784 */
9785 if (!is_any_column_signaled_for_table(table, &this->m_local_cols_ai))
9786 no_columns_to_update = true;
9787 stage = &stage_rpl_apply_row_evt_update;
9788 break;
9789 case binary_log::WRITE_ROWS_EVENT:
9790 /*
9791 For 'WRITE_ROWS_EVENT, the execution order for 'mark_generated_rows()'
9792 and bitset intersection between 'write_set' and 'm_cols', is inverted.
9793 This behaviour is necessary due to an inconsistency, between storage
9794 engines, regarding the 'm_cols' bitset and generated columns: while
9795 non-NDB engines always include the generated columns for write-rows
9796 events, NDB doesnot if not necessary. The previous execution order
9797 would set all generated columns bits to '1' in 'write_set', since
9798 'mark_generated_columns()' is expecting that every column is present
9799 in the log event. This would break replication of generated columns
9800 for NDB.
9801
9802 For engines that include every column in write-rows events, this order
9803 makes no difference, assuming that the master uses the same engine,
9804 since the master will include all the bits in the image.
9805
9806 For use-cases that use different storage engines, specifically NDB
9807 and some other, this order may break replication due to the
9808 differences in behaviour regarding generated columns bits, in
9809 wrote-rows event bitsets. This issue should be further addressed by
9810 storage engines handlers, by converging behaviour regarding such use
9811 cases.
9812 */
9813 /* WRITE ROWS EVENTS store the bitmap in the m_cols bitmap */
9814 if (m_table->vfield) m_table->mark_generated_columns(false);
9815 bitmap_intersect(table->write_set, &this->m_local_cols);
9816 stage = &stage_rpl_apply_row_evt_write;
9817 break;
9818 default:
9819 DBUG_ASSERT(false);
9820 }
9821
9822 if (thd->slave_thread) // set the mode for slave
9823 this->rbr_exec_mode = slave_exec_mode_options;
9824 else // set the mode for user thread
9825 this->rbr_exec_mode = thd->variables.rbr_exec_mode_options;
9826
9827 // Do event specific preparations
9828 error = do_before_row_operations(rli);
9829
9830 /*
9831 Bug#56662 Assertion failed: next_insert_id == 0, file handler.cc
9832 Don't allow generation of auto_increment value when processing
9833 rows event by setting 'MODE_NO_AUTO_VALUE_ON_ZERO'. The exception
9834 to this rule happens when the auto_inc column exists on some
9835 extra columns on the slave. In that case, do not force
9836 MODE_NO_AUTO_VALUE_ON_ZERO.
9837 */
9838 sql_mode_t saved_sql_mode = thd->variables.sql_mode;
9839 if (!is_auto_inc_in_extra_columns())
9840 thd->variables.sql_mode = MODE_NO_AUTO_VALUE_ON_ZERO;
9841
9842 // row processing loop
9843
9844 /*
9845 set the initial time of this ROWS statement if it was not done
9846 before in some other ROWS event.
9847 */
9848 const_cast<Relay_log_info *>(rli)->set_row_stmt_start_timestamp();
9849
9850 const uchar *saved_m_curr_row = m_curr_row;
9851
9852 int (Rows_log_event::*do_apply_row_ptr)(Relay_log_info const *) = nullptr;
9853
9854 /**
9855 Skip update rows events that don't have data for this slave's
9856 table.
9857 */
9858 if (no_columns_to_update) goto AFTER_MAIN_EXEC_ROW_LOOP;
9859
9860 /**
9861 If there are no columns marked in the read_set for this table,
9862 that means that we cannot lookup any row using the available BI
9863 in the binarr log. Thence, we immediatly raise an error:
9864 HA_ERR_END_OF_FILE.
9865 */
9866
9867 if ((m_rows_lookup_algorithm != ROW_LOOKUP_NOT_NEEDED) &&
9868 !is_any_column_signaled_for_table(table, &this->m_local_cols)) {
9869 error = HA_ERR_END_OF_FILE;
9870 goto AFTER_MAIN_EXEC_ROW_LOOP;
9871 }
9872 switch (m_rows_lookup_algorithm) {
9873 case ROW_LOOKUP_HASH_SCAN:
9874 do_apply_row_ptr = &Rows_log_event::do_hash_scan_and_update;
9875 break;
9876
9877 case ROW_LOOKUP_INDEX_SCAN:
9878 do_apply_row_ptr = &Rows_log_event::do_index_scan_and_update;
9879 break;
9880
9881 case ROW_LOOKUP_TABLE_SCAN:
9882 do_apply_row_ptr = &Rows_log_event::do_table_scan_and_update;
9883 break;
9884
9885 case ROW_LOOKUP_NOT_NEEDED:
9886 DBUG_ASSERT(get_general_type_code() == binary_log::WRITE_ROWS_EVENT);
9887
9888 /* No need to scan for rows, just apply it */
9889 do_apply_row_ptr = &Rows_log_event::do_apply_row;
9890 break;
9891
9892 default:
9893 DBUG_ASSERT(0);
9894 error = 1;
9895 goto AFTER_MAIN_EXEC_ROW_LOOP;
9896 break;
9897 }
9898
9899 DBUG_ASSERT(stage != nullptr);
9900 THD_STAGE_INFO(thd, *stage);
9901
9902 #ifdef HAVE_PSI_STAGE_INTERFACE
9903 m_psi_progress.set_progress(mysql_set_stage(stage->m_key));
9904 #endif
9905
9906 do {
9907 DBUG_PRINT("info", ("calling do_apply_row_ptr"));
9908
9909 error = (this->*do_apply_row_ptr)(rli);
9910
9911 if (handle_idempotent_and_ignored_errors(rli, &error)) break;
9912
9913 /* this advances m_curr_row */
9914 do_post_row_operations(rli, error);
9915
9916 } while (!error && (m_curr_row != m_rows_end));
9917
9918 #ifdef HAVE_PSI_STAGE_INTERFACE
9919 m_psi_progress.end_work();
9920 #endif
9921
9922 AFTER_MAIN_EXEC_ROW_LOOP:
9923
9924 if (saved_m_curr_row != m_curr_row && !table->file->has_transactions()) {
9925 /*
9926 Usually, the trans_commit_stmt() propagates unsafe_rollback_flags
9927 from statement to transaction level. However, we cannot rely on
9928 this when row format is in use as several events can be processed
9929 before calling this function. This happens because it is called
9930 only when the latest event generated by a statement is processed.
9931
9932 There are however upper level functions that execute per event
9933 and check transaction's status. So if the unsafe_rollback_flags
9934 are not propagated here, this can lead to errors.
9935
9936 For example, a transaction that updates non-transactional tables
9937 may be stopped in the middle thus leading to inconsistencies
9938 after a restart.
9939 */
9940 thd->get_transaction()->mark_modified_non_trans_table(
9941 Transaction_ctx::STMT);
9942 thd->get_transaction()->merge_unsafe_rollback_flags();
9943 }
9944
9945 /*
9946 Restore the sql_mode after the rows event is processed.
9947 */
9948 thd->variables.sql_mode = saved_sql_mode;
9949
9950 { /*
9951 The following failure injecion works in cooperation with tests
9952 setting @@global.debug= 'd,stop_slave_middle_group'.
9953 The sql thread receives the killed status and will proceed
9954 to shutdown trying to finish incomplete events group.
9955 */
9956 DBUG_EXECUTE_IF(
9957 "stop_slave_middle_group",
9958 if (thd->get_transaction()->cannot_safely_rollback(
9959 Transaction_ctx::SESSION)) const_cast<Relay_log_info *>(rli)
9960 ->abort_slave = 1;);
9961 }
9962
9963 if ((error = do_after_row_operations(rli, error)) &&
9964 ignored_error_code(convert_handler_error(error, thd, table))) {
9965 slave_rows_error_report(
9966 INFORMATION_LEVEL, error, rli, thd, table, get_type_str(),
9967 const_cast<Relay_log_info *>(rli)->get_rpl_log_name(),
9968 (ulong)common_header->log_pos);
9969 thd->get_stmt_da()->reset_condition_info(thd);
9970 clear_all_errors(thd, const_cast<Relay_log_info *>(rli));
9971 error = 0;
9972 }
9973
9974 // reset back the db
9975 thd->reset_db(current_db_name_saved);
9976 } // if (table)
9977
9978 if (error) {
9979 slave_rows_error_report(
9980 ERROR_LEVEL, error, rli, thd, table, get_type_str(),
9981 const_cast<Relay_log_info *>(rli)->get_rpl_log_name(),
9982 (ulong)common_header->log_pos);
9983 /*
9984 @todo We should probably not call
9985 reset_current_stmt_binlog_format_row() from here.
9986 /Sven
9987 */
9988 thd->reset_current_stmt_binlog_format_row();
9989 thd->is_slave_error = true;
9990 return error;
9991 }
9992
9993 end:
9994 if (get_flags(STMT_END_F)) {
9995 if ((error = rows_event_stmt_cleanup(rli, thd))) {
9996 if (table)
9997 slave_rows_error_report(
9998 ERROR_LEVEL, thd->is_error() ? 0 : error, rli, thd, table,
9999 get_type_str(),
10000 const_cast<Relay_log_info *>(rli)->get_rpl_log_name(),
10001 (ulong)common_header->log_pos);
10002 else {
10003 rli->report(
10004 ERROR_LEVEL,
10005 thd->is_error() ? thd->get_stmt_da()->mysql_errno() : error,
10006 "Error in cleaning up after an event of type:%s; %s; the group"
10007 " log file/position: %s %lu",
10008 get_type_str(),
10009 thd->is_error() ? thd->get_stmt_da()->message_text()
10010 : "unexpected error",
10011 const_cast<Relay_log_info *>(rli)->get_rpl_log_name(),
10012 (ulong)common_header->log_pos);
10013 }
10014 }
10015 /* We are at end of the statement (STMT_END_F flag), lets clean
10016 the memory which was used from thd's mem_root now.
10017 This needs to be done only if we are here in SQL thread context.
10018 In other flow ( in case of a regular thread which can happen
10019 when the thread is applying BINLOG'...' row event) we should
10020 *not* try to free the memory here. It will be done latter
10021 in dispatch_command() after command execution is completed.
10022 */
10023 if (thd->slave_thread) free_root(thd->mem_root, MYF(MY_KEEP_PREALLOC));
10024 }
10025 return error;
10026 }
10027
do_shall_skip(Relay_log_info * rli)10028 Log_event::enum_skip_reason Rows_log_event::do_shall_skip(Relay_log_info *rli) {
10029 /*
10030 If the slave skip counter is 1 and this event does not end a
10031 statement, then we should not start executing on the next event.
10032 Otherwise, we defer the decision to the normal skipping logic.
10033 */
10034 if (rli->slave_skip_counter == 1 && !get_flags(STMT_END_F))
10035 return Log_event::EVENT_SKIP_IGNORE;
10036 else
10037 return Log_event::do_shall_skip(rli);
10038 }
10039
10040 /**
10041 The function is called at Rows_log_event statement commit time,
10042 normally from Rows_log_event::do_update_pos() and possibly from
10043 Query_log_event::do_apply_event() of the COMMIT.
10044 The function commits the last statement for engines, binlog and
10045 releases resources have been allocated for the statement.
10046
10047 @retval 0 Ok.
10048 @retval non-zero Error at the commit.
10049 */
10050
rows_event_stmt_cleanup(Relay_log_info const * rli,THD * thd)10051 static int rows_event_stmt_cleanup(Relay_log_info const *rli, THD *thd) {
10052 DBUG_TRACE;
10053 DBUG_EXECUTE_IF("simulate_rows_event_cleanup_failure", {
10054 char errbuf[MYSQL_ERRMSG_SIZE];
10055 int err = 149;
10056 my_error(ER_ERROR_DURING_COMMIT, MYF(0), err,
10057 my_strerror(errbuf, MYSQL_ERRMSG_SIZE, err));
10058 return 1;
10059 });
10060 int error;
10061 {
10062 /*
10063 This is the end of a statement or transaction, so close (and
10064 unlock) the tables we opened when processing the
10065 Table_map_log_event starting the statement.
10066
10067 OBSERVER. This will clear *all* mappings, not only those that
10068 are open for the table. There is not good handle for on-close
10069 actions for tables.
10070
10071 NOTE. Even if we have no table ('table' == 0) we still need to be
10072 here, so that we increase the group relay log position. If we didn't, we
10073 could have a group relay log position which lags behind "forever"
10074 (assume the last master's transaction is ignored by the slave because of
10075 replicate-ignore rules).
10076 */
10077 error = thd->binlog_flush_pending_rows_event(true);
10078
10079 /*
10080 If this event is not in a transaction, the call below will, if some
10081 transactional storage engines are involved, commit the statement into
10082 them and flush the pending event to binlog.
10083 If this event is in a transaction, the call will do nothing, but a
10084 Xid_log_event will come next which will, if some transactional engines
10085 are involved, commit the transaction and flush the pending event to the
10086 binlog.
10087 If there was a deadlock the transaction should have been rolled back
10088 already. So there should be no need to rollback the transaction.
10089 */
10090 DBUG_ASSERT(!thd->transaction_rollback_request);
10091 error |= (error ? trans_rollback_stmt(thd) : trans_commit_stmt(thd));
10092
10093 /*
10094 Now what if this is not a transactional engine? we still need to
10095 flush the pending event to the binlog; we did it with
10096 thd->binlog_flush_pending_rows_event(). Note that we imitate
10097 what is done for real queries: a call to
10098 ha_autocommit_or_rollback() (sometimes only if involves a
10099 transactional engine), and a call to be sure to have the pending
10100 event flushed.
10101 */
10102
10103 /*
10104 @todo We should probably not call
10105 reset_current_stmt_binlog_format_row() from here.
10106
10107 Btw, the previous comment about transactional engines does not
10108 seem related to anything that happens here.
10109 /Sven
10110 */
10111 thd->reset_current_stmt_binlog_format_row();
10112
10113 const_cast<Relay_log_info *>(rli)->cleanup_context(thd, false);
10114
10115 /*
10116 Clean sql_command value
10117 */
10118 thd->lex->sql_command = SQLCOM_END;
10119 }
10120 return error;
10121 }
10122
10123 /**
10124 The method either increments the relay log position or
10125 commits the current statement and increments the master group
10126 possition if the event is STMT_END_F flagged and
10127 the statement corresponds to the autocommit query (i.e replicated
10128 without wrapping in BEGIN/COMMIT)
10129
10130 @retval 0 Success
10131 @retval non-zero Error in the statement commit
10132 */
do_update_pos(Relay_log_info * rli)10133 int Rows_log_event::do_update_pos(Relay_log_info *rli) {
10134 DBUG_TRACE;
10135 int error = 0;
10136
10137 DBUG_PRINT("info", ("flags: %s", get_flags(STMT_END_F) ? "STMT_END_F " : ""));
10138
10139 /* Worker does not execute binlog update position logics */
10140 DBUG_ASSERT(!is_mts_worker(rli->info_thd));
10141
10142 if (get_flags(STMT_END_F)) {
10143 /*
10144 Indicate that a statement is finished.
10145 Step the group log position if we are not in a transaction,
10146 otherwise increase the event log position.
10147 */
10148 error = rli->stmt_done(common_header->log_pos);
10149 } else {
10150 rli->inc_event_relay_log_pos();
10151 }
10152
10153 return error;
10154 }
10155
write_data_header(Basic_ostream * ostream)10156 bool Rows_log_event::write_data_header(Basic_ostream *ostream) {
10157 uchar
10158 buf[Binary_log_event::ROWS_HEADER_LEN_V2]; // No need to init the buffer
10159 DBUG_ASSERT(m_table_id.is_valid());
10160 DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master", {
10161 int4store(buf + 0, (ulong)m_table_id.id());
10162 int2store(buf + 4, m_flags);
10163 return (wrapper_my_b_safe_write(ostream, buf, 6));
10164 });
10165 int6store(buf + ROWS_MAPID_OFFSET, m_table_id.id());
10166 int2store(buf + ROWS_FLAGS_OFFSET, m_flags);
10167 if (likely(!log_bin_use_v1_row_events)) {
10168 /*
10169 v2 event, with variable header portion.
10170 Determine length of variable header payload(extra_row_info part)
10171 */
10172 uint extra_row_info_payloadlen = EXTRA_ROW_INFO_HEADER_LENGTH;
10173 if (m_extra_row_info.have_ndb_info()) {
10174 extra_row_info_payloadlen +=
10175 (EXTRA_ROW_INFO_TYPECODE_LENGTH + m_extra_row_info.get_ndb_length());
10176 ;
10177 }
10178
10179 if (m_extra_row_info.have_part()) {
10180 extra_row_info_payloadlen +=
10181 (EXTRA_ROW_INFO_TYPECODE_LENGTH + m_extra_row_info.get_part_length());
10182 }
10183 /* Var-size header len includes len itself */
10184 int2store(buf + ROWS_VHLEN_OFFSET, extra_row_info_payloadlen);
10185 if (wrapper_my_b_safe_write(ostream, buf,
10186 Binary_log_event::ROWS_HEADER_LEN_V2))
10187 return true;
10188
10189 /* Write var-sized payload, if any */
10190 if (m_extra_row_info.have_ndb_info()) {
10191 /* Add tag and extra row info */
10192 uint8 type_code = static_cast<uint8>(enum_extra_row_info_typecode::NDB);
10193 if (wrapper_my_b_safe_write(ostream, &(type_code),
10194 EXTRA_ROW_INFO_TYPECODE_LENGTH))
10195 return true;
10196 if (wrapper_my_b_safe_write(ostream, m_extra_row_info.get_ndb_info(),
10197 m_extra_row_info.get_ndb_length()))
10198 return true;
10199 }
10200 if (m_extra_row_info.have_part()) {
10201 uint8 type_code;
10202 type_code = static_cast<uint8>(enum_extra_row_info_typecode::PART);
10203 uchar partition_buf[5];
10204 uint8 extra_part_info_data_len = 0;
10205 partition_buf[extra_part_info_data_len++] = type_code;
10206
10207 // partition_id occupies less than 2 bytes
10208 // in all the cases because of the current range of allowed number
10209 // of partitions 8192 for non-ndb and 12288 for ndb.
10210 // So while writing the partition_id it is okay to use 2 bytes for it.
10211
10212 int write_partition_id = m_extra_row_info.get_partition_id();
10213 int2store(partition_buf + extra_part_info_data_len,
10214 static_cast<uint16>(write_partition_id));
10215 extra_part_info_data_len += EXTRA_ROW_PART_INFO_VALUE_LENGTH;
10216
10217 if (get_general_type_code() == binary_log::UPDATE_ROWS_EVENT) {
10218 write_partition_id = m_extra_row_info.get_source_partition_id();
10219 int2store(partition_buf + extra_part_info_data_len,
10220 static_cast<uint16>(write_partition_id));
10221 extra_part_info_data_len += EXTRA_ROW_PART_INFO_VALUE_LENGTH;
10222 }
10223
10224 if (wrapper_my_b_safe_write(ostream, partition_buf,
10225 extra_part_info_data_len))
10226 return true;
10227 }
10228 } else {
10229 if (wrapper_my_b_safe_write(ostream, buf,
10230 Binary_log_event::ROWS_HEADER_LEN_V1))
10231 return true;
10232 }
10233
10234 return false;
10235 }
10236
write_data_body(Basic_ostream * ostream)10237 bool Rows_log_event::write_data_body(Basic_ostream *ostream) {
10238 /*
10239 Note that this should be the number of *bits*, not the number of
10240 bytes.
10241 */
10242 uchar sbuf[sizeof(m_width) + 1];
10243 ptrdiff_t const data_size = m_rows_cur - m_rows_buf;
10244 bool res = false;
10245 uchar *const sbuf_end = net_store_length(sbuf, (size_t)m_width);
10246 DBUG_ASSERT(static_cast<size_t>(sbuf_end - sbuf) <= sizeof(sbuf));
10247
10248 DBUG_DUMP("m_width", sbuf, (size_t)(sbuf_end - sbuf));
10249 res =
10250 res || wrapper_my_b_safe_write(ostream, sbuf, (size_t)(sbuf_end - sbuf));
10251
10252 DBUG_DUMP("m_cols", (uchar *)m_cols.bitmap, no_bytes_in_map(&m_cols));
10253 res = res || wrapper_my_b_safe_write(ostream, (uchar *)m_cols.bitmap,
10254 no_bytes_in_map(&m_cols));
10255 /*
10256 TODO[refactor write]: Remove the "down cast" here (and elsewhere).
10257 */
10258 if (get_general_type_code() == binary_log::UPDATE_ROWS_EVENT) {
10259 DBUG_DUMP("m_cols_ai", (uchar *)m_cols_ai.bitmap,
10260 no_bytes_in_map(&m_cols_ai));
10261 res = res || wrapper_my_b_safe_write(ostream, (uchar *)m_cols_ai.bitmap,
10262 no_bytes_in_map(&m_cols_ai));
10263 }
10264 DBUG_DUMP("rows", m_rows_buf, data_size);
10265 res = res || wrapper_my_b_safe_write(ostream, m_rows_buf, (size_t)data_size);
10266
10267 return res;
10268 }
10269
pack_info(Protocol * protocol)10270 int Rows_log_event::pack_info(Protocol *protocol) {
10271 char buf[256];
10272 char const *const flagstr = get_flags(STMT_END_F) ? " flags: STMT_END_F" : "";
10273 size_t bytes =
10274 snprintf(buf, sizeof(buf), "table_id: %llu%s", m_table_id.id(), flagstr);
10275 protocol->store_string(buf, bytes, &my_charset_bin);
10276 return 0;
10277 }
10278 #endif // MYSQL_SERVER
10279
10280 #ifndef MYSQL_SERVER
print_helper(FILE *,PRINT_EVENT_INFO * print_event_info) const10281 void Rows_log_event::print_helper(FILE *,
10282 PRINT_EVENT_INFO *print_event_info) const {
10283 IO_CACHE *const head = &print_event_info->head_cache;
10284 IO_CACHE *const body = &print_event_info->body_cache;
10285 if (!print_event_info->short_form) {
10286 bool const last_stmt_event = get_flags(STMT_END_F);
10287 print_header(head, print_event_info, !last_stmt_event);
10288 my_b_printf(head, "\t%s: table id %llu%s\n", get_type_str(),
10289 m_table_id.id(), last_stmt_event ? " flags: STMT_END_F" : "");
10290 print_base64(body, print_event_info, !last_stmt_event);
10291 }
10292 }
10293 #endif
10294
10295 /**************************************************************************
10296 Table_map_log_event member functions and support functions
10297 **************************************************************************/
10298
10299 /**
10300 @ingroup Replication
10301
10302 @page PAGE_RPL_FIELD_METADATA How replication of field metadata works.
10303
10304 When a table map is created, the master first calls
10305 Table_map_log_event::save_field_metadata() which calculates how many
10306 values will be in the field metadata. Only those fields that require the
10307 extra data are added. The method also loops through all of the fields in
10308 the table calling the method Field::save_field_metadata() which returns the
10309 values for the field that will be saved in the metadata and replicated to
10310 the slave. Once all fields have been processed, the table map is written to
10311 the binlog adding the size of the field metadata and the field metadata to
10312 the end of the body of the table map.
10313
10314 When a table map is read on the slave, the field metadata is read from the
10315 table map and passed to the table_def class constructor which saves the
10316 field metadata from the table map into an array based on the type of the
10317 field. Field metadata values not present (those fields that do not use extra
10318 data) in the table map are initialized as zero (0). The array size is the
10319 same as the columns for the table on the slave.
10320
10321 Additionally, values saved for field metadata on the master are saved as a
10322 string of bytes (uchar) in the binlog. A field may require 1 or more bytes
10323 to store the information. In cases where values require multiple bytes
10324 (e.g. values > 255), the endian-safe methods are used to properly encode
10325 the values on the master and decode them on the slave. When the field
10326 metadata values are captured on the slave, they are stored in an array of
10327 type uint. This allows the least number of casts to prevent casting bugs
10328 when the field metadata is used in comparisons of field attributes. When
10329 the field metadata is used for calculating addresses in pointer math, the
10330 type used is uint32.
10331 */
10332
10333 #if defined(MYSQL_SERVER)
10334 /**
10335 Save the field metadata based on the real_type of the field.
10336 The metadata saved depends on the type of the field. Some fields
10337 store a single byte for pack_length() while others store two bytes
10338 for field_length (max length).
10339
10340 @retval 0 Ok.
10341
10342 @todo
10343 We may want to consider changing the encoding of the information.
10344 Currently, the code attempts to minimize the number of bytes written to
10345 the tablemap. There are at least two other alternatives; 1) using
10346 net_store_length() to store the data allowing it to choose the number of
10347 bytes that are appropriate thereby making the code much easier to
10348 maintain (only 1 place to change the encoding), or 2) use a fixed number
10349 of bytes for each field. The problem with option 1 is that net_store_length()
10350 will use one byte if the value < 251, but 3 bytes if it is > 250. Thus,
10351 for fields like CHAR which can be no larger than 255 characters, the method
10352 will use 3 bytes when the value is > 250. Further, every value that is
10353 encoded using 2 parts (e.g., pack_length, field_length) will be numerically
10354 > 250 therefore will use 3 bytes for eah value. The problem with option 2
10355 is less wasteful for space but does waste 1 byte for every field that does
10356 not encode 2 parts.
10357 */
save_field_metadata()10358 int Table_map_log_event::save_field_metadata() {
10359 DBUG_TRACE;
10360 int index = 0;
10361 for (auto it = this->m_fields.begin(); it != this->m_fields.end(); ++it) {
10362 Field *field = *it;
10363 DBUG_PRINT("debug", ("field_type: %d", m_coltype[it.filtered_pos()]));
10364 index += field->save_field_metadata(&m_field_metadata[index]);
10365
10366 DBUG_EXECUTE_IF("inject_invalid_blob_size", {
10367 if (m_coltype[it.filtered_pos()] == MYSQL_TYPE_BLOB)
10368 m_field_metadata[index - 1] = 5;
10369 });
10370 }
10371 return index;
10372 }
10373
10374 /*
10375 Constructor used to build an event for writing to the binary log.
10376 Mats says tbl->s lives longer than this event so it's ok to copy pointers
10377 (tbl->s->db etc) and not pointer content.
10378 */
10379
Table_map_log_event(THD * thd_arg,TABLE * tbl,const Table_id & tid,bool using_trans)10380 Table_map_log_event::Table_map_log_event(THD *thd_arg, TABLE *tbl,
10381 const Table_id &tid, bool using_trans)
10382 : binary_log::Table_map_event(
10383 tid,
10384 tbl->s->fields +
10385 DBUG_EVALUATE_IF("binlog_omit_last_column_from_table_map_event",
10386 -1, 0),
10387 (tbl->s->db.str), ((tbl->s->db.str) ? tbl->s->db.length : 0),
10388 (tbl->s->table_name.str), (tbl->s->table_name.length)),
10389 Log_event(thd_arg, 0,
10390 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE
10391 : Log_event::EVENT_STMT_CACHE,
10392 Log_event::EVENT_NORMAL_LOGGING, header(), footer()),
10393 m_fields{tbl, Replicated_columns_view::OUTBOUND} {
10394 common_header->type_code = binary_log::TABLE_MAP_EVENT;
10395 m_table = tbl;
10396 m_flags = TM_BIT_LEN_EXACT_F;
10397
10398 this->m_colcnt =
10399 this->m_fields.filtered_size() +
10400 DBUG_EVALUATE_IF("binlog_omit_last_column_from_table_map_event", -1, 0);
10401
10402 uchar cbuf[sizeof(m_colcnt) + 1];
10403 uchar *cbuf_end;
10404 DBUG_ASSERT(m_table_id.is_valid());
10405 /*
10406 In TABLE_SHARE, "db" and "table_name" are 0-terminated (see this comment in
10407 table.cc / alloc_table_share():
10408 Use the fact the key is db/0/table_name/0
10409 As we rely on this let's assert it.
10410 */
10411 DBUG_ASSERT((tbl->s->db.str == nullptr) ||
10412 (tbl->s->db.str[tbl->s->db.length] == 0));
10413 DBUG_ASSERT(tbl->s->table_name.str[tbl->s->table_name.length] == 0);
10414
10415 m_data_size = Binary_log_event::TABLE_MAP_HEADER_LEN;
10416 DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master", m_data_size = 6;);
10417 m_data_size += m_dblen + 2; // Include length and terminating \0
10418 m_data_size += m_tbllen + 2; // Include length and terminating \0
10419 cbuf_end = net_store_length(cbuf, (size_t)m_colcnt);
10420 DBUG_ASSERT(static_cast<size_t>(cbuf_end - cbuf) <= sizeof(cbuf));
10421 m_data_size += (cbuf_end - cbuf) + m_colcnt; // COLCNT and column types
10422
10423 m_coltype = (uchar *)my_malloc(key_memory_log_event, m_colcnt, MYF(MY_WME));
10424
10425 DBUG_ASSERT(m_colcnt ==
10426 this->m_fields.filtered_size() +
10427 DBUG_EVALUATE_IF(
10428 "binlog_omit_last_column_from_table_map_event", -1, 0));
10429
10430 for (auto it = this->m_fields.begin();
10431 it != this->m_fields.end() &&
10432 DBUG_EVALUATE_IF("binlog_omit_last_column_from_table_map_event",
10433 it.filtered_pos() != this->m_colcnt, true);
10434 ++it) {
10435 Field *field = *it;
10436 m_coltype[it.filtered_pos()] = field->binlog_type();
10437 }
10438 DBUG_EXECUTE_IF("inject_invalid_column_type", m_coltype[1] = 230;);
10439
10440 /*
10441 Calculate a bitmap for the results of maybe_null() for all columns.
10442 The bitmap is used to determine when there is a column from the master
10443 that is not on the slave and is null and thus not in the row data during
10444 replication.
10445 */
10446 uint num_null_bytes = (m_colcnt + 7) / 8;
10447 m_data_size += num_null_bytes;
10448 /*
10449 m_null_bits is a pointer indicating which columns can have a null value
10450 in a particular table.
10451 */
10452 m_null_bits =
10453 (uchar *)my_malloc(key_memory_log_event, num_null_bytes, MYF(MY_WME));
10454
10455 m_field_metadata =
10456 (uchar *)my_malloc(key_memory_log_event, (m_colcnt * 4), MYF(MY_WME));
10457 memset(m_field_metadata, 0, (m_colcnt * 4));
10458
10459 common_header->set_is_valid(m_null_bits != nullptr &&
10460 m_field_metadata != nullptr &&
10461 m_coltype != nullptr);
10462 /*
10463 Create an array for the field metadata and store it.
10464 */
10465 m_field_metadata_size = save_field_metadata();
10466 DBUG_ASSERT(m_field_metadata_size <= (m_colcnt * 4));
10467
10468 /*
10469 Now set the size of the data to the size of the field metadata array
10470 plus one or three bytes (see pack.c:net_store_length) for number of
10471 elements in the field metadata array.
10472 */
10473 if (m_field_metadata_size < 251)
10474 m_data_size += m_field_metadata_size + 1;
10475 else
10476 m_data_size += m_field_metadata_size + 3;
10477
10478 memset(m_null_bits, 0, num_null_bytes);
10479 Bit_writer bit_writer{this->m_null_bits};
10480 for (auto field : this->m_fields) bit_writer.set(field->is_nullable());
10481 /*
10482 Marking event to require sequential execution in MTS
10483 if the query might have updated FK-referenced db.
10484 Unlike Query_log_event where this fact is encoded through
10485 the accessed db list in the Table_map case m_flags is exploited.
10486 */
10487 uchar dbs = thd_arg->get_binlog_accessed_db_names()
10488 ? thd_arg->get_binlog_accessed_db_names()->elements
10489 : 0;
10490 if (dbs == 1) {
10491 char *db_name = thd_arg->get_binlog_accessed_db_names()->head();
10492 if (!strcmp(db_name, "")) m_flags |= TM_REFERRED_FK_DB_F;
10493 }
10494
10495 init_metadata_fields();
10496 m_data_size += m_metadata_buf.length();
10497 }
10498 #endif /* defined(MYSQL_SERVER) */
10499
10500 /*
10501 Constructor used by slave to read the event from the binary log.
10502 */
Table_map_log_event(const char * buf,const Format_description_event * description_event)10503 Table_map_log_event::Table_map_log_event(
10504 const char *buf, const Format_description_event *description_event)
10505 : binary_log::Table_map_event(buf, description_event),
10506 Log_event(header(), footer())
10507 #ifdef MYSQL_SERVER
10508 ,
10509 m_table(nullptr),
10510 m_fields(Replicated_columns_view::INBOUND)
10511 #endif
10512 {
10513 DBUG_TRACE;
10514 DBUG_ASSERT(header()->type_code == binary_log::TABLE_MAP_EVENT);
10515 }
10516
~Table_map_log_event()10517 Table_map_log_event::~Table_map_log_event() {}
10518
10519 /*
10520 Return value is an error code, one of:
10521
10522 -1 Failure to open table [from open_tables()]
10523 0 Success
10524 1 No room for more tables [from set_table()]
10525 2 Out of memory [from set_table()]
10526 3 Wrong table definition
10527 4 Daisy-chaining RBR with SBR not possible
10528 */
10529
10530 #if defined(MYSQL_SERVER)
10531
10532 enum enum_tbl_map_status {
10533 /* no duplicate identifier found */
10534 OK_TO_PROCESS = 0,
10535
10536 /* this table map must be filtered out */
10537 FILTERED_OUT = 1,
10538
10539 /* identifier mapping table with different properties */
10540 SAME_ID_MAPPING_DIFFERENT_TABLE = 2,
10541
10542 /* a duplicate identifier was found mapping the same table */
10543 SAME_ID_MAPPING_SAME_TABLE = 3,
10544
10545 /*
10546 this table must be filtered out but found an active XA transaction. XA
10547 transactions shouldn't be used with replication filters, until disabling
10548 the XA read only optimization is a supported feature.
10549 */
10550 FILTERED_WITH_XA_ACTIVE = 4
10551 };
10552
10553 /*
10554 Checks if this table map event should be processed or not. First
10555 it checks the filtering rules, and then looks for duplicate identifiers
10556 in the existing list of rli->tables_to_lock.
10557
10558 It checks that there hasn't been any corruption by verifying that there
10559 are no duplicate entries with different properties.
10560
10561 In some cases, some binary logs could get corrupted, showing several
10562 tables mapped to the same table_id, 0 (see: BUG#56226). Thus we do this
10563 early sanity check for such cases and avoid that the server crashes
10564 later.
10565
10566 In some corner cases, the master logs duplicate table map events, i.e.,
10567 same id, same database name, same table name (see: BUG#37137). This is
10568 different from the above as it's the same table that is mapped again
10569 to the same identifier. Thus we cannot just check for same ids and
10570 assume that the event is corrupted we need to check every property.
10571
10572 NOTE: in the event that BUG#37137 ever gets fixed, this extra check
10573 will still be valid because we would need to support old binary
10574 logs anyway.
10575
10576 @param rli The relay log info reference.
10577 @param table_list A list element containing the table to check against.
10578 @return OK_TO_PROCESS
10579 if there was no identifier already in rli->tables_to_lock
10580
10581 FILTERED_OUT
10582 if the event is filtered according to the filtering rules
10583
10584 SAME_ID_MAPPING_DIFFERENT_TABLE
10585 if the same identifier already maps a different table in
10586 rli->tables_to_lock
10587
10588 SAME_ID_MAPPING_SAME_TABLE
10589 if the same identifier already maps the same table in
10590 rli->tables_to_lock.
10591 */
check_table_map(Relay_log_info const * rli,RPL_TABLE_LIST * table_list)10592 static enum_tbl_map_status check_table_map(Relay_log_info const *rli,
10593 RPL_TABLE_LIST *table_list) {
10594 DBUG_TRACE;
10595 enum_tbl_map_status res = OK_TO_PROCESS;
10596
10597 if (rli->info_thd->slave_thread /* filtering is for slave only */ &&
10598 (!rli->rpl_filter->db_ok(table_list->db) ||
10599 (rli->rpl_filter->is_on() &&
10600 !rli->rpl_filter->tables_ok("", table_list))))
10601 if (rli->info_thd->get_transaction()->xid_state()->has_state(
10602 XID_STATE::XA_ACTIVE))
10603 res = FILTERED_WITH_XA_ACTIVE;
10604 else
10605 res = FILTERED_OUT;
10606 else {
10607 RPL_TABLE_LIST *ptr = static_cast<RPL_TABLE_LIST *>(rli->tables_to_lock);
10608 for (uint i = 0; ptr && (i < rli->tables_to_lock_count);
10609 ptr = static_cast<RPL_TABLE_LIST *>(ptr->next_local), i++) {
10610 if (ptr->table_id == table_list->table_id) {
10611 if (strcmp(ptr->db, table_list->db) ||
10612 strcmp(ptr->alias, table_list->table_name) ||
10613 ptr->lock_descriptor().type !=
10614 TL_WRITE) // the ::do_apply_event always sets TL_WRITE
10615 res = SAME_ID_MAPPING_DIFFERENT_TABLE;
10616 else
10617 res = SAME_ID_MAPPING_SAME_TABLE;
10618
10619 break;
10620 }
10621 }
10622 }
10623
10624 DBUG_PRINT("debug", ("check of table map ended up with: %u", res));
10625
10626 return res;
10627 }
10628
do_apply_event(Relay_log_info const * rli)10629 int Table_map_log_event::do_apply_event(Relay_log_info const *rli) {
10630 RPL_TABLE_LIST *table_list;
10631 char *db_mem, *tname_mem;
10632 const char *ptr;
10633 size_t dummy_len;
10634 void *memory;
10635 DBUG_TRACE;
10636 DBUG_ASSERT(rli->info_thd == thd);
10637
10638 /* Step the query id to mark what columns that are actually used. */
10639 thd->set_query_id(next_query_id());
10640
10641 if (!(memory =
10642 my_multi_malloc(key_memory_log_event, MYF(MY_WME), &table_list,
10643 sizeof(RPL_TABLE_LIST), &db_mem, (uint)NAME_LEN + 1,
10644 &tname_mem, (uint)NAME_LEN + 1, NullS)))
10645 return HA_ERR_OUT_OF_MEM;
10646
10647 my_stpcpy(db_mem, m_dbnam.c_str());
10648 my_stpcpy(tname_mem, m_tblnam.c_str());
10649
10650 if (lower_case_table_names) {
10651 my_casedn_str(system_charset_info, db_mem);
10652 my_casedn_str(system_charset_info, tname_mem);
10653 }
10654
10655 /* rewrite rules changed the database */
10656 if (rli->rpl_filter != nullptr &&
10657 ((ptr = rli->rpl_filter->get_rewrite_db(db_mem, &dummy_len)) != db_mem)) {
10658 rli->rpl_filter->get_rewrite_db_statistics()->increase_counter();
10659 my_stpcpy(db_mem, ptr);
10660 }
10661
10662 new (table_list) RPL_TABLE_LIST(db_mem, strlen(db_mem), tname_mem,
10663 strlen(tname_mem), tname_mem, TL_WRITE);
10664
10665 table_list->table_id = DBUG_EVALUATE_IF(
10666 "inject_tblmap_same_id_maps_diff_table", 0, m_table_id.id());
10667 table_list->updating = true;
10668 table_list->required_type = dd::enum_table_type::BASE_TABLE;
10669 DBUG_PRINT("debug", ("table: %s is mapped to %llu", table_list->table_name,
10670 table_list->table_id.id()));
10671
10672 enum_tbl_map_status tblmap_status = check_table_map(rli, table_list);
10673 if (tblmap_status == OK_TO_PROCESS) {
10674 DBUG_ASSERT(thd->lex->query_tables != table_list);
10675
10676 /*
10677 Use placement new to construct the table_def instance in the
10678 memory allocated for it inside table_list.
10679
10680 The memory allocated by the table_def structure (i.e., not the
10681 memory allocated *for* the table_def structure) is released
10682 inside Relay_log_info::clear_tables_to_lock() by calling the
10683 table_def destructor explicitly.
10684 */
10685 new (&table_list->m_tabledef)
10686 table_def(m_coltype, m_colcnt, m_field_metadata, m_field_metadata_size,
10687 m_null_bits, m_flags);
10688
10689 table_list->m_tabledef_valid = true;
10690 table_list->m_conv_table = nullptr;
10691 table_list->open_type = OT_BASE_ONLY;
10692
10693 /*
10694 We record in the slave's information that the table should be
10695 locked by linking the table into the list of tables to lock.
10696 */
10697 table_list->next_global = table_list->next_local = rli->tables_to_lock;
10698 const_cast<Relay_log_info *>(rli)->tables_to_lock = table_list;
10699 const_cast<Relay_log_info *>(rli)->tables_to_lock_count++;
10700 /* 'memory' is freed in clear_tables_to_lock */
10701 } else // FILTERED_OUT, SAME_ID_MAPPING_*
10702 {
10703 if (tblmap_status == FILTERED_WITH_XA_ACTIVE) {
10704 if (thd->slave_thread)
10705 rli->report(ERROR_LEVEL, ER_XA_REPLICATION_FILTERS, "%s",
10706 ER_THD(thd, ER_XA_REPLICATION_FILTERS));
10707 else
10708 /*
10709 For the cases in which a 'BINLOG' statement is set to
10710 execute in a user session
10711 */
10712 my_printf_error(ER_XA_REPLICATION_FILTERS, "%s", MYF(0),
10713 ER_THD(thd, ER_XA_REPLICATION_FILTERS));
10714 }
10715 /*
10716 If mapped already but with different properties, we raise an
10717 error.
10718 If mapped already but with same properties we skip the event.
10719 If filtered out we skip the event.
10720
10721 In all three cases, we need to free the memory previously
10722 allocated.
10723 */
10724 else if (tblmap_status == SAME_ID_MAPPING_DIFFERENT_TABLE) {
10725 /*
10726 Something bad has happened. We need to stop the slave as strange things
10727 could happen if we proceed: slave crash, wrong table being updated, ...
10728 As a consequence we push an error in this case.
10729 */
10730
10731 char buf[256];
10732
10733 snprintf(buf, sizeof(buf),
10734 "Found table map event mapping table id %llu which "
10735 "was already mapped but with different settings.",
10736 table_list->table_id.id());
10737
10738 if (thd->slave_thread)
10739 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
10740 ER_THD(thd, ER_SLAVE_FATAL_ERROR), buf);
10741 else
10742 /*
10743 For the cases in which a 'BINLOG' statement is set to
10744 execute in a user session
10745 */
10746 my_printf_error(ER_BINLOG_FATAL_ERROR,
10747 ER_THD(thd, ER_BINLOG_FATAL_ERROR), MYF(0), buf);
10748 }
10749
10750 my_free(memory);
10751 }
10752
10753 return tblmap_status == SAME_ID_MAPPING_DIFFERENT_TABLE;
10754 }
10755
do_shall_skip(Relay_log_info * rli)10756 Log_event::enum_skip_reason Table_map_log_event::do_shall_skip(
10757 Relay_log_info *rli) {
10758 /*
10759 If the slave skip counter is 1, then we should not start executing
10760 on the next event.
10761 */
10762 return continue_group(rli);
10763 }
10764
do_update_pos(Relay_log_info * rli)10765 int Table_map_log_event::do_update_pos(Relay_log_info *rli) {
10766 rli->inc_event_relay_log_pos();
10767 return 0;
10768 }
10769
write_data_header(Basic_ostream * ostream)10770 bool Table_map_log_event::write_data_header(Basic_ostream *ostream) {
10771 DBUG_ASSERT(m_table_id.is_valid());
10772 uchar buf[Binary_log_event::TABLE_MAP_HEADER_LEN];
10773 DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master", {
10774 int4store(buf + 0, static_cast<uint32>(m_table_id.id()));
10775 int2store(buf + 4, m_flags);
10776 return (wrapper_my_b_safe_write(ostream, buf, 6));
10777 });
10778 int6store(buf + TM_MAPID_OFFSET, m_table_id.id());
10779 int2store(buf + TM_FLAGS_OFFSET, m_flags);
10780 return (wrapper_my_b_safe_write(ostream, buf,
10781 Binary_log_event::TABLE_MAP_HEADER_LEN));
10782 }
10783
write_data_body(Basic_ostream * ostream)10784 bool Table_map_log_event::write_data_body(Basic_ostream *ostream) {
10785 DBUG_ASSERT(!m_dbnam.empty());
10786 DBUG_ASSERT(!m_tblnam.empty());
10787 /* We use only one byte per length for storage in event: */
10788 DBUG_ASSERT(m_dblen <= 128);
10789 DBUG_ASSERT(m_tbllen <= 128);
10790
10791 uchar const dbuf[] = {(uchar)m_dblen};
10792 uchar const tbuf[] = {(uchar)m_tbllen};
10793
10794 uchar cbuf[sizeof(m_colcnt) + 1];
10795 uchar *const cbuf_end = net_store_length(cbuf, (size_t)m_colcnt);
10796 DBUG_ASSERT(static_cast<size_t>(cbuf_end - cbuf) <= sizeof(cbuf));
10797
10798 /*
10799 Store the size of the field metadata.
10800 */
10801 uchar mbuf[sizeof(m_field_metadata_size)];
10802 uchar *const mbuf_end = net_store_length(mbuf, m_field_metadata_size);
10803
10804 return (wrapper_my_b_safe_write(ostream, dbuf, sizeof(dbuf)) ||
10805 wrapper_my_b_safe_write(ostream, (const uchar *)m_dbnam.c_str(),
10806 m_dblen + 1) ||
10807 wrapper_my_b_safe_write(ostream, tbuf, sizeof(tbuf)) ||
10808 wrapper_my_b_safe_write(ostream, (const uchar *)m_tblnam.c_str(),
10809 m_tbllen + 1) ||
10810 wrapper_my_b_safe_write(ostream, cbuf, (size_t)(cbuf_end - cbuf)) ||
10811 wrapper_my_b_safe_write(ostream, m_coltype, m_colcnt) ||
10812 wrapper_my_b_safe_write(ostream, mbuf, (size_t)(mbuf_end - mbuf)) ||
10813 wrapper_my_b_safe_write(ostream, m_field_metadata,
10814 m_field_metadata_size) ||
10815 wrapper_my_b_safe_write(ostream, m_null_bits, (m_colcnt + 7) / 8) ||
10816 wrapper_my_b_safe_write(ostream, (const uchar *)m_metadata_buf.ptr(),
10817 m_metadata_buf.length()));
10818 }
10819
10820 /**
10821 stores an integer into packed format.
10822
10823 @param[out] str_buf a buffer where the packed integer will be stored.
10824 @param[in] length the integer will be packed.
10825 */
store_compressed_length(String & str_buf,ulonglong length)10826 static inline void store_compressed_length(String &str_buf, ulonglong length) {
10827 // Store Type and packed length
10828 uchar buf[4];
10829 uchar *buf_ptr = net_store_length(buf, length);
10830
10831 str_buf.append(reinterpret_cast<char *>(buf), buf_ptr - buf);
10832 }
10833
10834 /**
10835 Write data into str_buf with Type|Length|Value(TLV) format.
10836
10837 @param[out] str_buf a buffer where the field is stored.
10838 @param[in] type type of the field
10839 @param[in] length length of the field value
10840 @param[in] value value of the field
10841 */
write_tlv_field(String & str_buf,enum Table_map_log_event::Optional_metadata_field_type type,uint length,const uchar * value)10842 static inline bool write_tlv_field(
10843 String &str_buf,
10844 enum Table_map_log_event::Optional_metadata_field_type type, uint length,
10845 const uchar *value) {
10846 /* type is stored in one byte, so it should never bigger than 255. */
10847 DBUG_ASSERT(static_cast<int>(type) <= 255);
10848 str_buf.append((char)type);
10849 store_compressed_length(str_buf, length);
10850 return str_buf.append(reinterpret_cast<const char *>(value), length);
10851 }
10852
10853 /**
10854 Write data into str_buf with Type|Length|Value(TLV) format.
10855
10856 @param[out] str_buf a buffer where the field is stored.
10857 @param[in] type type of the field
10858 @param[in] value value of the field
10859 */
write_tlv_field(String & str_buf,enum Table_map_log_event::Optional_metadata_field_type type,const String & value)10860 static inline bool write_tlv_field(
10861 String &str_buf,
10862 enum Table_map_log_event::Optional_metadata_field_type type,
10863 const String &value) {
10864 return write_tlv_field(str_buf, type, value.length(),
10865 reinterpret_cast<const uchar *>(value.ptr()));
10866 }
10867 #endif // MYSQL_SERVER
10868
10869 #ifndef MYSQL_SERVER
10870 // For MYSQL_SERVER, the version in field.h is used.
is_numeric_type(uint type)10871 static inline bool is_numeric_type(uint type) {
10872 switch (type) {
10873 case MYSQL_TYPE_TINY:
10874 case MYSQL_TYPE_SHORT:
10875 case MYSQL_TYPE_INT24:
10876 case MYSQL_TYPE_LONG:
10877 case MYSQL_TYPE_LONGLONG:
10878 case MYSQL_TYPE_NEWDECIMAL:
10879 case MYSQL_TYPE_FLOAT:
10880 case MYSQL_TYPE_DOUBLE:
10881 return true;
10882 default:
10883 return false;
10884 }
10885 return false;
10886 }
10887 #endif // !MYSQL_SERVER
10888
is_character_type(uint type)10889 static inline bool is_character_type(uint type) {
10890 switch (type) {
10891 case MYSQL_TYPE_STRING:
10892 case MYSQL_TYPE_VAR_STRING:
10893 case MYSQL_TYPE_VARCHAR:
10894 case MYSQL_TYPE_BLOB:
10895 return true;
10896 default:
10897 return false;
10898 }
10899 }
10900
is_enum_or_set_type(uint type)10901 static inline bool is_enum_or_set_type(uint type) {
10902 return type == MYSQL_TYPE_ENUM || type == MYSQL_TYPE_SET;
10903 }
10904
10905 #ifdef MYSQL_SERVER
is_numeric_field(const Field * field)10906 static inline bool is_numeric_field(const Field *field) {
10907 return is_numeric_type(field->binlog_type());
10908 }
10909
is_character_field(const Field * field)10910 static inline bool is_character_field(const Field *field) {
10911 return is_character_type(field->real_type());
10912 }
10913
is_enum_field(const Field * field)10914 static inline bool is_enum_field(const Field *field) {
10915 return field->real_type() == MYSQL_TYPE_ENUM;
10916 }
10917
is_set_field(const Field * field)10918 static inline bool is_set_field(const Field *field) {
10919 return field->real_type() == MYSQL_TYPE_SET;
10920 }
10921
is_enum_or_set_field(const Field * field)10922 static inline bool is_enum_or_set_field(const Field *field) {
10923 return is_enum_or_set_type(field->real_type());
10924 }
10925
is_geometry_field(const Field * field)10926 static inline bool is_geometry_field(const Field *field) {
10927 return field->real_type() == MYSQL_TYPE_GEOMETRY;
10928 }
10929
init_metadata_fields()10930 void Table_map_log_event::init_metadata_fields() {
10931 DBUG_TRACE;
10932 DBUG_EXECUTE_IF("simulate_no_optional_metadata", return;);
10933
10934 if (init_signedness_field() ||
10935 init_charset_field(&is_character_field, DEFAULT_CHARSET,
10936 COLUMN_CHARSET) ||
10937 init_geometry_type_field()) {
10938 m_metadata_buf.length(0);
10939 return;
10940 }
10941
10942 if (binlog_row_metadata == BINLOG_ROW_METADATA_FULL) {
10943 if (DBUG_EVALUATE_IF("dont_log_column_name", 0, init_column_name_field()) ||
10944 init_charset_field(&is_enum_or_set_field, ENUM_AND_SET_DEFAULT_CHARSET,
10945 ENUM_AND_SET_COLUMN_CHARSET) ||
10946 init_set_str_value_field() || init_enum_str_value_field() ||
10947 init_primary_key_field()) {
10948 m_metadata_buf.length(0);
10949 }
10950 }
10951 }
10952
init_signedness_field()10953 bool Table_map_log_event::init_signedness_field() {
10954 /* use it to store signed flags, each numeric column take a bit. */
10955 StringBuffer<128> buf;
10956 unsigned char flag = 0;
10957 unsigned char mask = 0x80;
10958
10959 for (auto field : this->m_fields) {
10960 if (is_numeric_field(field)) {
10961 Field_num *field_num = dynamic_cast<Field_num *>(field);
10962 if (field_num->is_unsigned()) flag |= mask;
10963
10964 mask >>= 1;
10965
10966 // 8 fields are tested, store the result and clear the flag.
10967 if (mask == 0) {
10968 buf.append(flag);
10969 flag = 0;
10970 mask = 0x80;
10971 }
10972 }
10973 }
10974
10975 // Stores the signedness flags of last few columns
10976 if (mask != 0x80) buf.append(flag);
10977
10978 // The table has no numeric column, so don't log SIGNEDNESS field
10979 if (buf.is_empty()) return false;
10980
10981 return write_tlv_field(m_metadata_buf, SIGNEDNESS, buf);
10982 }
10983
init_charset_field(std::function<bool (const Field *)> include_type,Optional_metadata_field_type default_charset_type,Optional_metadata_field_type column_charset_type)10984 bool Table_map_log_event::init_charset_field(
10985 std::function<bool(const Field *)> include_type,
10986 Optional_metadata_field_type default_charset_type,
10987 Optional_metadata_field_type column_charset_type) {
10988 DBUG_EXECUTE_IF("simulate_init_charset_field_error", return true;);
10989
10990 std::map<uint, uint> collation_map;
10991 // For counting characters columns
10992 uint char_col_cnt = 0;
10993
10994 /* Find the collation number used by most fields */
10995 for (auto field : this->m_fields) {
10996 if (include_type(field)) {
10997 Field_str *field_str = dynamic_cast<Field_str *>(field);
10998
10999 collation_map[field_str->charset()->number]++;
11000 char_col_cnt++;
11001 }
11002 }
11003
11004 if (char_col_cnt == 0) return false;
11005
11006 /* Find the most used collation */
11007 uint most_used_collation = 0;
11008 uint most_used_count = 0;
11009 for (std::map<uint, uint>::iterator it = collation_map.begin();
11010 it != collation_map.end(); it++) {
11011 if (it->second > most_used_count) {
11012 most_used_count = it->second;
11013 most_used_collation = it->first;
11014 }
11015 }
11016
11017 /*
11018 Comparing length of COLUMN_CHARSET field and COLUMN_CHARSET_WITH_DEFAULT
11019 field to decide which field should be logged.
11020
11021 Length of COLUMN_CHARSET = character column count * collation id size.
11022 Length of COLUMN_CHARSET_WITH_DEFAULT =
11023 default collation_id size + count of columns not use default charset *
11024 (column index size + collation id size)
11025
11026 Assume column index just uses 1 byte and collation number also uses 1 byte.
11027 */
11028 if (char_col_cnt * 1 < (1 + (char_col_cnt - most_used_count) * 2)) {
11029 StringBuffer<512> buf;
11030
11031 /*
11032 Stores character set information into COLUMN_CHARSET format,
11033 character sets of all columns are stored one by one.
11034 -----------------------------------------
11035 | Charset number | .... |Charset number |
11036 -----------------------------------------
11037 */
11038 for (auto field : this->m_fields) {
11039 if (include_type(field)) {
11040 Field_str *field_str = dynamic_cast<Field_str *>(field);
11041
11042 store_compressed_length(buf, field_str->charset()->number);
11043 }
11044 }
11045 return write_tlv_field(m_metadata_buf, column_charset_type, buf);
11046 } else {
11047 StringBuffer<512> buf;
11048 uint char_column_index = 0;
11049 uint default_collation = most_used_collation;
11050
11051 /*
11052 Stores character set information into DEFAULT_CHARSET format,
11053 First stores the default character set, and then stores the character
11054 sets different to default character with their column index one by one.
11055 --------------------------------------------------------
11056 | Default Charset | Col Index | Charset number | ... |
11057 --------------------------------------------------------
11058 */
11059
11060 // Store the default collation number
11061 store_compressed_length(buf, default_collation);
11062
11063 for (auto field : this->m_fields) {
11064 if (include_type(field)) {
11065 Field_str *field_str = dynamic_cast<Field_str *>(field);
11066
11067 if (field_str->charset()->number != default_collation) {
11068 store_compressed_length(buf, char_column_index);
11069 store_compressed_length(buf, field_str->charset()->number);
11070 }
11071 char_column_index++;
11072 }
11073 }
11074 return write_tlv_field(m_metadata_buf, default_charset_type, buf);
11075 }
11076 }
11077
init_column_name_field()11078 bool Table_map_log_event::init_column_name_field() {
11079 StringBuffer<2048> buf;
11080
11081 for (auto field : this->m_fields) {
11082 size_t len = strlen(field->field_name);
11083
11084 store_compressed_length(buf, len);
11085 buf.append(field->field_name, len);
11086 }
11087 return write_tlv_field(m_metadata_buf, COLUMN_NAME, buf);
11088 }
11089
init_set_str_value_field()11090 bool Table_map_log_event::init_set_str_value_field() {
11091 StringBuffer<1024> buf;
11092
11093 /*
11094 SET string values are stored in the same format:
11095 ----------------------------------------------
11096 | Value number | value1 len | value 1| .... | // first SET column
11097 ----------------------------------------------
11098 | Value number | value1 len | value 1| .... | // second SET column
11099 ----------------------------------------------
11100 */
11101 for (auto field : this->m_fields) {
11102 if (is_set_field(field)) {
11103 TYPELIB *typelib = dynamic_cast<Field_set *>(field)->typelib;
11104
11105 store_compressed_length(buf, typelib->count);
11106 for (unsigned int i = 0; i < typelib->count; i++) {
11107 store_compressed_length(buf, typelib->type_lengths[i]);
11108 buf.append(typelib->type_names[i], typelib->type_lengths[i]);
11109 }
11110 }
11111 }
11112 if (buf.length() > 0)
11113 return write_tlv_field(m_metadata_buf, SET_STR_VALUE, buf);
11114 return false;
11115 }
11116
init_enum_str_value_field()11117 bool Table_map_log_event::init_enum_str_value_field() {
11118 StringBuffer<1024> buf;
11119
11120 /* ENUM is same to SET columns, see comment in init_set_str_value_field */
11121 for (auto field : this->m_fields) {
11122 if (is_enum_field(field)) {
11123 TYPELIB *typelib = dynamic_cast<Field_enum *>(field)->typelib;
11124
11125 store_compressed_length(buf, typelib->count);
11126 for (unsigned int i = 0; i < typelib->count; i++) {
11127 store_compressed_length(buf, typelib->type_lengths[i]);
11128 buf.append(typelib->type_names[i], typelib->type_lengths[i]);
11129 }
11130 }
11131 }
11132
11133 if (buf.length() > 0)
11134 return write_tlv_field(m_metadata_buf, ENUM_STR_VALUE, buf);
11135 return false;
11136 }
11137
init_geometry_type_field()11138 bool Table_map_log_event::init_geometry_type_field() {
11139 StringBuffer<256> buf;
11140
11141 /* Geometry type of geometry columns is stored one by one as packed length */
11142 for (auto field : this->m_fields) {
11143 if (is_geometry_field(field)) {
11144 int type = dynamic_cast<Field_geom *>(field)->geom_type;
11145 DBUG_EXECUTE_IF("inject_invalid_geometry_type", type = 100;);
11146 store_compressed_length(buf, type);
11147 }
11148 }
11149
11150 if (buf.length() > 0)
11151 return write_tlv_field(m_metadata_buf, GEOMETRY_TYPE, buf);
11152 return false;
11153 }
11154
init_primary_key_field()11155 bool Table_map_log_event::init_primary_key_field() {
11156 DBUG_EXECUTE_IF("simulate_init_primary_key_field_error", return true;);
11157
11158 if (unlikely(m_table->s->is_missing_primary_key())) return false;
11159
11160 // If any key column uses prefix like KEY(c1(10)) */
11161 bool has_prefix = false;
11162 KEY *pk = m_table->key_info + m_table->s->primary_key;
11163
11164 DBUG_ASSERT(pk->user_defined_key_parts > 0);
11165
11166 /* Check if any key column uses prefix */
11167 for (uint i = 0; i < pk->user_defined_key_parts; i++) {
11168 KEY_PART_INFO *key_part = pk->key_part + i;
11169 if (key_part->length !=
11170 m_table->field[key_part->fieldnr - 1]->key_length()) {
11171 has_prefix = true;
11172 break;
11173 }
11174 }
11175
11176 StringBuffer<128> buf;
11177
11178 if (!has_prefix) {
11179 /* Index of PK columns are stored one by one. */
11180 for (uint i = 0; i < pk->user_defined_key_parts; i++) {
11181 KEY_PART_INFO *key_part = pk->key_part + i;
11182 store_compressed_length(buf, key_part->fieldnr - 1);
11183 }
11184 return write_tlv_field(m_metadata_buf, SIMPLE_PRIMARY_KEY, buf);
11185 } else {
11186 /* Index of PK columns are stored with a prefix length one by one. */
11187 for (uint i = 0; i < pk->user_defined_key_parts; i++) {
11188 KEY_PART_INFO *key_part = pk->key_part + i;
11189 size_t prefix = 0;
11190
11191 store_compressed_length(buf, key_part->fieldnr - 1);
11192
11193 // Store character length but not octet length
11194 if (key_part->length !=
11195 m_table->field[key_part->fieldnr - 1]->key_length())
11196 prefix = key_part->length / key_part->field->charset()->mbmaxlen;
11197 store_compressed_length(buf, prefix);
11198 }
11199 return write_tlv_field(m_metadata_buf, PRIMARY_KEY_WITH_PREFIX, buf);
11200 }
11201 }
11202
11203 /*
11204 Print some useful information for the SHOW BINARY LOG information
11205 field.
11206 */
11207
pack_info(Protocol * protocol)11208 int Table_map_log_event::pack_info(Protocol *protocol) {
11209 char buf[256];
11210 size_t bytes = snprintf(buf, sizeof(buf), "table_id: %llu (%s.%s)",
11211 m_table_id.id(), m_dbnam.c_str(), m_tblnam.c_str());
11212 DBUG_ASSERT(bytes < 256);
11213 protocol->store_string(buf, bytes, &my_charset_bin);
11214 return 0;
11215 }
11216 #endif // MYSQL_SERVER
11217
11218 #ifndef MYSQL_SERVER
print(FILE *,PRINT_EVENT_INFO * print_event_info) const11219 void Table_map_log_event::print(FILE *,
11220 PRINT_EVENT_INFO *print_event_info) const {
11221 if (!print_event_info->short_form) {
11222 print_header(&print_event_info->head_cache, print_event_info, true);
11223 my_b_printf(&print_event_info->head_cache,
11224 "\tTable_map: `%s`.`%s` mapped to number %llu\n",
11225 m_dbnam.c_str(), m_tblnam.c_str(), m_table_id.id());
11226
11227 if (print_event_info->print_table_metadata) {
11228 Optional_metadata_fields fields(m_optional_metadata,
11229 m_optional_metadata_len);
11230
11231 if (m_optional_metadata) DBUG_ASSERT(fields.is_valid);
11232 print_columns(&print_event_info->head_cache, fields);
11233 print_primary_key(&print_event_info->head_cache, fields);
11234 }
11235
11236 print_base64(&print_event_info->body_cache, print_event_info, true);
11237 }
11238 }
11239
11240 /**
11241 return the string name of a type.
11242
11243 @param[in] type type of a column
11244 @param[in,out] meta_ptr the meta_ptr of the column. If the type doesn't have
11245 metadata, it will not change meta_ptr, otherwise
11246 meta_ptr will be moved to the end of the column's
11247 metadat.
11248 @param[in] cs charset of the column if it is a character column.
11249 @param[out] typestr buffer to storing the string name of the type
11250 @param[in] typestr_length length of typestr
11251 @param[in] geometry_type internal geometry_type
11252 */
get_type_name(uint type,unsigned char ** meta_ptr,const CHARSET_INFO * cs,char * typestr,uint typestr_length,unsigned int geometry_type)11253 static void get_type_name(uint type, unsigned char **meta_ptr,
11254 const CHARSET_INFO *cs, char *typestr,
11255 uint typestr_length, unsigned int geometry_type) {
11256 switch (type) {
11257 case MYSQL_TYPE_LONG:
11258 snprintf(typestr, typestr_length, "%s", "INT");
11259 break;
11260 case MYSQL_TYPE_TINY:
11261 snprintf(typestr, typestr_length, "TINYINT");
11262 break;
11263 case MYSQL_TYPE_SHORT:
11264 snprintf(typestr, typestr_length, "SMALLINT");
11265 break;
11266 case MYSQL_TYPE_INT24:
11267 snprintf(typestr, typestr_length, "MEDIUMINT");
11268 break;
11269 case MYSQL_TYPE_LONGLONG:
11270 snprintf(typestr, typestr_length, "BIGINT");
11271 break;
11272 case MYSQL_TYPE_NEWDECIMAL:
11273 snprintf(typestr, typestr_length, "DECIMAL(%d,%d)", (*meta_ptr)[0],
11274 (*meta_ptr)[1]);
11275 (*meta_ptr) += 2;
11276 break;
11277 case MYSQL_TYPE_FLOAT:
11278 snprintf(typestr, typestr_length, "FLOAT");
11279 (*meta_ptr)++;
11280 break;
11281 case MYSQL_TYPE_DOUBLE:
11282 snprintf(typestr, typestr_length, "DOUBLE");
11283 (*meta_ptr)++;
11284 break;
11285 case MYSQL_TYPE_BIT:
11286 snprintf(typestr, typestr_length, "BIT(%d)",
11287 (((*meta_ptr)[0])) + (*meta_ptr)[1] * 8);
11288 (*meta_ptr) += 2;
11289 break;
11290 case MYSQL_TYPE_TIMESTAMP2:
11291 if (**meta_ptr != 0)
11292 snprintf(typestr, typestr_length, "TIMESTAMP(%d)", **meta_ptr);
11293 else
11294 snprintf(typestr, typestr_length, "TIMESTAMP");
11295 (*meta_ptr)++;
11296 break;
11297 case MYSQL_TYPE_DATETIME2:
11298 if (**meta_ptr != 0)
11299 snprintf(typestr, typestr_length, "DATETIME(%d)", **meta_ptr);
11300 else
11301 snprintf(typestr, typestr_length, "DATETIME");
11302 (*meta_ptr)++;
11303 break;
11304 case MYSQL_TYPE_TIME2:
11305 if (**meta_ptr != 0)
11306 snprintf(typestr, typestr_length, "TIME(%d)", **meta_ptr);
11307 else
11308 snprintf(typestr, typestr_length, "TIME");
11309 (*meta_ptr)++;
11310 break;
11311 case MYSQL_TYPE_NEWDATE:
11312 case MYSQL_TYPE_DATE:
11313 snprintf(typestr, typestr_length, "DATE");
11314 break;
11315 case MYSQL_TYPE_YEAR:
11316 snprintf(typestr, typestr_length, "YEAR");
11317 break;
11318 case MYSQL_TYPE_ENUM:
11319 snprintf(typestr, typestr_length, "ENUM");
11320 (*meta_ptr) += 2;
11321 break;
11322 case MYSQL_TYPE_SET:
11323 snprintf(typestr, typestr_length, "SET");
11324 (*meta_ptr) += 2;
11325 break;
11326 case MYSQL_TYPE_BLOB: {
11327 bool is_text = (cs && cs->number != my_charset_bin.number);
11328 const char *names[5][2] = {{"INVALID_BLOB(%d)", "INVALID_TEXT(%d)"},
11329 {"TINYBLOB", "TINYTEXT"},
11330 {"BLOB", "TEXT"},
11331 {"MEDIUMBLOB", "MEDIUMTEXT"},
11332 {"LONGBLOB", "LONGTEXT"}};
11333 unsigned char size = **meta_ptr;
11334
11335 if (size == 0 || size > 4)
11336 snprintf(typestr, typestr_length, names[0][is_text], size);
11337 else
11338 snprintf(typestr, typestr_length, "%s", names[**meta_ptr][is_text]);
11339
11340 (*meta_ptr)++;
11341 } break;
11342 case MYSQL_TYPE_VARCHAR:
11343 case MYSQL_TYPE_VAR_STRING:
11344 if (cs && cs->number != my_charset_bin.number)
11345 snprintf(typestr, typestr_length, "VARCHAR(%d)",
11346 uint2korr(*meta_ptr) / cs->mbmaxlen);
11347 else
11348 snprintf(typestr, typestr_length, "VARBINARY(%d)",
11349 uint2korr(*meta_ptr));
11350
11351 (*meta_ptr) += 2;
11352 break;
11353 case MYSQL_TYPE_STRING: {
11354 uint byte0 = (*meta_ptr)[0];
11355 uint byte1 = (*meta_ptr)[1];
11356 uint len = (((byte0 & 0x30) ^ 0x30) << 4) | byte1;
11357
11358 if (cs && cs->number != my_charset_bin.number)
11359 snprintf(typestr, typestr_length, "CHAR(%d)", len / cs->mbmaxlen);
11360 else
11361 snprintf(typestr, typestr_length, "BINARY(%d)", len);
11362
11363 (*meta_ptr) += 2;
11364 } break;
11365 case MYSQL_TYPE_JSON:
11366 snprintf(typestr, typestr_length, "JSON");
11367 (*meta_ptr)++;
11368 break;
11369 case MYSQL_TYPE_GEOMETRY: {
11370 const char *names[8] = {
11371 "GEOMETRY", "POINT", "LINESTRING", "POLYGON",
11372 "MULTIPOINT", "MULTILINESTRING", "MULTIPOLYGON", "GEOMCOLLECTION"};
11373 if (geometry_type < 8)
11374 snprintf(typestr, typestr_length, "%s", names[geometry_type]);
11375 else
11376 snprintf(typestr, typestr_length, "INVALID_GEOMETRY_TYPE(%u)",
11377 geometry_type);
11378 (*meta_ptr)++;
11379 } break;
11380 default:
11381 *typestr = 0;
11382 break;
11383 }
11384 }
11385
11386 /**
11387 Interface for iterator over charset columns.
11388 */
11389 class Table_map_log_event::Charset_iterator {
11390 public:
11391 typedef Table_map_event::Optional_metadata_fields::Default_charset
11392 Default_charset;
11393 virtual const CHARSET_INFO *next() = 0;
11394 virtual ~Charset_iterator() = default;
11395
11396 /**
11397 Factory method to create an instance of the appropriate subclass.
11398 */
11399 static std::unique_ptr<Charset_iterator> create_charset_iterator(
11400 const Default_charset &default_charset,
11401 const std::vector<uint> &column_charset);
11402 };
11403
11404 /**
11405 Implementation of charset iterator for the DEFAULT_CHARSET type.
11406 */
11407 class Table_map_log_event::Default_charset_iterator : public Charset_iterator {
11408 public:
Default_charset_iterator(const Default_charset & default_charset)11409 Default_charset_iterator(const Default_charset &default_charset)
11410 : m_iterator(default_charset.charset_pairs.begin()),
11411 m_end(default_charset.charset_pairs.end()),
11412 m_column_index(0),
11413 m_default_charset_info(
11414 get_charset(default_charset.default_charset, 0)) {}
11415
next()11416 const CHARSET_INFO *next() override {
11417 const CHARSET_INFO *ret;
11418 if (m_iterator != m_end && m_iterator->first == m_column_index) {
11419 ret = get_charset(m_iterator->second, 0);
11420 m_iterator++;
11421 } else
11422 ret = m_default_charset_info;
11423 m_column_index++;
11424 return ret;
11425 }
11426
11427 private:
11428 std::vector<Optional_metadata_fields::uint_pair>::const_iterator m_iterator,
11429 m_end;
11430 uint m_column_index;
11431 const CHARSET_INFO *m_default_charset_info;
11432 };
11433
11434 /**
11435 Implementation of charset iterator for the COLUMNT_CHARSET type.
11436 */
11437 class Table_map_log_event::Column_charset_iterator : public Charset_iterator {
11438 public:
Column_charset_iterator(const std::vector<uint> & column_charset)11439 Column_charset_iterator(const std::vector<uint> &column_charset)
11440 : m_iterator(column_charset.begin()), m_end(column_charset.end()) {}
11441
next()11442 const CHARSET_INFO *next() override {
11443 const CHARSET_INFO *ret = nullptr;
11444 if (m_iterator != m_end) {
11445 ret = get_charset(*m_iterator, 0);
11446 m_iterator++;
11447 }
11448 return ret;
11449 }
11450
11451 private:
11452 std::vector<uint>::const_iterator m_iterator;
11453 std::vector<uint>::const_iterator m_end;
11454 };
11455
11456 std::unique_ptr<Table_map_log_event::Charset_iterator>
create_charset_iterator(const Default_charset & default_charset,const std::vector<uint> & column_charset)11457 Table_map_log_event::Charset_iterator::create_charset_iterator(
11458 const Default_charset &default_charset,
11459 const std::vector<uint> &column_charset) {
11460 if (!default_charset.empty())
11461 return std::unique_ptr<Charset_iterator>(
11462 new Default_charset_iterator(default_charset));
11463 else
11464 return std::unique_ptr<Charset_iterator>(
11465 new Column_charset_iterator(column_charset));
11466 }
11467
print_columns(IO_CACHE * file,const Optional_metadata_fields & fields) const11468 void Table_map_log_event::print_columns(
11469 IO_CACHE *file, const Optional_metadata_fields &fields) const {
11470 unsigned char *field_metadata_ptr = m_field_metadata;
11471 std::vector<bool>::const_iterator signedness_it = fields.m_signedness.begin();
11472
11473 std::unique_ptr<Charset_iterator> charset_it =
11474 Charset_iterator::create_charset_iterator(fields.m_default_charset,
11475 fields.m_column_charset);
11476 std::unique_ptr<Charset_iterator> enum_and_set_charset_it =
11477 Charset_iterator::create_charset_iterator(
11478 fields.m_enum_and_set_default_charset,
11479 fields.m_enum_and_set_column_charset);
11480 std::vector<std::string>::const_iterator col_names_it =
11481 fields.m_column_name.begin();
11482 std::vector<Optional_metadata_fields::str_vector>::const_iterator
11483 set_str_values_it = fields.m_set_str_value.begin();
11484 std::vector<Optional_metadata_fields::str_vector>::const_iterator
11485 enum_str_values_it = fields.m_enum_str_value.begin();
11486 std::vector<unsigned int>::const_iterator geometry_type_it =
11487 fields.m_geometry_type.begin();
11488 uint geometry_type = 0;
11489
11490 my_b_printf(file, "# Columns(");
11491
11492 for (unsigned long i = 0; i < m_colcnt; i++) {
11493 uint real_type = m_coltype[i];
11494 if (real_type == MYSQL_TYPE_STRING &&
11495 (*field_metadata_ptr == MYSQL_TYPE_ENUM ||
11496 *field_metadata_ptr == MYSQL_TYPE_SET))
11497 real_type = *field_metadata_ptr;
11498
11499 // Get current column's collation id if it is a character, enum,
11500 // or set column
11501 const CHARSET_INFO *cs = nullptr;
11502 if (is_character_type(real_type))
11503 cs = charset_it->next();
11504 else if (is_enum_or_set_type(real_type))
11505 cs = enum_and_set_charset_it->next();
11506
11507 // Print column name
11508 if (col_names_it != fields.m_column_name.end()) {
11509 pretty_print_identifier(file, col_names_it->c_str(),
11510 col_names_it->size());
11511 my_b_printf(file, " ");
11512 col_names_it++;
11513 }
11514
11515 // update geometry_type for geometry columns
11516 if (real_type == MYSQL_TYPE_GEOMETRY) {
11517 geometry_type = (geometry_type_it != fields.m_geometry_type.end())
11518 ? *geometry_type_it++
11519 : 0;
11520 }
11521
11522 // print column type
11523 const uint TYPE_NAME_LEN = 100;
11524 char type_name[TYPE_NAME_LEN];
11525 get_type_name(real_type, &field_metadata_ptr, cs, type_name, TYPE_NAME_LEN,
11526 geometry_type);
11527
11528 if (type_name[0] == '\0') {
11529 my_b_printf(file, "INVALID_TYPE(%d)", real_type);
11530 continue;
11531 }
11532 my_b_printf(file, "%s", type_name);
11533
11534 // Print UNSIGNED for numeric column
11535 if (is_numeric_type(real_type) &&
11536 signedness_it != fields.m_signedness.end()) {
11537 if (*signedness_it == true) my_b_printf(file, " UNSIGNED");
11538 signedness_it++;
11539 }
11540
11541 // if the column is not marked as 'null', print 'not null'
11542 if (!(m_null_bits[(i / 8)] & (1 << (i % 8))))
11543 my_b_printf(file, " NOT NULL");
11544
11545 // Print string values of SET and ENUM column
11546 const Optional_metadata_fields::str_vector *str_values = nullptr;
11547 if (real_type == MYSQL_TYPE_ENUM &&
11548 enum_str_values_it != fields.m_enum_str_value.end()) {
11549 str_values = &(*enum_str_values_it);
11550 enum_str_values_it++;
11551 } else if (real_type == MYSQL_TYPE_SET &&
11552 set_str_values_it != fields.m_set_str_value.end()) {
11553 str_values = &(*set_str_values_it);
11554 set_str_values_it++;
11555 }
11556
11557 if (str_values != nullptr) {
11558 const char *separator = "(";
11559 for (Optional_metadata_fields::str_vector::const_iterator it =
11560 str_values->begin();
11561 it != str_values->end(); it++) {
11562 my_b_printf(file, "%s", separator);
11563 pretty_print_str(file, it->c_str(), it->size());
11564 separator = ", ";
11565 }
11566 my_b_printf(file, ")");
11567 }
11568
11569 // Print column character set, except in text columns with binary collation
11570 if (cs != nullptr &&
11571 (is_enum_or_set_type(real_type) || cs->number != my_charset_bin.number))
11572 my_b_printf(file, " CHARSET %s COLLATE %s", cs->csname, cs->name);
11573
11574 if (i != m_colcnt - 1) my_b_printf(file, ",\n# ");
11575 }
11576 my_b_printf(file, ")");
11577 my_b_printf(file, "\n");
11578 }
11579
print_primary_key(IO_CACHE * file,const Optional_metadata_fields & fields) const11580 void Table_map_log_event::print_primary_key(
11581 IO_CACHE *file, const Optional_metadata_fields &fields) const {
11582 if (!fields.m_primary_key.empty()) {
11583 my_b_printf(file, "# Primary Key(");
11584
11585 std::vector<Optional_metadata_fields::uint_pair>::const_iterator it =
11586 fields.m_primary_key.begin();
11587
11588 for (; it != fields.m_primary_key.end(); it++) {
11589 if (it != fields.m_primary_key.begin()) my_b_printf(file, ", ");
11590
11591 // Print column name or column index
11592 if (it->first >= fields.m_column_name.size())
11593 my_b_printf(file, "%u", it->first);
11594 else
11595 my_b_printf(file, "%s", fields.m_column_name[it->first].c_str());
11596
11597 // Print prefix length
11598 if (it->second != 0) my_b_printf(file, "(%u)", it->second);
11599 }
11600
11601 my_b_printf(file, ")\n");
11602 }
11603 }
11604 #endif
11605
11606 /**************************************************************************
11607 Write_rows_log_event member functions
11608 **************************************************************************/
11609
11610 /*
11611 Constructor used to build an event for writing to the binary log.
11612 */
11613 #if defined(MYSQL_SERVER)
Write_rows_log_event(THD * thd_arg,TABLE * tbl_arg,const Table_id & tid_arg,bool is_transactional,const unsigned char * extra_row_ndb_info)11614 Write_rows_log_event::Write_rows_log_event(
11615 THD *thd_arg, TABLE *tbl_arg, const Table_id &tid_arg,
11616 bool is_transactional, const unsigned char *extra_row_ndb_info)
11617 : binary_log::Rows_event(log_bin_use_v1_row_events
11618 ? binary_log::WRITE_ROWS_EVENT_V1
11619 : binary_log::WRITE_ROWS_EVENT),
11620 Rows_log_event(thd_arg, tbl_arg, tid_arg, tbl_arg->write_set,
11621 is_transactional,
11622 log_bin_use_v1_row_events ? binary_log::WRITE_ROWS_EVENT_V1
11623 : binary_log::WRITE_ROWS_EVENT,
11624 extra_row_ndb_info) {
11625 common_header->type_code = m_type;
11626 }
11627
binlog_row_logging_function(THD * thd_arg,TABLE * table,bool is_transactional,const uchar * before_record MY_ATTRIBUTE ((unused)),const uchar * after_record)11628 bool Write_rows_log_event::binlog_row_logging_function(
11629 THD *thd_arg, TABLE *table, bool is_transactional,
11630 const uchar *before_record MY_ATTRIBUTE((unused)),
11631 const uchar *after_record) {
11632 return thd_arg->binlog_write_row(table, is_transactional, after_record,
11633 nullptr);
11634 }
11635 #endif
11636
11637 /*
11638 Constructor used by slave to read the event from the binary log.
11639 */
Write_rows_log_event(const char * buf,const Format_description_event * description_event)11640 Write_rows_log_event::Write_rows_log_event(
11641 const char *buf, const Format_description_event *description_event)
11642 : binary_log::Rows_event(buf, description_event),
11643 Rows_log_event(buf, description_event),
11644 binary_log::Write_rows_event(buf, description_event) {
11645 DBUG_ASSERT(header()->type_code == m_type);
11646 }
11647
11648 #if defined(MYSQL_SERVER)
do_before_row_operations(const Slave_reporting_capability * const)11649 int Write_rows_log_event::do_before_row_operations(
11650 const Slave_reporting_capability *const) {
11651 int error = 0;
11652
11653 /*
11654 Increment the global status insert count variable
11655 */
11656 if (get_flags(STMT_END_F)) thd->status_var.com_stat[SQLCOM_INSERT]++;
11657
11658 /*
11659 Let storage engines treat this event as an INSERT command.
11660
11661 Set 'sql_command' as SQLCOM_INSERT after the tables are locked.
11662 When locking the tables, it should be SQLCOM_END.
11663 THD::decide_logging_format which is called from "lock tables"
11664 assumes that row_events will have 'sql_command' as SQLCOM_END.
11665 */
11666 thd->lex->sql_command = SQLCOM_INSERT;
11667
11668 DBUG_EXECUTE_IF(
11669 "crash_on_transactional_ddl_insert",
11670 if (thd->m_transactional_ddl.inited()) { DBUG_SUICIDE(); });
11671
11672 /**
11673 todo: to introduce a property for the event (handler?) which forces
11674 applying the event in the replace (idempotent) fashion.
11675 */
11676 if ((rbr_exec_mode == RBR_EXEC_MODE_IDEMPOTENT) ||
11677 (m_table->s->db_type()->db_type == DB_TYPE_NDBCLUSTER)) {
11678 /*
11679 We are using REPLACE semantics and not INSERT IGNORE semantics
11680 when writing rows, that is: new rows replace old rows. We need to
11681 inform the storage engine that it should use this behaviour.
11682 */
11683
11684 /* Tell the storage engine that we are using REPLACE semantics. */
11685 thd->lex->duplicates = DUP_REPLACE;
11686
11687 /*
11688 Pretend we're executing a REPLACE command: this is needed for
11689 InnoDB and NDB Cluster since they are not (properly) checking the
11690 lex->duplicates flag.
11691 */
11692 thd->lex->sql_command = SQLCOM_REPLACE;
11693 /*
11694 Do not raise the error flag in case of hitting to an unique attribute
11695 */
11696 m_table->file->ha_extra(HA_EXTRA_IGNORE_DUP_KEY);
11697 /*
11698 NDB specific: update from ndb master wrapped as Write_rows
11699 so that the event should be applied to replace slave's row
11700 */
11701 m_table->file->ha_extra(HA_EXTRA_WRITE_CAN_REPLACE);
11702 /*
11703 NDB specific: if update from ndb master wrapped as Write_rows
11704 does not find the row it's assumed idempotent binlog applying
11705 is taking place; don't raise the error.
11706 */
11707 m_table->file->ha_extra(HA_EXTRA_IGNORE_NO_KEY);
11708 /*
11709 TODO: the cluster team (Tomas?) says that it's better if the engine knows
11710 how many rows are going to be inserted, then it can allocate needed memory
11711 from the start.
11712 */
11713 }
11714
11715 /* Honor next number column if present */
11716 m_table->next_number_field = m_table->found_next_number_field;
11717 /*
11718 * Fixed Bug#45999, In RBR, Store engine of Slave auto-generates new
11719 * sequence numbers for auto_increment fields if the values of them are 0.
11720 * If generateing a sequence number is decided by the values of
11721 * table->autoinc_field_has_explicit_non_null_value and SQL_MODE(if
11722 * includes MODE_NO_AUTO_VALUE_ON_ZERO) in update_auto_increment function.
11723 * SQL_MODE of slave sql thread is always consistency with master's.
11724 * In RBR, auto_increment fields never are NULL, except if the auto_inc
11725 * column exists only on the slave side (i.e., in an extra column
11726 * on the slave's table).
11727 */
11728 if (!is_auto_inc_in_extra_columns())
11729 m_table->autoinc_field_has_explicit_non_null_value = true;
11730 else {
11731 /*
11732 Here we have checked that there is an extra field
11733 on this server's table that has an auto_inc column.
11734
11735 Mark that the auto_increment field is null and mark
11736 the read and write set bits.
11737
11738 (There can only be one AUTO_INC column, it is always
11739 indexed and it cannot have a DEFAULT value).
11740 */
11741 m_table->autoinc_field_has_explicit_non_null_value = false;
11742 m_table->mark_auto_increment_column();
11743 }
11744
11745 /**
11746 Sets it to ROW_LOOKUP_NOT_NEEDED.
11747 */
11748 decide_row_lookup_algorithm_and_key();
11749 DBUG_ASSERT(m_rows_lookup_algorithm == ROW_LOOKUP_NOT_NEEDED);
11750
11751 return error;
11752 }
11753
do_after_row_operations(const Slave_reporting_capability * const,int error)11754 int Write_rows_log_event::do_after_row_operations(
11755 const Slave_reporting_capability *const, int error) {
11756 int local_error = 0;
11757
11758 /**
11759 Clear the write_set bit for auto_inc field that only
11760 existed on the destination table as an extra column.
11761 */
11762 if (is_auto_inc_in_extra_columns()) {
11763 bitmap_clear_bit(m_table->write_set,
11764 m_table->next_number_field->field_index());
11765 bitmap_clear_bit(m_table->read_set,
11766 m_table->next_number_field->field_index());
11767
11768 if (get_flags(STMT_END_F)) m_table->file->ha_release_auto_increment();
11769 }
11770 m_table->next_number_field = nullptr;
11771 m_table->autoinc_field_has_explicit_non_null_value = false;
11772 if ((local_error = m_table->file->ha_end_bulk_insert())) {
11773 m_table->file->print_error(local_error, MYF(0));
11774 }
11775
11776 m_rows_lookup_algorithm = ROW_LOOKUP_UNDEFINED;
11777
11778 return error ? error : local_error;
11779 }
11780
11781 /*
11782 Check if there are more UNIQUE keys after the given key.
11783 */
last_uniq_key(TABLE * table,uint keyno)11784 static int last_uniq_key(TABLE *table, uint keyno) {
11785 while (++keyno < table->s->keys)
11786 if (table->key_info[keyno].flags & HA_NOSAME) return 0;
11787 return 1;
11788 }
11789
11790 /**
11791 Write the current row into event's table.
11792
11793 The row is located in the row buffer, pointed by @c m_curr_row member.
11794 Number of columns of the row is stored in @c m_width member (it can be
11795 different from the number of columns in the table to which we insert).
11796 Bitmap @c m_cols indicates which columns are present in the row. It is assumed
11797 that event's table is already open and pointed by @c m_table.
11798
11799 If the same record already exists in the table it can be either overwritten
11800 or an error is reported depending on the value of @c overwrite flag
11801 (error reporting not yet implemented). Note that the matching record can be
11802 different from the row we insert if we use primary keys to identify records in
11803 the table.
11804
11805 The row to be inserted can contain values only for selected columns. The
11806 missing columns are filled with default values using @c prepare_record()
11807 function. If a matching record is found in the table and @c overwritte is
11808 true, the missing columns are taken from it.
11809
11810 @param rli Relay log info (needed for row unpacking).
11811 @param overwrite
11812 Shall we overwrite if the row already exists or signal
11813 error (currently ignored).
11814
11815 @returns Error code on failure, 0 on success.
11816
11817 This method, if successful, sets @c m_curr_row_end pointer to point at the
11818 next row in the rows buffer. This is done when unpacking the row to be
11819 inserted.
11820
11821 @note If a matching record is found, it is either updated using
11822 @c ha_update_row() or first deleted and then new record written.
11823 */
11824
write_row(const Relay_log_info * const rli,const bool overwrite)11825 int Write_rows_log_event::write_row(const Relay_log_info *const rli,
11826 const bool overwrite) {
11827 DBUG_TRACE;
11828 DBUG_ASSERT(m_table != nullptr && thd != nullptr);
11829
11830 TABLE *table = m_table; // pointer to event's table
11831 int error;
11832 int keynum = 0;
11833 char *key = nullptr;
11834
11835 prepare_record(table, &this->m_local_cols,
11836 table->file->ht->db_type != DB_TYPE_NDBCLUSTER);
11837
11838 /* unpack row into table->record[0] */
11839 if ((error = unpack_current_row(rli, &m_cols, true /*is AI*/))) return error;
11840
11841 /*
11842 When m_curr_row == m_curr_row_end, it means a row that contains nothing,
11843 so all the pointers shall be pointing to the same address, or else
11844 we have corrupt data and shall throw the error.
11845 */
11846 DBUG_PRINT("debug", ("m_rows_buf= %p, m_rows_cur= %p, m_rows_end= %p",
11847 m_rows_buf, m_rows_cur, m_rows_end));
11848 DBUG_PRINT("debug", ("m_curr_row= %p, m_curr_row_end= %p", m_curr_row,
11849 m_curr_row_end));
11850 if (m_curr_row == m_curr_row_end &&
11851 !((m_rows_buf == m_rows_cur) && (m_rows_cur == m_rows_end))) {
11852 my_error(ER_SLAVE_CORRUPT_EVENT, MYF(0));
11853 return ER_SLAVE_CORRUPT_EVENT;
11854 }
11855
11856 // Invoke check constraints on the unpacked row.
11857 if (invoke_table_check_constraints(thd, table))
11858 return ER_CHECK_CONSTRAINT_VIOLATED;
11859
11860 if (m_curr_row == m_rows_buf) {
11861 /* this is the first row to be inserted, we estimate the rows with
11862 the size of the first row and use that value to initialize
11863 storage engine for bulk insertion */
11864 DBUG_ASSERT(!(m_curr_row > m_curr_row_end));
11865 ulong estimated_rows = 0;
11866 if (m_curr_row < m_curr_row_end)
11867 estimated_rows =
11868 (m_rows_end - m_curr_row) / (m_curr_row_end - m_curr_row);
11869 else if (m_curr_row == m_curr_row_end)
11870 estimated_rows = 1;
11871
11872 m_table->file->ha_start_bulk_insert(estimated_rows);
11873 }
11874
11875 /*
11876 Explicitly set the auto_inc to null to make sure that
11877 it gets an auto_generated value.
11878 */
11879 if (is_auto_inc_in_extra_columns()) m_table->next_number_field->set_null();
11880
11881 #ifndef DBUG_OFF
11882 DBUG_DUMP("record[0]", table->record[0], table->s->reclength);
11883 DBUG_PRINT_BITSET("debug", "write_set = %s", table->write_set);
11884 DBUG_PRINT_BITSET("debug", "read_set = %s", table->read_set);
11885 #endif
11886
11887 /*
11888 Try to write record. If a corresponding record already exists in the table,
11889 we try to change it using ha_update_row() if possible. Otherwise we delete
11890 it and repeat the whole process again.
11891
11892 TODO: Add safety measures against infinite looping.
11893 */
11894
11895 m_table->mark_columns_per_binlog_row_image(thd);
11896
11897 while ((error = table->file->ha_write_row(table->record[0]))) {
11898 if (error == HA_ERR_LOCK_DEADLOCK || error == HA_ERR_LOCK_WAIT_TIMEOUT ||
11899 (keynum = table->file->get_dup_key(error)) < 0 || !overwrite) {
11900 DBUG_PRINT("info", ("get_dup_key returns %d)", keynum));
11901 /*
11902 Deadlock, waiting for lock or just an error from the handler
11903 such as HA_ERR_FOUND_DUPP_KEY when overwrite is false.
11904 Retrieval of the duplicate key number may fail
11905 - either because the error was not "duplicate key" error
11906 - or because the information which key is not available
11907 */
11908 table->file->print_error(error, MYF(0));
11909 goto error;
11910 }
11911 /*
11912 key index value is either valid in the range [0-MAX_KEY) or
11913 has value MAX_KEY as a marker for the case when no information
11914 about key can be found. In the last case we have to require
11915 that storage engine has the flag HA_DUPLICATE_POS turned on.
11916 If this invariant is false then DBUG_ASSERT will crash
11917 the server built in debug mode. For the server that was built
11918 without DEBUG we have additional check for the value of key index
11919 in the code below in order to report about error in any case.
11920 */
11921 DBUG_ASSERT(keynum != MAX_KEY ||
11922 (keynum == MAX_KEY &&
11923 (table->file->ha_table_flags() & HA_DUPLICATE_POS)));
11924 /*
11925 We need to retrieve the old row into record[1] to be able to
11926 either update or delete the offending record. We either:
11927
11928 - use ha_rnd_pos() with a row-id (available as dupp_row) to the
11929 offending row, if that is possible (MyISAM and Blackhole), or else
11930
11931 - use ha_index_read_idx_map() with the key that is duplicated, to
11932 retrieve the offending row.
11933 */
11934 if (table->file->ha_table_flags() & HA_DUPLICATE_POS) {
11935 DBUG_PRINT("info", ("Locating offending record using ha_rnd_pos()"));
11936
11937 if (table->file->inited && (error = table->file->ha_index_end())) {
11938 table->file->print_error(error, MYF(0));
11939 goto error;
11940 }
11941 if ((error = table->file->ha_rnd_init(false))) {
11942 table->file->print_error(error, MYF(0));
11943 goto error;
11944 }
11945
11946 error = table->file->ha_rnd_pos(table->record[1], table->file->dup_ref);
11947
11948 table->file->ha_rnd_end();
11949 if (error) {
11950 DBUG_PRINT("info", ("ha_rnd_pos() returns error %d", error));
11951 if (error == HA_ERR_RECORD_DELETED) error = HA_ERR_KEY_NOT_FOUND;
11952 table->file->print_error(error, MYF(0));
11953 goto error;
11954 }
11955 } else {
11956 DBUG_PRINT("info", ("Locating offending record using index_read_idx()"));
11957
11958 if (key == nullptr) {
11959 key = static_cast<char *>(my_alloca(table->s->max_unique_length));
11960 if (key == nullptr) {
11961 DBUG_PRINT("info", ("Can't allocate key buffer"));
11962 error = ENOMEM;
11963 goto error;
11964 }
11965 }
11966
11967 if ((uint)keynum < MAX_KEY) {
11968 key_copy((uchar *)key, table->record[0], table->key_info + keynum, 0);
11969 error = table->file->ha_index_read_idx_map(
11970 table->record[1], keynum, (const uchar *)key, HA_WHOLE_KEY,
11971 HA_READ_KEY_EXACT);
11972 } else
11973 /*
11974 For the server built in non-debug mode returns error if
11975 handler::get_dup_key() returned MAX_KEY as the value of key index.
11976 */
11977 error = HA_ERR_FOUND_DUPP_KEY;
11978
11979 if (error) {
11980 DBUG_PRINT("info",
11981 ("ha_index_read_idx_map() returns %s", HA_ERR(error)));
11982 if (error == HA_ERR_RECORD_DELETED) error = HA_ERR_KEY_NOT_FOUND;
11983 table->file->print_error(error, MYF(0));
11984 goto error;
11985 }
11986 }
11987
11988 /*
11989 Now, record[1] should contain the offending row. That
11990 will enable us to update it or, alternatively, delete it (so
11991 that we can insert the new row afterwards).
11992 */
11993
11994 /*
11995 If row is incomplete we will use the record found to fill
11996 missing columns.
11997 */
11998 if (!get_flags(COMPLETE_ROWS_F)) {
11999 restore_record(table, record[1]);
12000 error = unpack_current_row(rli, &m_cols, true /*is AI*/);
12001 }
12002
12003 #ifndef DBUG_OFF
12004 DBUG_PRINT("debug", ("preparing for update: before and after image"));
12005 DBUG_DUMP("record[1] (before)", table->record[1], table->s->reclength);
12006 DBUG_DUMP("record[0] (after)", table->record[0], table->s->reclength);
12007 #endif
12008
12009 /*
12010 REPLACE is defined as either INSERT or DELETE + INSERT. If
12011 possible, we can replace it with an UPDATE, but that will not
12012 work on InnoDB if FOREIGN KEY checks are necessary.
12013
12014 I (Matz) am not sure of the reason for the last_uniq_key()
12015 check as, but I'm guessing that it's something along the
12016 following lines.
12017
12018 Suppose that we got the duplicate key to be a key that is not
12019 the last unique key for the table and we perform an update:
12020 then there might be another key for which the unique check will
12021 fail, so we're better off just deleting the row and inserting
12022 the correct row.
12023 */
12024 if (last_uniq_key(table, keynum) &&
12025 !table->s->is_referenced_by_foreign_key()) {
12026 DBUG_PRINT("info", ("Updating row using ha_update_row()"));
12027 error = table->file->ha_update_row(table->record[1], table->record[0]);
12028 switch (error) {
12029 case HA_ERR_RECORD_IS_THE_SAME:
12030 DBUG_PRINT("info", ("ignoring HA_ERR_RECORD_IS_THE_SAME error from"
12031 " ha_update_row()"));
12032 error = 0;
12033
12034 case 0:
12035 break;
12036
12037 default:
12038 DBUG_PRINT("info", ("ha_update_row() returns error %d", error));
12039 table->file->print_error(error, MYF(0));
12040 }
12041
12042 goto error;
12043 } else {
12044 DBUG_PRINT("info",
12045 ("Deleting offending row and trying to write new one again"));
12046 if ((error = table->file->ha_delete_row(table->record[1]))) {
12047 DBUG_PRINT("info", ("ha_delete_row() returns error %d", error));
12048 table->file->print_error(error, MYF(0));
12049 goto error;
12050 }
12051 /* Will retry ha_write_row() with the offending row removed. */
12052 }
12053 }
12054
12055 error:
12056 m_table->default_column_bitmaps();
12057 return error;
12058 }
12059
do_exec_row(const Relay_log_info * const rli)12060 int Write_rows_log_event::do_exec_row(const Relay_log_info *const rli) {
12061 DBUG_ASSERT(m_table != nullptr);
12062 int error = write_row(rli, rbr_exec_mode == RBR_EXEC_MODE_IDEMPOTENT);
12063
12064 if (error && !thd->is_error()) {
12065 DBUG_ASSERT(0);
12066 my_error(ER_UNKNOWN_ERROR, MYF(0));
12067 }
12068
12069 return error;
12070 }
12071
12072 #endif /* defined(MYSQL_SERVER) */
12073
12074 #ifndef MYSQL_SERVER
print(FILE * file,PRINT_EVENT_INFO * print_event_info) const12075 void Write_rows_log_event::print(FILE *file,
12076 PRINT_EVENT_INFO *print_event_info) const {
12077 DBUG_EXECUTE_IF("simulate_cache_read_error",
12078 { DBUG_SET("+d,simulate_my_b_fill_error"); });
12079 Rows_log_event::print_helper(file, print_event_info);
12080 }
12081 #endif
12082
12083 /**************************************************************************
12084 Delete_rows_log_event member functions
12085 **************************************************************************/
12086
12087 /*
12088 Constructor used to build an event for writing to the binary log.
12089 */
12090
12091 #ifdef MYSQL_SERVER
Delete_rows_log_event(THD * thd_arg,TABLE * tbl_arg,const Table_id & tid,bool is_transactional,const uchar * extra_row_ndb_info)12092 Delete_rows_log_event::Delete_rows_log_event(THD *thd_arg, TABLE *tbl_arg,
12093 const Table_id &tid,
12094 bool is_transactional,
12095 const uchar *extra_row_ndb_info)
12096 : binary_log::Rows_event(log_bin_use_v1_row_events
12097 ? binary_log::DELETE_ROWS_EVENT_V1
12098 : binary_log::DELETE_ROWS_EVENT),
12099 Rows_log_event(thd_arg, tbl_arg, tid, tbl_arg->read_set, is_transactional,
12100 log_bin_use_v1_row_events
12101 ? binary_log::DELETE_ROWS_EVENT_V1
12102 : binary_log::DELETE_ROWS_EVENT,
12103 extra_row_ndb_info),
12104 binary_log::Delete_rows_event() {
12105 common_header->type_code = m_type;
12106 }
12107
binlog_row_logging_function(THD * thd_arg,TABLE * table,bool is_transactional,const uchar * before_record,const uchar * after_record MY_ATTRIBUTE ((unused)))12108 bool Delete_rows_log_event::binlog_row_logging_function(
12109 THD *thd_arg, TABLE *table, bool is_transactional,
12110 const uchar *before_record,
12111 const uchar *after_record MY_ATTRIBUTE((unused))) {
12112 return thd_arg->binlog_delete_row(table, is_transactional, before_record,
12113 nullptr);
12114 }
12115
12116 #endif /* #if defined(MYSQL_SERVER) */
12117
12118 /*
12119 Constructor used by slave to read the event from the binary log.
12120 */
Delete_rows_log_event(const char * buf,const Format_description_event * description_event)12121 Delete_rows_log_event::Delete_rows_log_event(
12122 const char *buf, const Format_description_event *description_event)
12123 : binary_log::Rows_event(buf, description_event),
12124 Rows_log_event(buf, description_event),
12125 binary_log::Delete_rows_event(buf, description_event) {
12126 DBUG_ASSERT(header()->type_code == m_type);
12127 }
12128
12129 #if defined(MYSQL_SERVER)
12130
do_before_row_operations(const Slave_reporting_capability * const)12131 int Delete_rows_log_event::do_before_row_operations(
12132 const Slave_reporting_capability *const) {
12133 int error = 0;
12134 DBUG_TRACE;
12135 /*
12136 Increment the global status delete count variable
12137 */
12138 if (get_flags(STMT_END_F)) thd->status_var.com_stat[SQLCOM_DELETE]++;
12139
12140 /*
12141 Let storage engines treat this event as a DELETE command.
12142
12143 Set 'sql_command' as SQLCOM_UPDATE after the tables are locked.
12144 When locking the tables, it should be SQLCOM_END.
12145 THD::decide_logging_format which is called from "lock tables"
12146 assumes that row_events will have 'sql_command' as SQLCOM_END.
12147 */
12148 thd->lex->sql_command = SQLCOM_DELETE;
12149
12150 error = row_operations_scan_and_key_setup();
12151 return error;
12152 }
12153
do_after_row_operations(const Slave_reporting_capability * const,int error)12154 int Delete_rows_log_event::do_after_row_operations(
12155 const Slave_reporting_capability *const, int error) {
12156 DBUG_TRACE;
12157 error = row_operations_scan_and_key_teardown(error);
12158 return error;
12159 }
12160
do_exec_row(const Relay_log_info * const)12161 int Delete_rows_log_event::do_exec_row(const Relay_log_info *const) {
12162 int error;
12163 DBUG_ASSERT(m_table != nullptr);
12164 /* m_table->record[0] contains the BI */
12165 m_table->mark_columns_per_binlog_row_image(thd);
12166 error = m_table->file->ha_delete_row(m_table->record[0]);
12167 m_table->default_column_bitmaps();
12168 return error;
12169 }
12170
12171 #endif /* defined(MYSQL_SERVER) */
12172
12173 #ifndef MYSQL_SERVER
print(FILE * file,PRINT_EVENT_INFO * print_event_info) const12174 void Delete_rows_log_event::print(FILE *file,
12175 PRINT_EVENT_INFO *print_event_info) const {
12176 Rows_log_event::print_helper(file, print_event_info);
12177 }
12178 #endif
12179
12180 /**************************************************************************
12181 Update_rows_log_event member functions
12182 **************************************************************************/
12183
12184 #if defined(MYSQL_SERVER)
get_update_rows_event_type(const THD * thd_arg)12185 binary_log::Log_event_type Update_rows_log_event::get_update_rows_event_type(
12186 const THD *thd_arg) {
12187 DBUG_TRACE;
12188 binary_log::Log_event_type type =
12189 (thd_arg->variables.binlog_row_value_options != 0
12190 ? binary_log::PARTIAL_UPDATE_ROWS_EVENT
12191 : (log_bin_use_v1_row_events ? binary_log::UPDATE_ROWS_EVENT_V1
12192 : binary_log::UPDATE_ROWS_EVENT));
12193 DBUG_PRINT("info", ("update_rows event_type: %s", get_type_str(type)));
12194 return type;
12195 }
12196
12197 /*
12198 Constructor used to build an event for writing to the binary log.
12199 */
Update_rows_log_event(THD * thd_arg,TABLE * tbl_arg,const Table_id & tid,bool is_transactional,const unsigned char * extra_row_ndb_info)12200 Update_rows_log_event::Update_rows_log_event(
12201 THD *thd_arg, TABLE *tbl_arg, const Table_id &tid, bool is_transactional,
12202 const unsigned char *extra_row_ndb_info)
12203 : binary_log::Rows_event(get_update_rows_event_type(thd_arg)),
12204 Rows_log_event(thd_arg, tbl_arg, tid, tbl_arg->read_set, is_transactional,
12205 get_update_rows_event_type(thd_arg), extra_row_ndb_info),
12206 binary_log::Update_rows_event(get_update_rows_event_type(thd_arg)) {
12207 DBUG_TRACE;
12208 DBUG_PRINT("info", ("update_rows event_type: %s", get_type_str()));
12209 common_header->type_code = m_type;
12210 init(tbl_arg->write_set);
12211 common_header->set_is_valid(Rows_log_event::is_valid() && m_cols_ai.bitmap);
12212 }
12213
binlog_row_logging_function(THD * thd_arg,TABLE * table,bool is_transactional,const uchar * before_record,const uchar * after_record)12214 bool Update_rows_log_event::binlog_row_logging_function(
12215 THD *thd_arg, TABLE *table, bool is_transactional,
12216 const uchar *before_record, const uchar *after_record) {
12217 return thd_arg->binlog_update_row(table, is_transactional, before_record,
12218 after_record, nullptr);
12219 }
12220
init(MY_BITMAP const * cols)12221 void Update_rows_log_event::init(MY_BITMAP const *cols) {
12222 /* if bitmap_init fails, caught in is_valid() */
12223 if (likely(!bitmap_init(
12224 &m_cols_ai,
12225 m_width <= sizeof(m_bitbuf_ai) * 8 ? m_bitbuf_ai : nullptr,
12226 m_width))) {
12227 /* Cols can be zero if this is a dummy binrows event */
12228 if (likely(cols != nullptr)) {
12229 memcpy(m_cols_ai.bitmap, cols->bitmap, no_bytes_in_map(cols));
12230 create_last_word_mask(&m_cols_ai);
12231 }
12232 }
12233 }
12234 #endif /* defined(MYSQL_SERVER) */
12235
~Update_rows_log_event()12236 Update_rows_log_event::~Update_rows_log_event() {
12237 if (m_cols_ai.bitmap) {
12238 if (m_cols_ai.bitmap == m_bitbuf_ai) // no my_malloc happened
12239 m_cols_ai.bitmap = nullptr; // so no my_free in bitmap_free
12240 bitmap_free(&m_cols_ai); // To pair with bitmap_init().
12241 }
12242 }
12243
12244 /*
12245 Constructor used by slave to read the event from the binary log.
12246 */
Update_rows_log_event(const char * buf,const Format_description_event * description_event)12247 Update_rows_log_event::Update_rows_log_event(
12248 const char *buf, const Format_description_event *description_event)
12249 : binary_log::Rows_event(buf, description_event),
12250 Rows_log_event(buf, description_event),
12251 binary_log::Update_rows_event(buf, description_event) {
12252 DBUG_TRACE;
12253 if (!is_valid()) return;
12254 DBUG_ASSERT(header()->type_code == m_type);
12255 common_header->set_is_valid(m_cols_ai.bitmap);
12256 }
12257
12258 #if defined(MYSQL_SERVER)
12259
do_before_row_operations(const Slave_reporting_capability * const)12260 int Update_rows_log_event::do_before_row_operations(
12261 const Slave_reporting_capability *const) {
12262 int error = 0;
12263 DBUG_TRACE;
12264 /*
12265 Increment the global status update count variable
12266 */
12267 if (get_flags(STMT_END_F)) thd->status_var.com_stat[SQLCOM_UPDATE]++;
12268
12269 /*
12270 Let storage engines treat this event as an UPDATE command.
12271
12272 Set 'sql_command' as SQLCOM_UPDATE after the tables are locked.
12273 When locking the tables, it should be SQLCOM_END.
12274 THD::decide_logging_format which is called from "lock tables"
12275 assumes that row_events will have 'sql_command' as SQLCOM_END.
12276 */
12277 thd->lex->sql_command = SQLCOM_UPDATE;
12278
12279 error = row_operations_scan_and_key_setup();
12280 return error;
12281 }
12282
do_after_row_operations(const Slave_reporting_capability * const,int error)12283 int Update_rows_log_event::do_after_row_operations(
12284 const Slave_reporting_capability *const, int error) {
12285 DBUG_TRACE;
12286 error = row_operations_scan_and_key_teardown(error);
12287 return error;
12288 }
12289
do_exec_row(const Relay_log_info * const rli)12290 int Update_rows_log_event::do_exec_row(const Relay_log_info *const rli) {
12291 DBUG_ASSERT(m_table != nullptr);
12292 int error = 0;
12293
12294 /*
12295 This is the situation after locating BI:
12296
12297 ===|=== before image ====|=== after image ===|===
12298 ^ ^
12299 m_curr_row m_curr_row_end
12300
12301 BI found in the table is stored in record[0]. We copy it to record[1]
12302 and unpack AI to record[0].
12303 */
12304
12305 store_record(m_table, record[1]);
12306
12307 m_curr_row = m_curr_row_end;
12308 /* this also updates m_curr_row_end */
12309 if ((error = unpack_current_row(rli, &m_cols_ai, true /*is AI*/)))
12310 return error;
12311
12312 // Invoke check constraints on the unpacked row.
12313 if (invoke_table_check_constraints(thd, m_table))
12314 return ER_CHECK_CONSTRAINT_VIOLATED;
12315
12316 /*
12317 Now we have the right row to update. The old row (the one we're
12318 looking for) is in record[1] and the new row is in record[0].
12319 */
12320 DBUG_PRINT("info", ("Updating row in table"));
12321 DBUG_DUMP("old record", m_table->record[1], m_table->s->reclength);
12322 DBUG_DUMP("new values", m_table->record[0], m_table->s->reclength);
12323
12324 m_table->mark_columns_per_binlog_row_image(thd);
12325 error = m_table->file->ha_update_row(m_table->record[1], m_table->record[0]);
12326 if (error == HA_ERR_RECORD_IS_THE_SAME) error = 0;
12327 m_table->default_column_bitmaps();
12328
12329 return error;
12330 }
12331
12332 #endif /* defined(MYSQL_SERVER) */
12333
12334 #ifndef MYSQL_SERVER
print(FILE * file,PRINT_EVENT_INFO * print_event_info) const12335 void Update_rows_log_event::print(FILE *file,
12336 PRINT_EVENT_INFO *print_event_info) const {
12337 Rows_log_event::print_helper(file, print_event_info);
12338 }
12339 #endif
12340
Incident_log_event(const char * buf,const Format_description_event * description_event)12341 Incident_log_event::Incident_log_event(
12342 const char *buf, const Format_description_event *description_event)
12343 : binary_log::Incident_event(buf, description_event),
12344 Log_event(header(), footer()) {
12345 DBUG_TRACE;
12346 }
12347
~Incident_log_event()12348 Incident_log_event::~Incident_log_event() {
12349 if (message) bapi_free(message);
12350 }
12351
description() const12352 const char *Incident_log_event::description() const {
12353 static const char *const description[] = {"NOTHING", // Not used
12354 "LOST_EVENTS"};
12355
12356 DBUG_PRINT("info", ("incident: %d", incident));
12357
12358 return description[incident];
12359 }
12360
12361 #ifdef MYSQL_SERVER
pack_info(Protocol * protocol)12362 int Incident_log_event::pack_info(Protocol *protocol) {
12363 char buf[256];
12364 size_t bytes;
12365 if (message_length > 0)
12366 bytes = snprintf(buf, sizeof(buf), "#%d (%s)", incident, description());
12367 else
12368 bytes = snprintf(buf, sizeof(buf), "#%d (%s): %s", incident, description(),
12369 message);
12370 protocol->store_string(buf, bytes, &my_charset_bin);
12371 return 0;
12372 }
12373 #endif
12374
12375 #ifndef MYSQL_SERVER
print(FILE *,PRINT_EVENT_INFO * print_event_info) const12376 void Incident_log_event::print(FILE *,
12377 PRINT_EVENT_INFO *print_event_info) const {
12378 if (print_event_info->short_form) return;
12379
12380 print_header(&print_event_info->head_cache, print_event_info, false);
12381 my_b_printf(
12382 &print_event_info->head_cache,
12383 "\n# Incident: %s\nRELOAD DATABASE; # Shall generate syntax error\n",
12384 description());
12385 }
12386 #endif
12387
12388 #if defined(MYSQL_SERVER)
do_apply_event(Relay_log_info const * rli)12389 int Incident_log_event::do_apply_event(Relay_log_info const *rli) {
12390 DBUG_TRACE;
12391
12392 /*
12393 It is not necessary to do GTID related check if the error
12394 'ER_SLAVE_INCIDENT' is ignored.
12395 */
12396 if (ignored_error_code(ER_SLAVE_INCIDENT)) {
12397 DBUG_PRINT("info", ("Ignoring Incident"));
12398 mysql_bin_log.gtid_end_transaction(thd);
12399 return 0;
12400 }
12401
12402 enum_gtid_statement_status state = gtid_pre_statement_checks(thd);
12403 if (state == GTID_STATEMENT_EXECUTE) {
12404 if (gtid_pre_statement_post_implicit_commit_checks(thd))
12405 state = GTID_STATEMENT_CANCEL;
12406 }
12407
12408 if (state == GTID_STATEMENT_CANCEL) {
12409 uint error = thd->get_stmt_da()->mysql_errno();
12410 DBUG_ASSERT(error != 0);
12411 rli->report(ERROR_LEVEL, error, "Error executing incident event: '%s'",
12412 thd->get_stmt_da()->message_text());
12413 thd->is_slave_error = true;
12414 return -1;
12415 } else if (state == GTID_STATEMENT_SKIP) {
12416 /*
12417 Make slave skip the Incident event through general commands of GTID
12418 i.e. 'set gtid_next=<GTID>; begin; commit;'.
12419 */
12420 return 0;
12421 }
12422
12423 rli->report(ERROR_LEVEL, ER_SLAVE_INCIDENT, ER_THD(thd, ER_SLAVE_INCIDENT),
12424 description(), message_length > 0 ? message : "<none>");
12425 return 1;
12426 }
12427
write_data_header(Basic_ostream * ostream)12428 bool Incident_log_event::write_data_header(Basic_ostream *ostream) {
12429 DBUG_TRACE;
12430 DBUG_PRINT("enter", ("incident: %d", incident));
12431 uchar buf[sizeof(int16)];
12432 int2store(buf, (int16)incident);
12433 return wrapper_my_b_safe_write(ostream, buf, sizeof(buf));
12434 }
12435
12436 /*
12437 Stores string to an output stream.
12438
12439 Writes str to file in the following format:
12440 1. Stores length using only one byte (255 maximum value);
12441 2. Stores complete str.
12442 */
12443
write_str_at_most_255_bytes(Basic_ostream * ostream,const char * str,uint length)12444 static bool write_str_at_most_255_bytes(Basic_ostream *ostream, const char *str,
12445 uint length) {
12446 uchar tmp[1];
12447
12448 tmp[0] = (uchar)length;
12449 return (
12450 ostream->write(tmp, sizeof(tmp)) ||
12451 (length > 0 && ostream->write(pointer_cast<const uchar *>(str), length)));
12452 }
12453
write_data_body(Basic_ostream * ostream)12454 bool Incident_log_event::write_data_body(Basic_ostream *ostream) {
12455 uchar tmp[1];
12456 DBUG_TRACE;
12457 tmp[0] = (uchar)message_length;
12458 crc = checksum_crc32(crc, (uchar *)tmp, 1);
12459 if (message_length > 0) {
12460 crc = checksum_crc32(crc, (uchar *)message, message_length);
12461 // todo: report a bug on write_str accepts uint but treats it as uchar
12462 }
12463 return write_str_at_most_255_bytes(ostream, message, (uint)message_length);
12464 }
12465 #endif
12466
Ignorable_log_event(const char * buf,const Format_description_event * descr_event)12467 Ignorable_log_event::Ignorable_log_event(
12468 const char *buf, const Format_description_event *descr_event)
12469 : binary_log::Ignorable_event(buf, descr_event),
12470 Log_event(header(), footer()) {
12471 DBUG_TRACE;
12472 }
12473
~Ignorable_log_event()12474 Ignorable_log_event::~Ignorable_log_event() {}
12475
12476 #ifdef MYSQL_SERVER
12477 /* Pack info for its unrecognized ignorable event */
pack_info(Protocol * protocol)12478 int Ignorable_log_event::pack_info(Protocol *protocol) {
12479 char buf[256];
12480 size_t bytes;
12481 bytes = snprintf(buf, sizeof(buf), "# Unrecognized ignorable event");
12482 protocol->store_string(buf, bytes, &my_charset_bin);
12483 return 0;
12484 }
12485 #endif
12486
12487 #ifndef MYSQL_SERVER
12488 /* Print for its unrecognized ignorable event */
print(FILE *,PRINT_EVENT_INFO * print_event_info) const12489 void Ignorable_log_event::print(FILE *,
12490 PRINT_EVENT_INFO *print_event_info) const {
12491 if (print_event_info->short_form) return;
12492
12493 print_header(&print_event_info->head_cache, print_event_info, false);
12494 my_b_printf(&print_event_info->head_cache, "\tIgnorable\n");
12495 my_b_printf(&print_event_info->head_cache,
12496 "# Unrecognized ignorable event\n");
12497 }
12498 #endif
12499
Rows_query_log_event(const char * buf,const Format_description_event * descr_event)12500 Rows_query_log_event::Rows_query_log_event(
12501 const char *buf, const Format_description_event *descr_event)
12502 : binary_log::Ignorable_event(buf, descr_event),
12503 Ignorable_log_event(buf, descr_event),
12504 binary_log::Rows_query_event(buf, descr_event) {
12505 DBUG_TRACE;
12506 }
12507
12508 #ifdef MYSQL_SERVER
pack_info(Protocol * protocol)12509 int Rows_query_log_event::pack_info(Protocol *protocol) {
12510 char *buf;
12511 size_t bytes;
12512 size_t len = sizeof("# ") + strlen(m_rows_query);
12513 if (!(buf = (char *)my_malloc(key_memory_log_event, len, MYF(MY_WME))))
12514 return 1;
12515 bytes = snprintf(buf, len, "# %s", m_rows_query);
12516 protocol->store_string(buf, bytes, &my_charset_bin);
12517 my_free(buf);
12518 return 0;
12519 }
12520 #endif
12521
12522 #ifndef MYSQL_SERVER
print(FILE *,PRINT_EVENT_INFO * print_event_info) const12523 void Rows_query_log_event::print(FILE *,
12524 PRINT_EVENT_INFO *print_event_info) const {
12525 if (!print_event_info->short_form && print_event_info->verbose > 1) {
12526 IO_CACHE *const head = &print_event_info->head_cache;
12527 IO_CACHE *const body = &print_event_info->body_cache;
12528 char *token = nullptr, *saveptr = nullptr;
12529 char *rows_query_copy = nullptr;
12530 if (!(rows_query_copy =
12531 my_strdup(key_memory_log_event, m_rows_query, MYF(MY_WME))))
12532 return;
12533
12534 print_header(head, print_event_info, false);
12535 my_b_printf(head, "\tRows_query\n");
12536 /*
12537 Prefix every line of a multi-line query with '#' to prevent the
12538 statement from being executed when binary log will be processed
12539 using 'mysqlbinlog --verbose --verbose'.
12540 */
12541 for (token = my_strtok_r(rows_query_copy, "\n", &saveptr); token;
12542 token = my_strtok_r(nullptr, "\n", &saveptr))
12543 my_b_printf(head, "# %s\n", token);
12544 my_free(rows_query_copy);
12545 print_base64(body, print_event_info, true);
12546 }
12547 }
12548 #endif
12549
12550 #if defined(MYSQL_SERVER)
write_data_body(Basic_ostream * ostream)12551 bool Rows_query_log_event::write_data_body(Basic_ostream *ostream) {
12552 DBUG_TRACE;
12553 /*
12554 m_rows_query length will be stored using only one byte, but on read
12555 that length will be ignored and the complete query will be read.
12556 */
12557 return write_str_at_most_255_bytes(ostream, m_rows_query,
12558 strlen(m_rows_query));
12559 }
12560
do_apply_event(Relay_log_info const * rli)12561 int Rows_query_log_event::do_apply_event(Relay_log_info const *rli) {
12562 DBUG_TRACE;
12563 DBUG_ASSERT(rli->info_thd == thd);
12564 /* Set query for writing Rows_query log event into binlog later.*/
12565 thd->set_query(m_rows_query, strlen(m_rows_query));
12566 thd->set_query_for_display(m_rows_query, strlen(m_rows_query));
12567
12568 DBUG_ASSERT(rli->rows_query_ev == nullptr);
12569
12570 const_cast<Relay_log_info *>(rli)->rows_query_ev = this;
12571 /* Tell worker not to free the event */
12572 worker = nullptr;
12573 return 0;
12574 }
12575 #endif
12576
12577 const char *Gtid_log_event::SET_STRING_PREFIX = "SET @@SESSION.GTID_NEXT= '";
12578
Gtid_log_event(const char * buffer,const Format_description_event * description_event)12579 Gtid_log_event::Gtid_log_event(
12580 const char *buffer, const Format_description_event *description_event)
12581 : binary_log::Gtid_event(buffer, description_event),
12582 Log_event(header(), footer()) {
12583 DBUG_TRACE;
12584 if (!is_valid()) return;
12585
12586 #ifndef DBUG_OFF
12587 uint8_t const common_header_len = description_event->common_header_len;
12588 uint8 const post_header_len =
12589 buffer[EVENT_TYPE_OFFSET] == binary_log::ANONYMOUS_GTID_LOG_EVENT
12590 ? description_event
12591 ->post_header_len[binary_log::ANONYMOUS_GTID_LOG_EVENT - 1]
12592 : description_event->post_header_len[binary_log::GTID_LOG_EVENT - 1];
12593 DBUG_PRINT("info",
12594 ("event_len: %zu; common_header_len: %d; post_header_len: %d",
12595 header()->data_written, common_header_len, post_header_len));
12596 #endif
12597
12598 spec.type = get_type_code() == binary_log::ANONYMOUS_GTID_LOG_EVENT
12599 ? ANONYMOUS_GTID
12600 : ASSIGNED_GTID;
12601 sid.copy_from((uchar *)Uuid_parent_struct.bytes);
12602 spec.gtid.sidno = gtid_info_struct.rpl_gtid_sidno;
12603 spec.gtid.gno = gtid_info_struct.rpl_gtid_gno;
12604 }
12605
12606 #ifdef MYSQL_SERVER
Gtid_log_event(THD * thd_arg,bool using_trans,int64 last_committed_arg,int64 sequence_number_arg,bool may_have_sbr_stmts_arg,ulonglong original_commit_timestamp_arg,ulonglong immediate_commit_timestamp_arg,uint32_t original_server_version_arg,uint32_t immediate_server_version_arg)12607 Gtid_log_event::Gtid_log_event(THD *thd_arg, bool using_trans,
12608 int64 last_committed_arg,
12609 int64 sequence_number_arg,
12610 bool may_have_sbr_stmts_arg,
12611 ulonglong original_commit_timestamp_arg,
12612 ulonglong immediate_commit_timestamp_arg,
12613 uint32_t original_server_version_arg,
12614 uint32_t immediate_server_version_arg)
12615 : binary_log::Gtid_event(
12616 last_committed_arg, sequence_number_arg, may_have_sbr_stmts_arg,
12617 original_commit_timestamp_arg, immediate_commit_timestamp_arg,
12618 original_server_version_arg, immediate_server_version_arg),
12619 Log_event(thd_arg,
12620 thd_arg->variables.gtid_next.type == ANONYMOUS_GTID
12621 ? LOG_EVENT_IGNORABLE_F
12622 : 0,
12623 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE
12624 : Log_event::EVENT_STMT_CACHE,
12625 Log_event::EVENT_NORMAL_LOGGING, header(), footer()) {
12626 DBUG_TRACE;
12627 if (thd->owned_gtid.sidno > 0) {
12628 spec.set(thd->owned_gtid);
12629 sid = thd->owned_sid;
12630 } else {
12631 DBUG_ASSERT(thd->owned_gtid.sidno == THD::OWNED_SIDNO_ANONYMOUS);
12632 spec.set_anonymous();
12633 spec.gtid.clear();
12634 sid.clear();
12635 }
12636
12637 Log_event_type event_type =
12638 (spec.type == ANONYMOUS_GTID ? binary_log::ANONYMOUS_GTID_LOG_EVENT
12639 : binary_log::GTID_LOG_EVENT);
12640 common_header->type_code = event_type;
12641
12642 #ifndef DBUG_OFF
12643 char buf[MAX_SET_STRING_LENGTH + 1];
12644 to_string(buf);
12645 DBUG_PRINT("info", ("%s", buf));
12646 #endif
12647 common_header->set_is_valid(true);
12648 }
12649
Gtid_log_event(uint32 server_id_arg,bool using_trans,int64 last_committed_arg,int64 sequence_number_arg,bool may_have_sbr_stmts_arg,ulonglong original_commit_timestamp_arg,ulonglong immediate_commit_timestamp_arg,const Gtid_specification spec_arg,uint32_t original_server_version_arg,uint32_t immediate_server_version_arg)12650 Gtid_log_event::Gtid_log_event(
12651 uint32 server_id_arg, bool using_trans, int64 last_committed_arg,
12652 int64 sequence_number_arg, bool may_have_sbr_stmts_arg,
12653 ulonglong original_commit_timestamp_arg,
12654 ulonglong immediate_commit_timestamp_arg, const Gtid_specification spec_arg,
12655 uint32_t original_server_version_arg, uint32_t immediate_server_version_arg)
12656 : binary_log::Gtid_event(
12657 last_committed_arg, sequence_number_arg, may_have_sbr_stmts_arg,
12658 original_commit_timestamp_arg, immediate_commit_timestamp_arg,
12659 original_server_version_arg, immediate_server_version_arg),
12660 Log_event(header(), footer(),
12661 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE
12662 : Log_event::EVENT_STMT_CACHE,
12663 Log_event::EVENT_NORMAL_LOGGING) {
12664 DBUG_TRACE;
12665 server_id = server_id_arg;
12666 common_header->unmasked_server_id = server_id_arg;
12667
12668 if (spec_arg.type == ASSIGNED_GTID) {
12669 DBUG_ASSERT(spec_arg.gtid.sidno > 0 && spec_arg.gtid.gno > 0);
12670 spec.set(spec_arg.gtid);
12671 global_sid_lock->rdlock();
12672 sid = global_sid_map->sidno_to_sid(spec_arg.gtid.sidno);
12673 global_sid_lock->unlock();
12674 } else {
12675 DBUG_ASSERT(spec_arg.type == ANONYMOUS_GTID);
12676 spec.set_anonymous();
12677 spec.gtid.clear();
12678 sid.clear();
12679 common_header->flags |= LOG_EVENT_IGNORABLE_F;
12680 }
12681
12682 Log_event_type event_type =
12683 (spec.type == ANONYMOUS_GTID ? binary_log::ANONYMOUS_GTID_LOG_EVENT
12684 : binary_log::GTID_LOG_EVENT);
12685 common_header->type_code = event_type;
12686
12687 #ifndef DBUG_OFF
12688 char buf[MAX_SET_STRING_LENGTH + 1];
12689 to_string(buf);
12690 DBUG_PRINT("info", ("%s", buf));
12691 #endif
12692 common_header->set_is_valid(true);
12693 }
12694
pack_info(Protocol * protocol)12695 int Gtid_log_event::pack_info(Protocol *protocol) {
12696 char buffer[MAX_SET_STRING_LENGTH + 1];
12697 size_t len = to_string(buffer);
12698 protocol->store_string(buffer, len, &my_charset_bin);
12699 return 0;
12700 }
12701 #endif // MYSQL_SERVER
12702
to_string(char * buf) const12703 size_t Gtid_log_event::to_string(char *buf) const {
12704 char *p = buf;
12705 DBUG_ASSERT(strlen(SET_STRING_PREFIX) == SET_STRING_PREFIX_LENGTH);
12706 strcpy(p, SET_STRING_PREFIX);
12707 p += SET_STRING_PREFIX_LENGTH;
12708 p += spec.to_string(&sid, p);
12709 *p++ = '\'';
12710 *p = '\0';
12711 return p - buf;
12712 }
12713
12714 #ifndef MYSQL_SERVER
print(FILE *,PRINT_EVENT_INFO * print_event_info) const12715 void Gtid_log_event::print(FILE *, PRINT_EVENT_INFO *print_event_info) const {
12716 char buffer[MAX_SET_STRING_LENGTH + 1];
12717 IO_CACHE *const head = &print_event_info->head_cache;
12718 if (!print_event_info->short_form) {
12719 print_header(head, print_event_info, false);
12720 my_b_printf(head,
12721 "\t%s\tlast_committed=%llu\tsequence_number=%llu\t"
12722 "rbr_only=%s\t"
12723 "original_committed_timestamp=%llu\t"
12724 "immediate_commit_timestamp=%llu\t"
12725 "transaction_length=%llu\n",
12726 get_type_code() == binary_log::GTID_LOG_EVENT
12727 ? "GTID"
12728 : "Anonymous_GTID",
12729 last_committed, sequence_number,
12730 may_have_sbr_stmts ? "no" : "yes", original_commit_timestamp,
12731 immediate_commit_timestamp, transaction_length);
12732 }
12733
12734 /*
12735 The applier thread can always use "READ COMMITTED" isolation for
12736 transactions containing only RBR events (Table_map + Rows).
12737
12738 This would prevent some deadlock issues because InnoDB doesn't
12739 acquire GAP locks in "READ COMMITTED" isolation level since
12740 MySQL 5.7.18.
12741 */
12742 if (!may_have_sbr_stmts) {
12743 my_b_printf(head,
12744 "/*!50718 SET TRANSACTION ISOLATION LEVEL "
12745 "READ COMMITTED*/%s\n",
12746 print_event_info->delimiter);
12747 }
12748
12749 /*
12750 We always print the original commit timestamp in order to make
12751 dumps from binary logs generated on servers without this info on
12752 GTID events to print "0" (not known) as the session value.
12753 */
12754 char llbuf[22];
12755
12756 char immediate_commit_timestamp_str[256];
12757 char original_commit_timestamp_str[256];
12758
12759 microsecond_timestamp_to_str(immediate_commit_timestamp,
12760 immediate_commit_timestamp_str);
12761 microsecond_timestamp_to_str(original_commit_timestamp,
12762 original_commit_timestamp_str);
12763
12764 my_b_printf(head, "# original_commit_timestamp=%s (%s)\n",
12765 llstr(original_commit_timestamp, llbuf),
12766 original_commit_timestamp_str);
12767 my_b_printf(head, "# immediate_commit_timestamp=%s (%s)\n",
12768 llstr(immediate_commit_timestamp, llbuf),
12769 immediate_commit_timestamp_str);
12770
12771 if (DBUG_EVALUATE_IF("do_not_write_rpl_OCT", false, true)) {
12772 my_b_printf(
12773 head, "/*!80001 SET @@session.original_commit_timestamp=%s*/%s\n",
12774 llstr(original_commit_timestamp, llbuf), print_event_info->delimiter);
12775 }
12776
12777 my_b_printf(head, "/*!80014 SET @@session.original_server_version=%u*/%s\n",
12778 original_server_version, print_event_info->delimiter);
12779
12780 my_b_printf(head, "/*!80014 SET @@session.immediate_server_version=%u*/%s\n",
12781 immediate_server_version, print_event_info->delimiter);
12782
12783 to_string(buffer);
12784 my_b_printf(head, "%s%s\n", buffer, print_event_info->delimiter);
12785 }
12786 #endif
12787
12788 #ifdef MYSQL_SERVER
write_post_header_to_memory(uchar * buffer)12789 uint32 Gtid_log_event::write_post_header_to_memory(uchar *buffer) {
12790 DBUG_TRACE;
12791 uchar *ptr_buffer = buffer;
12792
12793 /* Encode the GTID flags */
12794 uchar gtid_flags = 0;
12795 gtid_flags |=
12796 may_have_sbr_stmts ? binary_log::Gtid_event::FLAG_MAY_HAVE_SBR : 0;
12797 *ptr_buffer = gtid_flags;
12798 ptr_buffer += ENCODED_FLAG_LENGTH;
12799
12800 #ifndef DBUG_OFF
12801 char buf[binary_log::Uuid::TEXT_LENGTH + 1];
12802 sid.to_string(buf);
12803 DBUG_PRINT("info",
12804 ("sid=%s sidno=%d gno=%lld", buf, spec.gtid.sidno, spec.gtid.gno));
12805 #endif
12806
12807 sid.copy_to(ptr_buffer);
12808 ptr_buffer += ENCODED_SID_LENGTH;
12809
12810 int8store(ptr_buffer, spec.gtid.gno);
12811 ptr_buffer += ENCODED_GNO_LENGTH;
12812
12813 *ptr_buffer = LOGICAL_TIMESTAMP_TYPECODE;
12814 ptr_buffer += LOGICAL_TIMESTAMP_TYPECODE_LENGTH;
12815
12816 DBUG_ASSERT((sequence_number == 0 && last_committed == 0) ||
12817 (sequence_number > last_committed));
12818 DBUG_EXECUTE_IF("set_commit_parent_100", {
12819 last_committed =
12820 max<int64>(sequence_number > 1 ? 1 : 0, sequence_number - 100);
12821 });
12822 DBUG_EXECUTE_IF("set_commit_parent_150", {
12823 last_committed =
12824 max<int64>(sequence_number > 1 ? 1 : 0, sequence_number - 150);
12825 });
12826 DBUG_EXECUTE_IF("feign_commit_parent", { last_committed = sequence_number; });
12827 int8store(ptr_buffer, last_committed);
12828 int8store(ptr_buffer + 8, sequence_number);
12829 ptr_buffer += LOGICAL_TIMESTAMP_LENGTH;
12830
12831 DBUG_ASSERT(ptr_buffer == (buffer + POST_HEADER_LENGTH));
12832
12833 return POST_HEADER_LENGTH;
12834 }
12835
12836 #ifdef MYSQL_SERVER
write_data_header(Basic_ostream * ostream)12837 bool Gtid_log_event::write_data_header(Basic_ostream *ostream) {
12838 DBUG_TRACE;
12839 uchar buffer[POST_HEADER_LENGTH];
12840 write_post_header_to_memory(buffer);
12841 return wrapper_my_b_safe_write(ostream, (uchar *)buffer, POST_HEADER_LENGTH);
12842 }
12843
write_body_to_memory(uchar * buffer)12844 uint32 Gtid_log_event::write_body_to_memory(uchar *buffer) {
12845 DBUG_TRACE;
12846 DBUG_EXECUTE_IF("do_not_write_rpl_timestamps", return 0;);
12847 uchar *ptr_buffer = buffer;
12848
12849 /*
12850 We want to modify immediate_commit_timestamp with the flag written
12851 in the highest bit(MSB). At the same time, we also want to have the original
12852 value to be able to use in if() later, so we use a temporary variable here.
12853 */
12854 ulonglong immediate_commit_timestamp_with_flag = immediate_commit_timestamp;
12855
12856 // Transaction did not originate at this server, set highest bit to hint this.
12857 if (immediate_commit_timestamp != original_commit_timestamp)
12858 immediate_commit_timestamp_with_flag |=
12859 (1ULL << ENCODED_COMMIT_TIMESTAMP_LENGTH);
12860 else // Clear highest bit(MSB)
12861 immediate_commit_timestamp_with_flag &=
12862 ~(1ULL << ENCODED_COMMIT_TIMESTAMP_LENGTH);
12863
12864 int7store(ptr_buffer, immediate_commit_timestamp_with_flag);
12865 ptr_buffer += IMMEDIATE_COMMIT_TIMESTAMP_LENGTH;
12866
12867 if (immediate_commit_timestamp != original_commit_timestamp) {
12868 int7store(ptr_buffer, original_commit_timestamp);
12869 ptr_buffer += ORIGINAL_COMMIT_TIMESTAMP_LENGTH;
12870 }
12871
12872 // Write the transaction length information
12873 uchar *ptr_after_length = net_store_length(ptr_buffer, transaction_length);
12874 ptr_buffer = ptr_after_length;
12875
12876 /*
12877 We want to modify immediate_server_version with the flag written to its MSB.
12878 At the same time, we also want to have the original value to be able to use
12879 it in if() later, so we use a temporary variable here.
12880 */
12881 uint32_t immediate_server_version_with_flag = immediate_server_version;
12882
12883 if (immediate_server_version != original_server_version)
12884 immediate_server_version_with_flag |=
12885 (1ULL << ENCODED_SERVER_VERSION_LENGTH);
12886 else // Clear MSB
12887 immediate_server_version_with_flag &=
12888 ~(1ULL << ENCODED_SERVER_VERSION_LENGTH);
12889
12890 int4store(ptr_buffer, immediate_server_version_with_flag);
12891 ptr_buffer += IMMEDIATE_SERVER_VERSION_LENGTH;
12892
12893 if (immediate_server_version != original_server_version) {
12894 int4store(ptr_buffer, original_server_version);
12895 ptr_buffer += ORIGINAL_SERVER_VERSION_LENGTH;
12896 }
12897
12898 return ptr_buffer - buffer;
12899 }
12900
write_data_body(Basic_ostream * ostream)12901 bool Gtid_log_event::write_data_body(Basic_ostream *ostream) {
12902 DBUG_TRACE;
12903 uchar buffer[MAX_DATA_LENGTH];
12904 uint32 len = write_body_to_memory(buffer);
12905 return wrapper_my_b_safe_write(ostream, (uchar *)buffer, len);
12906 }
12907
12908 #endif // MYSQL_SERVER
12909
do_apply_event(Relay_log_info const * rli)12910 int Gtid_log_event::do_apply_event(Relay_log_info const *rli) {
12911 DBUG_TRACE;
12912 DBUG_ASSERT(rli->info_thd == thd);
12913
12914 /*
12915 In rare cases it is possible that we already own a GTID (either
12916 ANONYMOUS or ASSIGNED_GTID). This can happen if a transaction was truncated
12917 in the middle in the relay log and then next relay log begins with a
12918 Gtid_log_events without closing the transaction context from the previous
12919 relay log. In this case the only sensible thing to do is to discard the
12920 truncated transaction and move on.
12921
12922 Note that when the applier is "GTID skipping" a transactions it
12923 owns nothing, but its gtid_next->type == ASSIGNED_GTID.
12924 */
12925 const Gtid_specification *gtid_next = &thd->variables.gtid_next;
12926 if (!thd->owned_gtid_is_empty() ||
12927 (thd->owned_gtid_is_empty() && gtid_next->type == ASSIGNED_GTID)) {
12928 /*
12929 Slave will execute this code if a previous Gtid_log_event was applied
12930 but the GTID wasn't consumed yet (the transaction was not committed,
12931 nor rolled back, nor skipped).
12932 On a client session we cannot do consecutive SET GTID_NEXT without
12933 a COMMIT or a ROLLBACK in the middle.
12934 Applying this event without rolling back the current transaction may
12935 lead to problems, as a "BEGIN" event following this GTID will
12936 implicitly commit the "partial transaction" and will consume the
12937 GTID. If this "partial transaction" was left in the relay log by the
12938 IO thread restarting in the middle of a transaction, you could have
12939 the partial transaction being logged with the GTID on the slave,
12940 causing data corruption on replication.
12941 */
12942 if (thd->server_status & SERVER_STATUS_IN_TRANS) {
12943 /* This is not an error (XA is safe), just an information */
12944 rli->report(INFORMATION_LEVEL, 0,
12945 "Rolling back unfinished transaction (no COMMIT "
12946 "or ROLLBACK in relay log). A probable cause is partial "
12947 "transaction left on relay log because of restarting IO "
12948 "thread with auto-positioning protocol.");
12949 const_cast<Relay_log_info *>(rli)->cleanup_context(thd, true);
12950 }
12951 gtid_state->update_on_rollback(thd);
12952 }
12953
12954 global_sid_lock->rdlock();
12955
12956 // make sure that sid has been converted to sidno
12957 if (spec.type == ASSIGNED_GTID) {
12958 if (get_sidno(false) < 0) {
12959 global_sid_lock->unlock();
12960 return 1; // out of memory
12961 }
12962 }
12963
12964 // set_gtid_next releases global_sid_lock
12965 if (set_gtid_next(thd, spec))
12966 // This can happen e.g. if gtid_mode is incompatible with spec.
12967 return 1;
12968
12969 /*
12970 Set the original_commit_timestamp.
12971 0 will be used if this event does not contain such information.
12972 */
12973 enum_gtid_statement_status state = gtid_pre_statement_checks(thd);
12974 thd->variables.original_commit_timestamp = original_commit_timestamp;
12975 thd->set_original_commit_timestamp_for_slave_thread();
12976 /**
12977 Set the original/immediate server version.
12978 It will be set to UNKNOWN_SERVER_VERSION if the event does not contain such
12979 information.
12980 */
12981 thd->variables.original_server_version = original_server_version;
12982 thd->variables.immediate_server_version = immediate_server_version;
12983 const_cast<Relay_log_info *>(rli)->started_processing(
12984 thd->variables.gtid_next.gtid, original_commit_timestamp,
12985 immediate_commit_timestamp, state == GTID_STATEMENT_SKIP);
12986
12987 /*
12988 If the current transaction contains no changes logged with SBR
12989 we can assume this transaction as a pure row based replicated one.
12990
12991 Based on this assumption, we can set current transaction tx_isolation to
12992 READ COMMITTED in order to avoid concurrent transactions to be blocked by
12993 InnoDB gap locks.
12994
12995 The session tx_isolation will be restored:
12996 - When the transaction finishes with QUERY(COMMIT|ROLLBACK),
12997 as the MySQL server does for ordinary user sessions;
12998 - When applying a Xid_log_event, after committing the transaction;
12999 - When applying a XA_prepare_log_event, after preparing the transaction;
13000 - When the applier needs to abort a transaction execution.
13001
13002 Notice that when a transaction is being "gtid skipped", its statements are
13003 not actually executed (see mysql_execute_command()). So, the call to the
13004 function that would restore the tx_isolation after finishing the transaction
13005 may not happen.
13006 */
13007 if (DBUG_EVALUATE_IF(
13008 "force_trx_as_rbr_only", true,
13009 !may_have_sbr_stmts && thd->tx_isolation > ISO_READ_COMMITTED &&
13010 gtid_pre_statement_checks(thd) != GTID_STATEMENT_SKIP)) {
13011 DBUG_ASSERT(thd->get_transaction()->is_empty(Transaction_ctx::STMT));
13012 DBUG_ASSERT(thd->get_transaction()->is_empty(Transaction_ctx::SESSION));
13013 DBUG_ASSERT(!thd->lock);
13014 DBUG_PRINT("info", ("setting tx_isolation to READ COMMITTED"));
13015 set_tx_isolation(thd, ISO_READ_COMMITTED, true /*one_shot*/);
13016 }
13017
13018 return 0;
13019 }
13020
do_update_pos(Relay_log_info * rli)13021 int Gtid_log_event::do_update_pos(Relay_log_info *rli) {
13022 /*
13023 This event does not increment group positions. This means
13024 that if there is a failure after it has been processed,
13025 it will be automatically re-executed.
13026 */
13027 rli->inc_event_relay_log_pos();
13028 DBUG_EXECUTE_IF(
13029 "crash_after_update_pos_gtid",
13030 sql_print_information("Crashing crash_after_update_pos_gtid.");
13031 DBUG_SUICIDE(););
13032 return 0;
13033 }
13034
do_shall_skip(Relay_log_info * rli)13035 Log_event::enum_skip_reason Gtid_log_event::do_shall_skip(Relay_log_info *rli) {
13036 return Log_event::continue_group(rli);
13037 }
13038 #endif // MYSQL_SERVER
13039
set_trx_length_by_cache_size(ulonglong cache_size,bool is_checksum_enabled,int event_counter)13040 void Gtid_log_event::set_trx_length_by_cache_size(ulonglong cache_size,
13041 bool is_checksum_enabled,
13042 int event_counter) {
13043 // Transaction content length
13044 transaction_length = cache_size;
13045 if (is_checksum_enabled)
13046 transaction_length += event_counter * BINLOG_CHECKSUM_LEN;
13047
13048 // GTID length
13049 transaction_length += LOG_EVENT_HEADER_LEN;
13050 transaction_length += POST_HEADER_LENGTH;
13051 transaction_length += get_commit_timestamp_length();
13052 transaction_length += get_server_version_length();
13053 transaction_length += is_checksum_enabled ? BINLOG_CHECKSUM_LEN : 0;
13054
13055 /*
13056 Notice that it is not possible to determine the transaction_length field
13057 size using pack.cc:net_length_size() since the length of the field itself
13058 must be added to the value.
13059
13060 Example: Suppose transaction_length is 250 without considering the
13061 transaction_length field. Using net_length_size(250) would return 1, but
13062 when adding the transaction_length field size to it (+1), the
13063 transaction_length becomes 251, and the field must be represented using two
13064 more bytes, so the correct transaction length must be in fact 253.
13065 */
13066 #ifndef DBUG_OFF
13067 ulonglong size_without_transaction_length = transaction_length;
13068 #endif
13069 // transaction_length will use at least TRANSACTION_LENGTH_MIN_LENGTH
13070 transaction_length += TRANSACTION_LENGTH_MIN_LENGTH;
13071 DBUG_ASSERT(transaction_length - size_without_transaction_length == 1);
13072 if (transaction_length >= 251ULL) {
13073 // transaction_length will use at least 3 bytes
13074 transaction_length += 2;
13075 DBUG_ASSERT(transaction_length - size_without_transaction_length == 3);
13076 if (transaction_length >= 65536ULL) {
13077 // transaction_length will use at least 4 bytes
13078 transaction_length += 1;
13079 DBUG_ASSERT(transaction_length - size_without_transaction_length == 4);
13080 if (transaction_length >= 16777216ULL) {
13081 // transaction_length will use 9 bytes
13082 transaction_length += 5;
13083 DBUG_ASSERT(transaction_length - size_without_transaction_length == 9);
13084 }
13085 }
13086 }
13087 }
13088
get_sidno(bool need_lock)13089 rpl_sidno Gtid_log_event::get_sidno(bool need_lock) {
13090 if (spec.gtid.sidno < 0) {
13091 if (need_lock)
13092 global_sid_lock->rdlock();
13093 else
13094 global_sid_lock->assert_some_lock();
13095 spec.gtid.sidno = global_sid_map->add_sid(sid);
13096 if (need_lock) global_sid_lock->unlock();
13097 }
13098 return spec.gtid.sidno;
13099 }
13100
Previous_gtids_log_event(const char * buf_arg,const Format_description_event * description_event)13101 Previous_gtids_log_event::Previous_gtids_log_event(
13102 const char *buf_arg, const Format_description_event *description_event)
13103 : binary_log::Previous_gtids_event(buf_arg, description_event),
13104 Log_event(header(), footer()) {
13105 DBUG_TRACE;
13106 }
13107
13108 #ifdef MYSQL_SERVER
Previous_gtids_log_event(const Gtid_set * set)13109 Previous_gtids_log_event::Previous_gtids_log_event(const Gtid_set *set)
13110 : binary_log::Previous_gtids_event(),
13111 Log_event(header(), footer(), Log_event::EVENT_NO_CACHE,
13112 Log_event::EVENT_IMMEDIATE_LOGGING) {
13113 DBUG_TRACE;
13114 common_header->type_code = binary_log::PREVIOUS_GTIDS_LOG_EVENT;
13115 common_header->flags |= LOG_EVENT_IGNORABLE_F;
13116 set->get_sid_map()->get_sid_lock()->assert_some_lock();
13117 buf_size = set->get_encoded_length();
13118 uchar *buffer =
13119 (uchar *)my_malloc(key_memory_log_event, buf_size, MYF(MY_WME));
13120 if (buffer != nullptr) {
13121 set->encode(buffer);
13122 register_temp_buf((char *)buffer);
13123 }
13124 buf = buffer;
13125 // if buf is empty, is_valid will be false
13126 common_header->set_is_valid(buf != nullptr);
13127 }
13128
pack_info(Protocol * protocol)13129 int Previous_gtids_log_event::pack_info(Protocol *protocol) {
13130 size_t length = 0;
13131 char *str = get_str(&length, &Gtid_set::default_string_format);
13132 if (str == nullptr) return 1;
13133 protocol->store_string(str, length, &my_charset_bin);
13134 my_free(str);
13135 return 0;
13136 }
13137 #endif // MYSQL_SERVER
13138
13139 #ifndef MYSQL_SERVER
print(FILE *,PRINT_EVENT_INFO * print_event_info) const13140 void Previous_gtids_log_event::print(FILE *,
13141 PRINT_EVENT_INFO *print_event_info) const {
13142 IO_CACHE *const head = &print_event_info->head_cache;
13143 char *str = get_str(nullptr, &Gtid_set::commented_string_format);
13144 if (str != nullptr) {
13145 if (!print_event_info->short_form) {
13146 print_header(head, print_event_info, false);
13147 my_b_printf(head, "\tPrevious-GTIDs\n");
13148 }
13149 my_b_printf(head, "%s\n", str);
13150 my_free(str);
13151 }
13152 }
13153 #endif
13154
add_to_set(Gtid_set * target) const13155 int Previous_gtids_log_event::add_to_set(Gtid_set *target) const {
13156 DBUG_TRACE;
13157 size_t end_pos = 0;
13158 size_t add_size = DBUG_EVALUATE_IF("gtid_has_extra_data", 10, 0);
13159 /* Silently ignore additional unknown data at the end of the encoding */
13160 PROPAGATE_REPORTED_ERROR_INT(
13161 target->add_gtid_encoding(buf, buf_size + add_size, &end_pos));
13162 DBUG_ASSERT(end_pos <= buf_size);
13163 return 0;
13164 }
13165
get_str(size_t * length_p,const Gtid_set::String_format * string_format) const13166 char *Previous_gtids_log_event::get_str(
13167 size_t *length_p, const Gtid_set::String_format *string_format) const {
13168 DBUG_TRACE;
13169 Sid_map sid_map(nullptr);
13170 Gtid_set set(&sid_map, nullptr);
13171 DBUG_PRINT("info", ("temp_buf=%p buf=%p", temp_buf, buf));
13172 if (set.add_gtid_encoding(buf, buf_size) != RETURN_STATUS_OK) return nullptr;
13173 set.dbug_print("set");
13174 size_t length = set.get_string_length(string_format);
13175 DBUG_PRINT("info", ("string length= %lu", (ulong)length));
13176 char *str = (char *)my_malloc(key_memory_log_event, length + 1, MYF(MY_WME));
13177 if (str != nullptr) {
13178 set.to_string(str, false /*need_lock*/, string_format);
13179 if (length_p != nullptr) *length_p = length;
13180 }
13181 return str;
13182 }
13183
13184 #ifdef MYSQL_SERVER
write_data_body(Basic_ostream * ostream)13185 bool Previous_gtids_log_event::write_data_body(Basic_ostream *ostream) {
13186 DBUG_TRACE;
13187 DBUG_PRINT("info", ("size=%d", static_cast<int>(buf_size)));
13188 bool ret = wrapper_my_b_safe_write(ostream, buf, buf_size);
13189 return ret;
13190 }
13191
do_update_pos(Relay_log_info * rli)13192 int Previous_gtids_log_event::do_update_pos(Relay_log_info *rli) {
13193 rli->inc_event_relay_log_pos();
13194 return 0;
13195 }
13196
13197 /**************************************************************************
13198 Transaction_context_log_event methods
13199 **************************************************************************/
13200
Transaction_context_log_event(const char * server_uuid_arg,bool using_trans,my_thread_id thread_id_arg,bool is_gtid_specified_arg)13201 Transaction_context_log_event::Transaction_context_log_event(
13202 const char *server_uuid_arg, bool using_trans, my_thread_id thread_id_arg,
13203 bool is_gtid_specified_arg)
13204 : binary_log::Transaction_context_event(thread_id_arg,
13205 is_gtid_specified_arg),
13206 Log_event(header(), footer(),
13207 using_trans ? Log_event::EVENT_TRANSACTIONAL_CACHE
13208 : Log_event::EVENT_STMT_CACHE,
13209 Log_event::EVENT_NORMAL_LOGGING) {
13210 DBUG_TRACE;
13211 common_header->flags |= LOG_EVENT_IGNORABLE_F;
13212 server_uuid = nullptr;
13213 sid_map = new Sid_map(nullptr);
13214 snapshot_version = new Gtid_set(sid_map);
13215
13216 /*
13217 Copy global_sid_map to a local copy to avoid the acquisition
13218 of the global_sid_lock for operations on top of this snapshot
13219 version.
13220 The Sid_map and Gtid_executed must be read under the protection
13221 of MYSQL_BIN_LOG.LOCK_commit to avoid race conditions between
13222 ordered commits in the storage engine and gtid_state update.
13223 */
13224 if (mysql_bin_log.get_gtid_executed(sid_map, snapshot_version)) goto err;
13225
13226 server_uuid = my_strdup(key_memory_log_event, server_uuid_arg, MYF(MY_WME));
13227 if (server_uuid == nullptr) goto err;
13228
13229 // These two fields are only populated on event decoding.
13230 // Encoding is done directly from snapshot_version field.
13231 encoded_snapshot_version = nullptr;
13232 encoded_snapshot_version_length = 0;
13233
13234 // Debug sync point for SQL threads.
13235 DBUG_EXECUTE_IF(
13236 "debug.wait_after_set_snapshot_version_on_transaction_context_log_event",
13237 {
13238 const char act[] =
13239 "now wait_for "
13240 "signal.resume_after_set_snapshot_version_on_transaction_context_"
13241 "log_event";
13242 DBUG_ASSERT(opt_debug_sync_timeout > 0);
13243 DBUG_ASSERT(!debug_sync_set_action(current_thd, STRING_WITH_LEN(act)));
13244 };);
13245
13246 common_header->set_is_valid(true);
13247 return;
13248
13249 err:
13250 common_header->set_is_valid(false);
13251 }
13252 #endif // MYSQL_SERVER
13253
Transaction_context_log_event(const char * buffer,const Format_description_event * descr_event)13254 Transaction_context_log_event::Transaction_context_log_event(
13255 const char *buffer, const Format_description_event *descr_event)
13256 : binary_log::Transaction_context_event(buffer, descr_event),
13257 Log_event(header(), footer()),
13258 sid_map(nullptr),
13259 snapshot_version(nullptr) {
13260 DBUG_TRACE;
13261 if (!is_valid()) return;
13262
13263 common_header->flags |= LOG_EVENT_IGNORABLE_F;
13264
13265 sid_map = new Sid_map(nullptr);
13266 snapshot_version = new Gtid_set(sid_map);
13267 }
13268
~Transaction_context_log_event()13269 Transaction_context_log_event::~Transaction_context_log_event() {
13270 DBUG_TRACE;
13271 if (server_uuid) my_free(const_cast<char *>(server_uuid));
13272 server_uuid = nullptr;
13273 if (encoded_snapshot_version)
13274 my_free(const_cast<uchar *>(encoded_snapshot_version));
13275 encoded_snapshot_version = nullptr;
13276 delete snapshot_version;
13277 delete sid_map;
13278 }
13279
to_string(char * buf,ulong len) const13280 size_t Transaction_context_log_event::to_string(char *buf, ulong len) const {
13281 DBUG_TRACE;
13282 return snprintf(buf, len, "server_uuid=%s\tthread_id=%u", server_uuid,
13283 thread_id);
13284 }
13285
13286 #ifdef MYSQL_SERVER
pack_info(Protocol * protocol)13287 int Transaction_context_log_event::pack_info(Protocol *protocol) {
13288 DBUG_TRACE;
13289 char buf[256];
13290 size_t bytes = to_string(buf, 256);
13291 protocol->store_string(buf, bytes, &my_charset_bin);
13292 return 0;
13293 }
13294 #endif
13295
13296 #ifndef MYSQL_SERVER
print(FILE *,PRINT_EVENT_INFO * print_event_info) const13297 void Transaction_context_log_event::print(
13298 FILE *, PRINT_EVENT_INFO *print_event_info) const {
13299 DBUG_TRACE;
13300 char buf[256];
13301 IO_CACHE *const head = &print_event_info->head_cache;
13302
13303 if (!print_event_info->short_form) {
13304 to_string(buf, 256);
13305 print_header(head, print_event_info, false);
13306 my_b_printf(head, "Transaction_context: %s\n", buf);
13307 }
13308 }
13309 #endif
13310
13311 #if defined(MYSQL_SERVER)
do_update_pos(Relay_log_info * rli)13312 int Transaction_context_log_event::do_update_pos(Relay_log_info *rli) {
13313 DBUG_TRACE;
13314 rli->inc_event_relay_log_pos();
13315 return 0;
13316 }
13317 #endif
13318
get_data_size()13319 size_t Transaction_context_log_event::get_data_size() {
13320 DBUG_TRACE;
13321
13322 size_t size = Binary_log_event::TRANSACTION_CONTEXT_HEADER_LEN;
13323 size += strlen(server_uuid);
13324 size += get_snapshot_version_size();
13325 size += get_data_set_size(&write_set);
13326 size += get_data_set_size(&read_set);
13327
13328 return size;
13329 }
13330
13331 #ifdef MYSQL_SERVER
write_data_header(Basic_ostream * ostream)13332 bool Transaction_context_log_event::write_data_header(Basic_ostream *ostream) {
13333 DBUG_TRACE;
13334 char buf[Binary_log_event::TRANSACTION_CONTEXT_HEADER_LEN];
13335
13336 buf[ENCODED_SERVER_UUID_LEN_OFFSET] = (char)strlen(server_uuid);
13337 int4store(buf + ENCODED_THREAD_ID_OFFSET, thread_id);
13338 buf[ENCODED_GTID_SPECIFIED_OFFSET] = gtid_specified;
13339 int4store(buf + ENCODED_SNAPSHOT_VERSION_LEN_OFFSET,
13340 get_snapshot_version_size());
13341 int4store(buf + ENCODED_WRITE_SET_ITEMS_OFFSET, write_set.size());
13342 int4store(buf + ENCODED_READ_SET_ITEMS_OFFSET, read_set.size());
13343 return wrapper_my_b_safe_write(
13344 ostream, (const uchar *)buf,
13345 Binary_log_event::TRANSACTION_CONTEXT_HEADER_LEN);
13346 }
13347
write_data_body(Basic_ostream * ostream)13348 bool Transaction_context_log_event::write_data_body(Basic_ostream *ostream) {
13349 DBUG_TRACE;
13350
13351 if (wrapper_my_b_safe_write(ostream, (const uchar *)server_uuid,
13352 strlen(server_uuid)) ||
13353 write_snapshot_version(ostream) || write_data_set(ostream, &write_set) ||
13354 write_data_set(ostream, &read_set))
13355 return true;
13356
13357 return false;
13358 }
13359
write_snapshot_version(Basic_ostream * ostream)13360 bool Transaction_context_log_event::write_snapshot_version(
13361 Basic_ostream *ostream) {
13362 DBUG_TRACE;
13363 bool result = false;
13364
13365 uint32 len = get_snapshot_version_size();
13366 uchar *buffer = (uchar *)my_malloc(key_memory_log_event, len, MYF(MY_WME));
13367 if (buffer == nullptr) return true;
13368
13369 snapshot_version->encode(buffer);
13370 if (wrapper_my_b_safe_write(ostream, buffer, len)) result = true;
13371
13372 my_free(buffer);
13373 return result;
13374 }
13375
write_data_set(Basic_ostream * ostream,std::list<const char * > * set)13376 bool Transaction_context_log_event::write_data_set(
13377 Basic_ostream *ostream, std::list<const char *> *set) {
13378 DBUG_TRACE;
13379 for (std::list<const char *>::iterator it = set->begin(); it != set->end();
13380 ++it) {
13381 char buf[ENCODED_READ_WRITE_SET_ITEM_LEN];
13382 const char *hash = *it;
13383 uint16 len = strlen(hash);
13384
13385 int2store(buf, len);
13386 if (wrapper_my_b_safe_write(ostream, (const uchar *)buf,
13387 ENCODED_READ_WRITE_SET_ITEM_LEN) ||
13388 wrapper_my_b_safe_write(ostream, (const uchar *)hash, len))
13389 return true;
13390 }
13391
13392 return false;
13393 }
13394 #endif
13395
read_snapshot_version()13396 bool Transaction_context_log_event::read_snapshot_version() {
13397 DBUG_TRACE;
13398 DBUG_ASSERT(snapshot_version->is_empty());
13399
13400 global_sid_lock->wrlock();
13401 enum_return_status return_status = global_sid_map->copy(sid_map);
13402 global_sid_lock->unlock();
13403 if (return_status != RETURN_STATUS_OK) return true;
13404
13405 return snapshot_version->add_gtid_encoding(encoded_snapshot_version,
13406 encoded_snapshot_version_length) !=
13407 RETURN_STATUS_OK;
13408 }
13409
get_snapshot_version_size()13410 size_t Transaction_context_log_event::get_snapshot_version_size() {
13411 DBUG_TRACE;
13412 size_t result = snapshot_version->get_encoded_length();
13413 return result;
13414 }
13415
get_data_set_size(std::list<const char * > * set)13416 int Transaction_context_log_event::get_data_set_size(
13417 std::list<const char *> *set) {
13418 DBUG_TRACE;
13419 int size = 0;
13420
13421 for (std::list<const char *>::iterator it = set->begin(); it != set->end();
13422 ++it)
13423 size += ENCODED_READ_WRITE_SET_ITEM_LEN + strlen(*it);
13424
13425 return size;
13426 }
13427
add_write_set(const char * hash)13428 void Transaction_context_log_event::add_write_set(const char *hash) {
13429 DBUG_TRACE;
13430 write_set.push_back(hash);
13431 }
13432
add_read_set(const char * hash)13433 void Transaction_context_log_event::add_read_set(const char *hash) {
13434 DBUG_TRACE;
13435 read_set.push_back(hash);
13436 }
13437
13438 /**************************************************************************
13439 View_change_log_event methods
13440 **************************************************************************/
13441
13442 #ifdef MYSQL_SERVER
View_change_log_event(const char * raw_view_id)13443 View_change_log_event::View_change_log_event(const char *raw_view_id)
13444 : binary_log::View_change_event(raw_view_id),
13445 Log_event(header(), footer(), Log_event::EVENT_TRANSACTIONAL_CACHE,
13446 Log_event::EVENT_NORMAL_LOGGING) {
13447 DBUG_TRACE;
13448 common_header->flags |= LOG_EVENT_IGNORABLE_F;
13449
13450 common_header->set_is_valid(strlen(view_id) != 0);
13451 }
13452 #endif
13453
View_change_log_event(const char * buffer,const Format_description_event * descr_event)13454 View_change_log_event::View_change_log_event(
13455 const char *buffer, const Format_description_event *descr_event)
13456 : binary_log::View_change_event(buffer, descr_event),
13457 Log_event(header(), footer()) {
13458 DBUG_TRACE;
13459 if (!is_valid()) return;
13460 common_header->flags |= LOG_EVENT_IGNORABLE_F;
13461
13462 // Change the cache/logging types to allow writing to the binary log cache
13463 event_cache_type = EVENT_TRANSACTIONAL_CACHE;
13464 event_logging_type = EVENT_NORMAL_LOGGING;
13465 }
13466
~View_change_log_event()13467 View_change_log_event::~View_change_log_event() {
13468 DBUG_TRACE;
13469 certification_info.clear();
13470 }
13471
get_data_size()13472 size_t View_change_log_event::get_data_size() {
13473 DBUG_TRACE;
13474
13475 size_t size = Binary_log_event::VIEW_CHANGE_HEADER_LEN;
13476 size += get_size_data_map(&certification_info);
13477
13478 return size;
13479 }
13480
get_size_data_map(std::map<std::string,std::string> * map)13481 size_t View_change_log_event::get_size_data_map(
13482 std::map<std::string, std::string> *map) {
13483 DBUG_TRACE;
13484 size_t size = 0;
13485
13486 std::map<std::string, std::string>::iterator iter;
13487 size += (ENCODED_CERT_INFO_KEY_SIZE_LEN + ENCODED_CERT_INFO_VALUE_LEN) *
13488 map->size();
13489 for (iter = map->begin(); iter != map->end(); iter++)
13490 size += iter->first.length() + iter->second.length();
13491
13492 return size;
13493 }
13494
to_string(char * buf,ulong len) const13495 size_t View_change_log_event::to_string(char *buf, ulong len) const {
13496 DBUG_TRACE;
13497 return snprintf(buf, len, "view_id=%s", view_id);
13498 }
13499
13500 #ifdef MYSQL_SERVER
pack_info(Protocol * protocol)13501 int View_change_log_event::pack_info(Protocol *protocol) {
13502 DBUG_TRACE;
13503 char buf[256];
13504 size_t bytes = to_string(buf, 256);
13505 protocol->store_string(buf, bytes, &my_charset_bin);
13506 return 0;
13507 }
13508 #endif
13509
13510 #ifndef MYSQL_SERVER
print(FILE *,PRINT_EVENT_INFO * print_event_info) const13511 void View_change_log_event::print(FILE *,
13512 PRINT_EVENT_INFO *print_event_info) const {
13513 DBUG_TRACE;
13514 char buf[256];
13515 IO_CACHE *const head = &print_event_info->head_cache;
13516
13517 if (!print_event_info->short_form) {
13518 to_string(buf, 256);
13519 print_header(head, print_event_info, false);
13520 my_b_printf(head, "View_change_log_event: %s\n", buf);
13521 }
13522 }
13523 #endif
13524
13525 #if defined(MYSQL_SERVER)
13526
do_apply_event(Relay_log_info const * rli)13527 int View_change_log_event::do_apply_event(Relay_log_info const *rli) {
13528 enum_gtid_statement_status state = gtid_pre_statement_checks(thd);
13529 if (state == GTID_STATEMENT_SKIP) return 0;
13530
13531 if (state == GTID_STATEMENT_CANCEL ||
13532 (state == GTID_STATEMENT_EXECUTE &&
13533 gtid_pre_statement_post_implicit_commit_checks(thd))) {
13534 uint error = thd->get_stmt_da()->mysql_errno();
13535 DBUG_ASSERT(error != 0);
13536 rli->report(ERROR_LEVEL, error, "Error executing View Change event: '%s'",
13537 thd->get_stmt_da()->message_text());
13538 thd->is_slave_error = true;
13539 return -1;
13540 }
13541
13542 if (!opt_bin_log) {
13543 return 0;
13544 }
13545
13546 /*
13547 The view change is going to be written directly into the binary log and
13548 its "data_written" field may change depending on local binlog-checksum
13549 settings.
13550
13551 As MTS keep track of the size of the events on its queue relying on events
13552 header data_written field, we must ensure that it should not change on the
13553 event instance in memory (by backing it up before writing into binary log
13554 and restoring it after it was written).
13555 */
13556 size_t original_ev_data_written = common_header->data_written;
13557 int error = mysql_bin_log.write_event(this);
13558 if (original_ev_data_written)
13559 common_header->data_written = original_ev_data_written;
13560 if (error)
13561 rli->report(ERROR_LEVEL, ER_SLAVE_FATAL_ERROR,
13562 ER_THD(thd, ER_SLAVE_FATAL_ERROR),
13563 "Could not write the VIEW CHANGE event in the binary log.");
13564
13565 return (error);
13566 }
13567
do_update_pos(Relay_log_info * rli)13568 int View_change_log_event::do_update_pos(Relay_log_info *rli) {
13569 DBUG_TRACE;
13570 rli->inc_event_relay_log_pos();
13571 return 0;
13572 }
13573
write_data_header(Basic_ostream * ostream)13574 bool View_change_log_event::write_data_header(Basic_ostream *ostream) {
13575 DBUG_TRACE;
13576 char buf[Binary_log_event::VIEW_CHANGE_HEADER_LEN];
13577
13578 memcpy(buf, view_id, ENCODED_VIEW_ID_MAX_LEN);
13579 int8store(buf + ENCODED_SEQ_NUMBER_OFFSET, seq_number);
13580 int4store(buf + ENCODED_CERT_INFO_SIZE_OFFSET, certification_info.size());
13581 return wrapper_my_b_safe_write(ostream, (const uchar *)buf,
13582 Binary_log_event::VIEW_CHANGE_HEADER_LEN);
13583 }
13584
write_data_body(Basic_ostream * ostream)13585 bool View_change_log_event::write_data_body(Basic_ostream *ostream) {
13586 DBUG_TRACE;
13587
13588 if (write_data_map(ostream, &certification_info)) return true;
13589
13590 return false;
13591 }
13592
write_data_map(Basic_ostream * ostream,std::map<std::string,std::string> * map)13593 bool View_change_log_event::write_data_map(
13594 Basic_ostream *ostream, std::map<std::string, std::string> *map) {
13595 DBUG_TRACE;
13596 bool result = false;
13597
13598 std::map<std::string, std::string>::iterator iter;
13599 for (iter = map->begin(); iter != map->end(); iter++) {
13600 uchar buf_key_len[ENCODED_CERT_INFO_KEY_SIZE_LEN];
13601 uint16 key_len = iter->first.length();
13602 int2store(buf_key_len, key_len);
13603
13604 const char *key = iter->first.c_str();
13605
13606 uchar buf_value_len[ENCODED_CERT_INFO_VALUE_LEN];
13607 uint32 value_len = iter->second.length();
13608 int4store(buf_value_len, value_len);
13609
13610 const char *value = iter->second.c_str();
13611
13612 if (wrapper_my_b_safe_write(ostream, buf_key_len,
13613 ENCODED_CERT_INFO_KEY_SIZE_LEN) ||
13614 wrapper_my_b_safe_write(ostream, (const uchar *)key, key_len) ||
13615 wrapper_my_b_safe_write(ostream, buf_value_len,
13616 ENCODED_CERT_INFO_VALUE_LEN) ||
13617 wrapper_my_b_safe_write(ostream, (const uchar *)value, value_len))
13618 return result;
13619 }
13620
13621 return false;
13622 }
13623
13624 #endif // MYSQL_SERVER
13625
13626 /*
13627 Updates the certification info map.
13628 */
set_certification_info(std::map<std::string,std::string> * info,size_t * event_size)13629 void View_change_log_event::set_certification_info(
13630 std::map<std::string, std::string> *info, size_t *event_size) {
13631 DBUG_TRACE;
13632 certification_info.clear();
13633
13634 *event_size = Binary_log_event::VIEW_CHANGE_HEADER_LEN;
13635 std::map<std::string, std::string>::iterator it;
13636 for (it = info->begin(); it != info->end(); ++it) {
13637 std::string key = it->first;
13638 std::string value = it->second;
13639 certification_info[key] = value;
13640 *event_size += it->first.length() + it->second.length();
13641 }
13642 *event_size +=
13643 (ENCODED_CERT_INFO_KEY_SIZE_LEN + ENCODED_CERT_INFO_VALUE_LEN) *
13644 certification_info.size();
13645 }
13646
get_data_size()13647 size_t Transaction_payload_log_event::get_data_size() {
13648 /* purecov: begin inspected */
13649 DBUG_TRACE;
13650 DBUG_ASSERT(false);
13651 return 0;
13652 /* purecov: end */
13653 }
13654
13655 #ifdef MYSQL_SERVER
get_mts_dbs(Mts_db_names * arg,Rpl_filter * rpl_filter MY_ATTRIBUTE ((unused)))13656 uint8 Transaction_payload_log_event::get_mts_dbs(
13657 Mts_db_names *arg, Rpl_filter *rpl_filter MY_ATTRIBUTE((unused))) {
13658 Mts_db_names &mts_dbs = m_applier_ctx.get_mts_db_names();
13659 if (mts_dbs.num == OVER_MAX_DBS_IN_EVENT_MTS) {
13660 arg->name[0] = 0;
13661 arg->num = OVER_MAX_DBS_IN_EVENT_MTS;
13662 } else {
13663 for (int i = 0; i < mts_dbs.num; i++) arg->name[i] = mts_dbs.name[i];
13664 arg->num = mts_dbs.num;
13665 }
13666
13667 return arg->num;
13668 }
13669
set_mts_dbs(Mts_db_names & arg)13670 void Transaction_payload_log_event::set_mts_dbs(Mts_db_names &arg) {
13671 m_applier_ctx.reset();
13672 Mts_db_names &mts_dbs = m_applier_ctx.get_mts_db_names();
13673 mts_dbs.num = arg.num;
13674 if (mts_dbs.num < MAX_DBS_IN_EVENT_MTS) {
13675 for (int i = 0; i < arg.num; i++)
13676 // strndup already adds the string terminator
13677 mts_dbs.name[i] = strndup(arg.name[i], NAME_LEN);
13678 }
13679 #ifndef DBUG_OFF
13680 else
13681 DBUG_ASSERT(mts_dbs.num == OVER_MAX_DBS_IN_EVENT_MTS);
13682 #endif
13683 }
13684
mts_number_dbs()13685 uint8 Transaction_payload_log_event::mts_number_dbs() {
13686 return m_applier_ctx.get_mts_db_names().num;
13687 }
13688
do_apply_event(Relay_log_info const * rli)13689 int Transaction_payload_log_event::do_apply_event(Relay_log_info const *rli) {
13690 DBUG_TRACE;
13691 int res = 0;
13692 PSI_stage_info old_stage;
13693
13694 /* apply events in the payload */
13695
13696 binary_log::transaction::compression::Iterable_buffer it(
13697 m_payload, m_payload_size, m_uncompressed_size, m_compression_type);
13698
13699 thd->enter_stage(&stage_binlog_transaction_decompress, &old_stage, __func__,
13700 __FILE__, __LINE__);
13701 for (auto ptr : it) {
13702 THD_STAGE_INFO(thd, old_stage);
13703 if ((res = apply_payload_event(rli, (const uchar *)ptr))) break;
13704 thd->enter_stage(&stage_binlog_transaction_decompress, &old_stage, __func__,
13705 __FILE__, __LINE__);
13706 }
13707 THD_STAGE_INFO(thd, old_stage);
13708
13709 return res;
13710 }
13711
shall_delete_event_after_apply(Log_event * ev)13712 static bool shall_delete_event_after_apply(Log_event *ev) {
13713 bool res = false;
13714 if (ev == nullptr) return res;
13715 switch (ev->get_type_code()) {
13716 case binary_log::FORMAT_DESCRIPTION_EVENT:
13717 /*
13718 Format_description_log_event should not be deleted because it will
13719 be used to read info about the relay log's format; it will be
13720 deleted when the SQL thread does not need it, i.e. when this
13721 thread terminates.
13722 */
13723
13724 /* fall through */
13725 case binary_log::ROWS_QUERY_LOG_EVENT:
13726 /*
13727 ROWS_QUERY_LOG_EVENT is destroyed at the end of the current statement
13728 clean-up routine.
13729 */
13730 res = false;
13731 break;
13732 default:
13733 DBUG_PRINT("info", ("Deleting the event after it has been executed"));
13734 res = true;
13735 break;
13736 }
13737
13738 return res;
13739 }
13740
apply_payload_event(Relay_log_info const * rli,const uchar * event_buf)13741 bool Transaction_payload_log_event::apply_payload_event(
13742 Relay_log_info const *rli, const uchar *event_buf) {
13743 DBUG_TRACE;
13744 bool res = false;
13745 const uchar *ptr = event_buf;
13746 Log_event *ev = nullptr;
13747 bool copied_buffer = false;
13748 uchar *copy_buffer = nullptr;
13749
13750 /*
13751 disable checksums - there are no checksums for events inside the tple
13752 otherwise, the last 4 bytes would be truncated.
13753
13754 We do this by copying the fdle from the rli. Then we disable the checksum
13755 in the copy. Then we use it to decode the events in the payload instead
13756 of the original fdle.
13757
13758 We allocate the fdle copy in the stack.
13759
13760 TODO: simplify this by breaking the binlog_event_deserialize API
13761 and make it take a single boolean instead that states whether the
13762 event has a checksum in it or not.
13763 */
13764 Format_description_event *fde = rli->get_rli_description_event();
13765 Format_description_log_event fdle(fde->reader().buffer(), fde);
13766 fdle.footer()->checksum_alg = binary_log::BINLOG_CHECKSUM_ALG_OFF;
13767 fdle.register_temp_buf(const_cast<char *>(fde->reader().buffer()), false);
13768 size_t event_len = uint4korr(ptr + EVENT_LEN_OFFSET);
13769 if (binlog_event_deserialize(ptr, event_len, &fdle, true, &ev)) {
13770 res = true;
13771 goto end;
13772 }
13773
13774 if (!shall_delete_event_after_apply(ev)) {
13775 copy_buffer =
13776 (uchar *)my_malloc(key_memory_log_event, event_len, MYF(MY_WME));
13777 memcpy(copy_buffer, ptr, event_len);
13778 copied_buffer = true;
13779 } else {
13780 copy_buffer = const_cast<uchar *>(ptr);
13781 copied_buffer = false;
13782 }
13783
13784 ev->register_temp_buf((char *)copy_buffer, copied_buffer);
13785 ev->common_header->log_pos = header()->log_pos;
13786
13787 thd->server_id = ev->server_id; // use the original server id for logging
13788 thd->unmasked_server_id = ev->common_header->unmasked_server_id;
13789 thd->set_time(); // time the query
13790 thd->lex->set_current_select(0);
13791 if (!ev->common_header->when.tv_sec)
13792 my_micro_time_to_timeval(my_micro_time(), &ev->common_header->when);
13793 ev->thd = thd; // because up to this point, ev->thd == 0
13794
13795 // TODO: HATE THIS
13796 if (is_mts_worker(thd)) {
13797 auto worker =
13798 static_cast<Slave_worker *>(const_cast<Relay_log_info *>(rli));
13799 this->worker = worker;
13800
13801 // set in the event context
13802 ev->future_event_relay_log_pos = this->future_event_relay_log_pos;
13803 ev->mts_group_idx = mts_group_idx;
13804 ev->worker = worker;
13805
13806 // set in the worker context
13807 worker->set_future_event_relay_log_pos(ev->future_event_relay_log_pos);
13808 worker->set_master_log_pos(static_cast<ulong>(ev->common_header->log_pos));
13809 worker->set_gaq_index(ev->mts_group_idx);
13810
13811 if (ev->get_type_code() == binary_log::QUERY_EVENT)
13812 static_cast<Query_log_event *>(ev)
13813 ->set_skip_temp_tables_handling_by_worker();
13814 res = ev->do_apply_event_worker(worker);
13815 } else {
13816 auto coord = const_cast<Relay_log_info *>(rli);
13817 ev->future_event_relay_log_pos = coord->get_future_event_relay_log_pos();
13818 res = ev->apply_event(coord);
13819 }
13820
13821 if (shall_delete_event_after_apply(ev)) delete ev;
13822
13823 end:
13824 return res;
13825 }
13826
do_shall_skip(Relay_log_info * rli)13827 Log_event::enum_skip_reason Transaction_payload_log_event::do_shall_skip(
13828 Relay_log_info *rli) {
13829 return Log_event::continue_group(rli);
13830 }
13831
write(Basic_ostream * ostream)13832 bool Transaction_payload_log_event::write(Basic_ostream *ostream) {
13833 DBUG_TRACE;
13834 auto codec = binary_log::codecs::Factory::build_codec(header()->type_code);
13835 auto buffer_size = MAX_DATA_LENGTH + LOG_EVENT_HEADER_LEN;
13836 unsigned char buffer[MAX_DATA_LENGTH + LOG_EVENT_HEADER_LEN];
13837 auto result = codec->encode(*this, buffer, buffer_size);
13838 size_t data_size = result.first + m_payload_size;
13839
13840 if (result.second == true) goto end;
13841
13842 return write_header(ostream, data_size) ||
13843 wrapper_my_b_safe_write(ostream, (uchar *)buffer, result.first) ||
13844 wrapper_my_b_safe_write(ostream,
13845 reinterpret_cast<const uchar *>(m_payload),
13846 m_payload_size) ||
13847 write_footer(ostream);
13848 end:
13849 return true;
13850 }
13851
pack_info(Protocol * protocol)13852 int Transaction_payload_log_event::pack_info(Protocol *protocol) {
13853 std::ostringstream oss;
13854 oss << "compression='";
13855 oss << binary_log::transaction::compression::type_to_string(
13856 m_compression_type);
13857 oss << "', decompressed_size=";
13858 oss << m_uncompressed_size << " bytes";
13859 protocol->store(oss.str().c_str(), &my_charset_bin);
13860 return 0;
13861 }
13862
ends_group() const13863 bool Transaction_payload_log_event::ends_group() const { return true; }
13864
13865 #endif
13866
13867 #ifndef MYSQL_SERVER
13868 /**
13869 The default values for these variables should be values that are
13870 *incorrect*, i.e., values that cannot occur in an event. This way,
13871 they will always be printed for the first event.
13872 */
PRINT_EVENT_INFO()13873 PRINT_EVENT_INFO::PRINT_EVENT_INFO()
13874 : flags2_inited(false),
13875 sql_mode_inited(false),
13876 sql_mode(0),
13877 auto_increment_increment(0),
13878 auto_increment_offset(0),
13879 charset_inited(false),
13880 lc_time_names_number(~0),
13881 charset_database_number(ILLEGAL_CHARSET_INFO_NUMBER),
13882 default_collation_for_utf8mb4_number(ILLEGAL_CHARSET_INFO_NUMBER),
13883 sql_require_primary_key(0xff),
13884 thread_id(0),
13885 thread_id_printed(false),
13886 default_table_encryption(0xff),
13887 base64_output_mode(BASE64_OUTPUT_UNSPEC),
13888 printed_fd_event(false),
13889 have_unflushed_events(false),
13890 skipped_event_in_transaction(false) {
13891 /*
13892 Currently we only use static PRINT_EVENT_INFO objects, so zeroed at
13893 program's startup, but these explicit memset() is for the day someone
13894 creates dynamic instances.
13895 */
13896 memset(db, 0, sizeof(db));
13897 memset(charset, 0, sizeof(charset));
13898 memset(time_zone_str, 0, sizeof(time_zone_str));
13899 delimiter[0] = ';';
13900 delimiter[1] = 0;
13901 myf const flags = MYF(MY_WME | MY_NABP);
13902 open_cached_file(&head_cache, nullptr, nullptr, 0, flags);
13903 open_cached_file(&body_cache, nullptr, nullptr, 0, flags);
13904 open_cached_file(&footer_cache, nullptr, nullptr, 0, flags);
13905 }
13906 #endif
13907
13908 #if defined(MYSQL_SERVER)
Heartbeat_log_event(const char * buf,const Format_description_event * description_event)13909 Heartbeat_log_event::Heartbeat_log_event(
13910 const char *buf, const Format_description_event *description_event)
13911 : binary_log::Heartbeat_event(buf, description_event),
13912 Log_event(header(), footer()) {
13913 DBUG_TRACE;
13914 }
13915 #endif
13916
13917 #ifdef MYSQL_SERVER
13918 /*
13919 This is a utility function that adds a quoted identifier into the a buffer.
13920 This also escapes any existance of the quote string inside the identifier.
13921
13922 SYNOPSIS
13923 my_strmov_quoted_identifier
13924 thd thread handler
13925 buffer target buffer
13926 identifier the identifier to be quoted
13927 length length of the identifier
13928 */
my_strmov_quoted_identifier(THD * thd,char * buffer,const char * identifier,size_t length)13929 size_t my_strmov_quoted_identifier(THD *thd, char *buffer,
13930 const char *identifier, size_t length) {
13931 int q = thd ? get_quote_char_for_identifier(thd, identifier, length) : '`';
13932 return my_strmov_quoted_identifier_helper(q, buffer, identifier, length);
13933 }
13934 #else
my_strmov_quoted_identifier(char * buffer,const char * identifier)13935 size_t my_strmov_quoted_identifier(char *buffer, const char *identifier) {
13936 int q = '`';
13937 return my_strmov_quoted_identifier_helper(q, buffer, identifier, 0);
13938 }
13939
13940 #endif
13941
my_strmov_quoted_identifier_helper(int q,char * buffer,const char * identifier,size_t length)13942 size_t my_strmov_quoted_identifier_helper(int q, char *buffer,
13943 const char *identifier,
13944 size_t length) {
13945 size_t written = 0;
13946 char quote_char;
13947 size_t id_length = (length) ? length : strlen(identifier);
13948
13949 if (q == EOF) {
13950 (void)strncpy(buffer, identifier, id_length);
13951 return id_length;
13952 }
13953 quote_char = (char)q;
13954 *buffer++ = quote_char;
13955 written++;
13956 while (id_length--) {
13957 if (*identifier == quote_char) {
13958 *buffer++ = quote_char;
13959 written++;
13960 }
13961 *buffer++ = *identifier++;
13962 written++;
13963 }
13964 *buffer++ = quote_char;
13965 return ++written;
13966 }
13967
extract_log_event_basic_info(Log_event * log_event)13968 std::pair<bool, binary_log::Log_event_basic_info> extract_log_event_basic_info(
13969 Log_event *log_event) {
13970 DBUG_TRACE;
13971
13972 binary_log::Log_event_basic_info event_info;
13973 event_info.query_length = 0;
13974 event_info.event_type = log_event->get_type_code();
13975
13976 if (binary_log::QUERY_EVENT == event_info.event_type) {
13977 Query_log_event *qlog_event = static_cast<Query_log_event *>(log_event);
13978 event_info.query = qlog_event->query;
13979 if (event_info.query != nullptr)
13980 event_info.query_length = strlen(event_info.query);
13981 if (event_info.query_length == 0) {
13982 DBUG_ASSERT(event_info.query == nullptr); /* purecov: inspected */
13983 return std::make_pair(true, event_info); /* purecov: inspected */
13984 }
13985 }
13986 event_info.ignorable_event = log_event->is_ignorable_event();
13987 return std::make_pair(false, event_info);
13988 }
13989
extract_log_event_basic_info(const char * buf,size_t length,const binary_log::Format_description_event * fd_event)13990 std::pair<bool, binary_log::Log_event_basic_info> extract_log_event_basic_info(
13991 const char *buf, size_t length,
13992 const binary_log::Format_description_event *fd_event) {
13993 DBUG_TRACE;
13994
13995 binary_log::Log_event_basic_info event_info;
13996 event_info.query_length = 0;
13997
13998 uint header_size = fd_event->common_header_len;
13999 const char *query = nullptr;
14000
14001 /* Error if the event content is smaller than header size for the format */
14002 if (length < header_size) return std::make_pair(true, event_info);
14003
14004 event_info.event_type = (Log_event_type)buf[EVENT_TYPE_OFFSET];
14005
14006 if (binary_log::QUERY_EVENT == event_info.event_type) {
14007 event_info.query_length =
14008 Query_log_event::get_query(buf, length, fd_event, &query);
14009 if (event_info.query_length == 0) {
14010 DBUG_ASSERT(query == nullptr); /* purecov: inspected */
14011 return std::make_pair(true, event_info); /* purecov: inspected */
14012 }
14013 event_info.query = query;
14014 }
14015 event_info.ignorable_event =
14016 uint2korr(buf + FLAGS_OFFSET) & LOG_EVENT_IGNORABLE_F;
14017 return std::make_pair(false, event_info);
14018 }
14019