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