1 /* Copyright (c) 2007, 2021, Oracle and/or its affiliates. 2 3 This program is free software; you can redistribute it and/or modify 4 it under the terms of the GNU General Public License, version 2.0, 5 as published by the Free Software Foundation. 6 7 This program is also distributed with certain software (including 8 but not limited to OpenSSL) that is licensed under separate terms, 9 as designated in a particular file or component or in included license 10 documentation. The authors of MySQL hereby grant you an additional 11 permission to link the program and your derivative works with the 12 separately licensed software that they have included with MySQL. 13 14 This program is distributed in the hope that it will be useful, 15 but WITHOUT ANY WARRANTY; without even the implied warranty of 16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 GNU General Public License, version 2.0, for more details. 18 19 You should have received a copy of the GNU General Public License 20 along with this program; if not, write to the Free Software 21 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ 22 23 #ifndef LOG_EVENT_OLD_H 24 #define LOG_EVENT_OLD_H 25 26 /* 27 Need to include this file at the proper position of log_event.h 28 */ 29 30 31 /** 32 @file 33 34 @brief This file contains classes handling old formats of row-based 35 binlog events. 36 */ 37 /* 38 Around 2007-10-31, I made these classes completely separated from 39 the new classes (before, there was a complex class hierarchy 40 involving multiple inheritance; see BUG#31581), by simply copying 41 and pasting the entire contents of Rows_log_event into 42 Old_rows_log_event and the entire contents of 43 {Write|Update|Delete}_rows_log_event into 44 {Write|Update|Delete}_rows_log_event_old. For clarity, I will keep 45 the comments marking which code was cut-and-pasted for some time. 46 With the classes collapsed into one, there is probably some 47 redundancy (maybe some methods can be simplified and/or removed), 48 but we keep them this way for now. /Sven 49 */ 50 51 /* These classes are based on the v1 RowsHeaderLen */ 52 #define ROWS_HEADER_LEN ROWS_HEADER_LEN_V1 53 54 /** 55 @class Old_rows_log_event 56 57 Base class for the three types of row-based events 58 {Write|Update|Delete}_row_log_event_old, with event type codes 59 PRE_GA_{WRITE|UPDATE|DELETE}_ROWS_EVENT. These events are never 60 created any more, except when reading a relay log created by an old 61 server. 62 */ 63 class Old_rows_log_event : public Binary_log_event, public Log_event 64 { 65 /********** BEGIN CUT & PASTE FROM Rows_log_event **********/ 66 public: 67 /** 68 Enumeration of the errors that can be returned. 69 */ 70 enum enum_error 71 { 72 ERR_OPEN_FAILURE = -1, /**< Failure to open table */ 73 ERR_OK = 0, /**< No error */ 74 ERR_TABLE_LIMIT_EXCEEDED = 1, /**< No more room for tables */ 75 ERR_OUT_OF_MEM = 2, /**< Out of memory */ 76 ERR_BAD_TABLE_DEF = 3, /**< Table definition does not match */ 77 ERR_RBR_TO_SBR = 4 /**< daisy-chanining RBR to SBR not allowed */ 78 }; 79 80 /* 81 These definitions allow you to combine the flags into an 82 appropriate flag set using the normal bitwise operators. The 83 implicit conversion from an enum-constant to an integer is 84 accepted by the compiler, which is then used to set the real set 85 of flags. 86 */ 87 enum enum_flag 88 { 89 /* Last event of a statement */ 90 STMT_END_F = (1U << 0), 91 92 /* Value of the OPTION_NO_FOREIGN_KEY_CHECKS flag in thd->options */ 93 NO_FOREIGN_KEY_CHECKS_F = (1U << 1), 94 95 /* Value of the OPTION_RELAXED_UNIQUE_CHECKS flag in thd->options */ 96 RELAXED_UNIQUE_CHECKS_F = (1U << 2), 97 98 /** 99 Indicates that rows in this event are complete, that is contain 100 values for all columns of the table. 101 */ 102 COMPLETE_ROWS_F = (1U << 3) 103 }; 104 105 typedef uint16 flag_set; 106 107 /* Special constants representing sets of flags */ 108 enum 109 { 110 RLE_NO_FLAGS = 0U 111 }; 112 113 virtual ~Old_rows_log_event(); 114 set_flags(flag_set flags_arg)115 void set_flags(flag_set flags_arg) { m_flags |= flags_arg; } clear_flags(flag_set flags_arg)116 void clear_flags(flag_set flags_arg) { m_flags &= ~flags_arg; } get_flags(flag_set flags_arg)117 flag_set get_flags(flag_set flags_arg) const { return m_flags & flags_arg; } 118 119 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) 120 virtual int pack_info(Protocol *protocol); 121 #endif 122 123 #ifdef MYSQL_CLIENT 124 /* not for direct call, each derived has its own ::print() */ 125 virtual void print(FILE *file, PRINT_EVENT_INFO *print_event_info)= 0; 126 #endif 127 128 #ifndef MYSQL_CLIENT add_row_data(uchar * data,size_t length)129 int add_row_data(uchar *data, size_t length) 130 { 131 return do_add_row_data(data,length); 132 } 133 #endif 134 135 /* Member functions to implement superclass interface */ 136 virtual size_t get_data_size(); 137 get_cols()138 MY_BITMAP const *get_cols() const { return &m_cols; } get_width()139 size_t get_width() const { return m_width; } get_table_id()140 const Table_id& get_table_id() const { return m_table_id; } 141 142 #ifndef MYSQL_CLIENT 143 virtual bool write_data_header(IO_CACHE *file); 144 virtual bool write_data_body(IO_CACHE *file); get_db()145 virtual const char *get_db() { return m_table->s->db.str; } 146 #endif 147 /* 148 Check that malloc() succeeded in allocating memory for the rows 149 buffer and the COLS vector. Checking that an Update_rows_log_event_old 150 is valid is done in the Update_rows_log_event_old::is_valid() 151 function. 152 */ is_valid()153 virtual bool is_valid() const 154 { 155 return m_rows_buf && m_cols.bitmap; 156 } 157 158 uint m_row_count; /* The number of rows added to the event */ 159 160 protected: 161 /* 162 The constructors are protected since you're supposed to inherit 163 this class, not create instances of this class. 164 */ 165 #ifndef MYSQL_CLIENT 166 Old_rows_log_event(THD*, TABLE*, ulong table_id, 167 MY_BITMAP const *cols, bool is_transactional); 168 #endif 169 Old_rows_log_event(const char *row_data, uint event_len, 170 Log_event_type event_type, 171 const Format_description_event *description_event); 172 173 #ifdef MYSQL_CLIENT 174 void print_helper(FILE *, PRINT_EVENT_INFO *, char const *const name); 175 #endif 176 177 #ifndef MYSQL_CLIENT 178 virtual int do_add_row_data(uchar *data, size_t length); 179 #endif 180 181 #ifndef MYSQL_CLIENT 182 TABLE *m_table; /* The table the rows belong to */ 183 #endif 184 Table_id m_table_id; /* Table ID */ 185 MY_BITMAP m_cols; /* Bitmap denoting columns available */ 186 ulong m_width; /* The width of the columns bitmap */ 187 188 ulong m_master_reclength; /* Length of record on master side */ 189 190 /* Bit buffers in the same memory as the class */ 191 uint32 m_bitbuf[128/(sizeof(uint32)*8)]; 192 uint32 m_bitbuf_ai[128/(sizeof(uint32)*8)]; 193 194 uchar *m_rows_buf; /* The rows in packed format */ 195 uchar *m_rows_cur; /* One-after the end of the data */ 196 uchar *m_rows_end; /* One-after the end of the allocated space */ 197 198 flag_set m_flags; /* Flags for row-level events */ 199 200 /* helper functions */ 201 202 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) 203 const uchar *m_curr_row; /* Start of the row being processed */ 204 const uchar *m_curr_row_end; /* One-after the end of the current row */ 205 uchar *m_key; /* Buffer to keep key value during searches */ 206 207 int find_row(const Relay_log_info *const); 208 int write_row(const Relay_log_info *const, const bool); 209 210 // Unpack the current row into m_table->record[0] unpack_current_row(const Relay_log_info * const rli)211 int unpack_current_row(const Relay_log_info *const rli) 212 { 213 assert(m_table); 214 ASSERT_OR_RETURN_ERROR(m_curr_row < m_rows_end, HA_ERR_CORRUPT_EVENT); 215 return ::unpack_row(rli, m_table, m_width, m_curr_row, &m_cols, 216 &m_curr_row_end, &m_master_reclength, m_rows_end); 217 } 218 #endif 219 220 private: 221 222 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) 223 virtual int do_apply_event(Relay_log_info const *rli); 224 virtual int do_update_pos(Relay_log_info *rli); 225 virtual enum_skip_reason do_shall_skip(Relay_log_info *rli); 226 227 /* 228 Primitive to prepare for a sequence of row executions. 229 230 DESCRIPTION 231 232 Before doing a sequence of do_prepare_row() and do_exec_row() 233 calls, this member function should be called to prepare for the 234 entire sequence. Typically, this member function will allocate 235 space for any buffers that are needed for the two member 236 functions mentioned above. 237 238 RETURN VALUE 239 240 The member function will return 0 if all went OK, or a non-zero 241 error code otherwise. 242 */ 243 virtual 244 int do_before_row_operations(const Slave_reporting_capability *const log) = 0; 245 246 /* 247 Primitive to clean up after a sequence of row executions. 248 249 DESCRIPTION 250 251 After doing a sequence of do_prepare_row() and do_exec_row(), 252 this member function should be called to clean up and release 253 any allocated buffers. 254 255 The error argument, if non-zero, indicates an error which happened during 256 row processing before this function was called. In this case, even if 257 function is successful, it should return the error code given in the argument. 258 */ 259 virtual 260 int do_after_row_operations(const Slave_reporting_capability *const log, 261 int error) = 0; 262 263 /* 264 Primitive to do the actual execution necessary for a row. 265 266 DESCRIPTION 267 The member function will do the actual execution needed to handle a row. 268 The row is located at m_curr_row. When the function returns, 269 m_curr_row_end should point at the next row (one byte after the end 270 of the current row). 271 272 RETURN VALUE 273 0 if execution succeeded, 1 if execution failed. 274 275 */ 276 virtual int do_exec_row(const Relay_log_info *const rli) = 0; 277 #endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */ 278 279 /********** END OF CUT & PASTE FROM Rows_log_event **********/ 280 protected: 281 282 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) 283 284 int do_apply_event(Old_rows_log_event*,const Relay_log_info*); 285 286 /* 287 Primitive to prepare for a sequence of row executions. 288 289 DESCRIPTION 290 291 Before doing a sequence of do_prepare_row() and do_exec_row() 292 calls, this member function should be called to prepare for the 293 entire sequence. Typically, this member function will allocate 294 space for any buffers that are needed for the two member 295 functions mentioned above. 296 297 RETURN VALUE 298 299 The member function will return 0 if all went OK, or a non-zero 300 error code otherwise. 301 */ 302 virtual int do_before_row_operations(TABLE *table) = 0; 303 304 /* 305 Primitive to clean up after a sequence of row executions. 306 307 DESCRIPTION 308 309 After doing a sequence of do_prepare_row() and do_exec_row(), 310 this member function should be called to clean up and release 311 any allocated buffers. 312 */ 313 virtual int do_after_row_operations(TABLE *table, int error) = 0; 314 315 /* 316 Primitive to prepare for handling one row in a row-level event. 317 318 DESCRIPTION 319 320 The member function prepares for execution of operations needed for one 321 row in a row-level event by reading up data from the buffer containing 322 the row. No specific interpretation of the data is normally done here, 323 since SQL thread specific data is not available: that data is made 324 available for the do_exec function. 325 326 A pointer to the start of the next row, or NULL if the preparation 327 failed. Currently, preparation cannot fail, but don't rely on this 328 behavior. 329 330 RETURN VALUE 331 Error code, if something went wrong, 0 otherwise. 332 */ 333 virtual int do_prepare_row(THD*, Relay_log_info const*, TABLE*, 334 uchar const *row_start, 335 uchar const **row_end) = 0; 336 337 /* 338 Primitive to do the actual execution necessary for a row. 339 340 DESCRIPTION 341 The member function will do the actual execution needed to handle a row. 342 343 RETURN VALUE 344 0 if execution succeeded, 1 if execution failed. 345 346 */ 347 virtual int do_exec_row(TABLE *table) = 0; 348 349 #endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */ 350 }; 351 352 353 /** 354 @class Write_rows_log_event_old 355 356 Old class for binlog events that write new rows to a table (event 357 type code PRE_GA_WRITE_ROWS_EVENT). Such events are never produced 358 by this version of the server, but they may be read from a relay log 359 created by an old server. New servers create events of class 360 Write_rows_log_event (event type code WRITE_ROWS_EVENT) instead. 361 */ 362 class Write_rows_log_event_old : public Old_rows_log_event 363 { 364 /********** BEGIN CUT & PASTE FROM Write_rows_log_event **********/ 365 public: 366 #if !defined(MYSQL_CLIENT) 367 Write_rows_log_event_old(THD*, TABLE*, ulong table_id, 368 MY_BITMAP const *cols, 369 bool is_transactional); 370 #endif 371 #ifdef HAVE_REPLICATION 372 Write_rows_log_event_old(const char *buf, uint event_len, 373 const Format_description_event *description_event); 374 #endif 375 #if !defined(MYSQL_CLIENT) binlog_row_logging_function(THD * thd,TABLE * table,bool is_transactional,const uchar * before_record MY_ATTRIBUTE ((unused)),const uchar * after_record)376 static bool binlog_row_logging_function(THD *thd, TABLE *table, 377 bool is_transactional, 378 const uchar *before_record 379 MY_ATTRIBUTE((unused)), 380 const uchar *after_record) 381 { 382 return thd->binlog_write_row(table, is_transactional, 383 after_record, NULL); 384 } 385 #endif 386 387 private: 388 #ifdef MYSQL_CLIENT 389 void print(FILE *file, PRINT_EVENT_INFO *print_event_info); 390 #endif 391 392 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) 393 virtual int do_before_row_operations(const Slave_reporting_capability *const); 394 virtual int do_after_row_operations(const Slave_reporting_capability *const,int); 395 virtual int do_exec_row(const Relay_log_info *const); 396 #endif 397 /********** END OF CUT & PASTE FROM Write_rows_log_event **********/ 398 399 public: 400 enum 401 { 402 /* Support interface to THD::binlog_prepare_pending_rows_event */ 403 TYPE_CODE = binary_log::PRE_GA_WRITE_ROWS_EVENT 404 }; 405 406 private: 407 408 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) 409 // use old definition of do_apply_event() do_apply_event(const Relay_log_info * rli)410 virtual int do_apply_event(const Relay_log_info *rli) 411 { return Old_rows_log_event::do_apply_event(this,rli); } 412 413 // primitives for old version of do_apply_event() 414 virtual int do_before_row_operations(TABLE *table); 415 virtual int do_after_row_operations(TABLE *table, int error); 416 virtual int do_prepare_row(THD*, Relay_log_info const*, TABLE*, 417 uchar const *row_start, uchar const **row_end); 418 virtual int do_exec_row(TABLE *table); 419 420 #endif 421 }; 422 423 424 /** 425 @class Update_rows_log_event_old 426 427 Old class for binlog events that modify existing rows to a table 428 (event type code PRE_GA_UPDATE_ROWS_EVENT). Such events are never 429 produced by this version of the server, but they may be read from a 430 relay log created by an old server. New servers create events of 431 class Update_rows_log_event (event type code UPDATE_ROWS_EVENT) 432 instead. 433 */ 434 class Update_rows_log_event_old : public Old_rows_log_event 435 { 436 /********** BEGIN CUT & PASTE FROM Update_rows_log_event **********/ 437 public: 438 #ifndef MYSQL_CLIENT 439 Update_rows_log_event_old(THD*, TABLE*, ulong table_id, 440 MY_BITMAP const *cols, 441 bool is_transactional); 442 #endif 443 444 #ifdef HAVE_REPLICATION 445 Update_rows_log_event_old(const char *buf, uint event_len, 446 const Format_description_event *description_event); 447 #endif 448 449 #if !defined(MYSQL_CLIENT) binlog_row_logging_function(THD * thd,TABLE * table,bool is_transactional,const uchar * before_record,const uchar * after_record)450 static bool binlog_row_logging_function(THD *thd, TABLE *table, 451 bool is_transactional, 452 const uchar *before_record, 453 const uchar *after_record) 454 { 455 return thd->binlog_update_row(table, is_transactional, 456 before_record, after_record, NULL); 457 } 458 #endif 459 460 protected: 461 #ifdef MYSQL_CLIENT 462 void print(FILE *file, PRINT_EVENT_INFO *print_event_info); 463 #endif 464 465 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) 466 virtual int do_before_row_operations(const Slave_reporting_capability *const); 467 virtual int do_after_row_operations(const Slave_reporting_capability *const,int); 468 virtual int do_exec_row(const Relay_log_info *const); 469 #endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */ 470 /********** END OF CUT & PASTE FROM Update_rows_log_event **********/ 471 472 uchar *m_after_image, *m_memory; 473 474 public: 475 enum 476 { 477 /* Support interface to THD::binlog_prepare_pending_rows_event */ 478 TYPE_CODE = binary_log::PRE_GA_UPDATE_ROWS_EVENT 479 }; 480 481 private: 482 483 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) 484 // use old definition of do_apply_event() do_apply_event(const Relay_log_info * rli)485 virtual int do_apply_event(const Relay_log_info *rli) 486 { return Old_rows_log_event::do_apply_event(this,rli); } 487 488 // primitives for old version of do_apply_event() 489 virtual int do_before_row_operations(TABLE *table); 490 virtual int do_after_row_operations(TABLE *table, int error); 491 virtual int do_prepare_row(THD*, Relay_log_info const*, TABLE*, 492 uchar const *row_start, uchar const **row_end); 493 virtual int do_exec_row(TABLE *table); 494 #endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */ 495 }; 496 497 498 /** 499 @class Delete_rows_log_event_old 500 501 Old class for binlog events that delete existing rows from a table 502 (event type code PRE_GA_DELETE_ROWS_EVENT). Such events are never 503 produced by this version of the server, but they may be read from a 504 relay log created by an old server. New servers create events of 505 class Delete_rows_log_event (event type code DELETE_ROWS_EVENT) 506 instead. 507 */ 508 class Delete_rows_log_event_old : public Old_rows_log_event 509 { 510 /********** BEGIN CUT & PASTE FROM Update_rows_log_event **********/ 511 public: 512 #ifndef MYSQL_CLIENT 513 Delete_rows_log_event_old(THD*, TABLE*, ulong, 514 MY_BITMAP const *cols, 515 bool is_transactional); 516 #endif 517 #ifdef HAVE_REPLICATION 518 Delete_rows_log_event_old(const char *buf, uint event_len, 519 const Format_description_event *description_event); 520 #endif 521 #if !defined(MYSQL_CLIENT) binlog_row_logging_function(THD * thd,TABLE * table,bool is_transactional,const uchar * before_record,const uchar * after_record MY_ATTRIBUTE ((unused)))522 static bool binlog_row_logging_function(THD *thd, TABLE *table, 523 bool is_transactional, 524 const uchar *before_record, 525 const uchar *after_record 526 MY_ATTRIBUTE((unused))) 527 { 528 return thd->binlog_delete_row(table, is_transactional, 529 before_record, NULL); 530 } 531 #endif 532 533 protected: 534 #ifdef MYSQL_CLIENT 535 void print(FILE *file, PRINT_EVENT_INFO *print_event_info); 536 #endif 537 538 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) 539 virtual int do_before_row_operations(const Slave_reporting_capability *const); 540 virtual int do_after_row_operations(const Slave_reporting_capability *const,int); 541 virtual int do_exec_row(const Relay_log_info *const); 542 #endif 543 /********** END CUT & PASTE FROM Delete_rows_log_event **********/ 544 545 uchar *m_after_image, *m_memory; 546 547 public: 548 enum 549 { 550 /* Support interface to THD::binlog_prepare_pending_rows_event */ 551 TYPE_CODE = binary_log::PRE_GA_DELETE_ROWS_EVENT 552 }; 553 554 private: 555 556 #if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) 557 // use old definition of do_apply_event() do_apply_event(const Relay_log_info * rli)558 virtual int do_apply_event(const Relay_log_info *rli) 559 { return Old_rows_log_event::do_apply_event(this,rli); } 560 561 // primitives for old version of do_apply_event() 562 virtual int do_before_row_operations(TABLE *table); 563 virtual int do_after_row_operations(TABLE *table, int error); 564 virtual int do_prepare_row(THD*, Relay_log_info const*, TABLE*, 565 uchar const *row_start, uchar const **row_end); 566 virtual int do_exec_row(TABLE *table); 567 #endif 568 }; 569 570 571 #endif 572