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(&ltime, 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(&ltime, 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