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