log_event.h 82 KB
Newer Older
unknown's avatar
unknown committed
1
/* Copyright (C) 2000-2006 MySQL AB
unknown's avatar
unknown committed
2

unknown's avatar
unknown committed
3 4
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
unknown's avatar
unknown committed
5
   the Free Software Foundation; version 2 of the License.
unknown's avatar
unknown committed
6

unknown's avatar
unknown committed
7 8 9 10
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
unknown's avatar
unknown committed
11

unknown's avatar
unknown committed
12 13 14 15 16
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */


17 18
#ifndef _log_event_h
#define _log_event_h
unknown's avatar
unknown committed
19

20
#if defined(USE_PRAGMA_INTERFACE) && !defined(MYSQL_CLIENT)
unknown's avatar
unknown committed
21 22 23
#pragma interface			/* gcc class implementation */
#endif

24
#include <my_bitmap.h>
25
#include "rpl_constants.h"
26

unknown's avatar
unknown committed
27 28 29 30
#define LOG_READ_EOF    -1
#define LOG_READ_BOGUS  -2
#define LOG_READ_IO     -3
#define LOG_READ_MEM    -5
unknown's avatar
unknown committed
31
#define LOG_READ_TRUNC  -6
unknown's avatar
unknown committed
32
#define LOG_READ_TOO_LARGE -7
unknown's avatar
unknown committed
33 34

#define LOG_EVENT_OFFSET 4
unknown's avatar
unknown committed
35 36

/*
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
   3 is MySQL 4.x; 4 is MySQL 5.0.0.
   Compared to version 3, version 4 has:
   - a different Start_log_event, which includes info about the binary log
   (sizes of headers); this info is included for better compatibility if the
   master's MySQL version is different from the slave's.
   - all events have a unique ID (the triplet (server_id, timestamp at server
   start, other) to be sure an event is not executed more than once in a
   multimaster setup, example:
                M1
              /   \
             v     v
             M2    M3
             \     /
              v   v
                S
   if a query is run on M1, it will arrive twice on S, so we need that S
   remembers the last unique ID it has processed, to compare and know if the
   event should be skipped or not. Example of ID: we already have the server id
   (4 bytes), plus:
   timestamp_when_the_master_started (4 bytes), a counter (a sequence number
   which increments every time we write an event to the binlog) (3 bytes).
   Q: how do we handle when the counter is overflowed and restarts from 0 ?
unknown's avatar
unknown committed
59

60
   - Query and Load (Create or Execute) events may have a more precise timestamp
unknown's avatar
unknown committed
61
   (with microseconds), number of matched/affected/warnings rows
62 63
   and fields of session variables: SQL_MODE,
   FOREIGN_KEY_CHECKS, UNIQUE_CHECKS, SQL_AUTO_IS_NULL, the collations and
unknown's avatar
unknown committed
64
   charsets, the PASSWORD() version (old/new/...).
65 66
*/
#define BINLOG_VERSION    4
67

68 69 70
/*
 We could have used SERVER_VERSION_LENGTH, but this introduces an
 obscure dependency - if somebody decided to change SERVER_VERSION_LENGTH
71
 this would break the replication protocol
72 73 74
*/
#define ST_SERVER_VER_LEN 50

75 76 77 78 79
/*
  These are flags and structs to handle all the LOAD DATA INFILE options (LINES
  TERMINATED etc).
*/

80 81 82 83 84 85
/*
  These are flags and structs to handle all the LOAD DATA INFILE options (LINES
  TERMINATED etc).
  DUMPFILE_FLAG is probably useless (DUMPFILE is a clause of SELECT, not of LOAD
  DATA).
*/
86 87 88 89
#define DUMPFILE_FLAG		0x1
#define OPT_ENCLOSED_FLAG	0x2
#define REPLACE_FLAG		0x4
#define IGNORE_FLAG		0x8
90

91 92 93 94 95
#define FIELD_TERM_EMPTY	0x1
#define ENCLOSED_EMPTY		0x2
#define LINE_TERM_EMPTY		0x4
#define LINE_START_EMPTY	0x8
#define ESCAPED_EMPTY		0x10
96

97 98 99 100 101
/*****************************************************************************

  old_sql_ex struct

 ****************************************************************************/
102
struct old_sql_ex
103 104 105 106 107 108 109 110 111
{
  char field_term;
  char enclosed;
  char line_term;
  char line_start;
  char escaped;
  char opt_flags;
  char empty_flags;
};
112

unknown's avatar
unknown committed
113 114
#define NUM_LOAD_DELIM_STRS 5

115 116 117 118 119
/*****************************************************************************

  sql_ex_info struct

 ****************************************************************************/
120
struct sql_ex_info
121
{
122
  sql_ex_info() {}                            /* Remove gcc warning */
123 124 125 126 127 128 129
  char* field_term;
  char* enclosed;
  char* line_term;
  char* line_start;
  char* escaped;
  int cached_new_format;
  uint8 field_term_len,enclosed_len,line_term_len,line_start_len, escaped_len;
unknown's avatar
unknown committed
130
  char opt_flags;
131
  char empty_flags;
unknown's avatar
unknown committed
132

133
  // store in new format even if old is possible
unknown's avatar
unknown committed
134
  void force_new_format() { cached_new_format = 1;}
135 136 137 138 139 140
  int data_size()
  {
    return (new_format() ?
	    field_term_len + enclosed_len + line_term_len +
	    line_start_len + escaped_len + 6 : 7);
  }
141
  bool write_data(IO_CACHE* file);
142 143 144 145 146 147 148 149 150 151
  char* init(char* buf,char* buf_end,bool use_new_format);
  bool new_format()
  {
    return ((cached_new_format != -1) ? cached_new_format :
	    (cached_new_format=(field_term_len > 1 ||
				enclosed_len > 1 ||
				line_term_len > 1 || line_start_len > 1 ||
				escaped_len > 1)));
  }
};
152

153 154 155 156 157 158 159 160 161 162 163 164
/*****************************************************************************

  MySQL Binary Log

  This log consists of events.  Each event has a fixed-length header,
  possibly followed by a variable length data body.

  The data body consists of an optional fixed length segment (post-header)
  and  an optional variable length segment.

  See the #defines below for the format specifics.

unknown's avatar
unknown committed
165 166 167 168 169 170
  The events which really update data are Query_log_event,
  Execute_load_query_log_event and old Load_log_event and
  Execute_load_log_event events (Execute_load_query is used together with
  Begin_load_query and Append_block events to replicate LOAD DATA INFILE.
  Create_file/Append_block/Execute_load (which includes Load_log_event)
  were used to replicate LOAD DATA before the 5.0.3).
171

172
 ****************************************************************************/
173

174 175
#define LOG_EVENT_HEADER_LEN 19     /* the fixed header length */
#define OLD_HEADER_LEN       13     /* the fixed header length in 3.23 */
unknown's avatar
unknown committed
176
/*
177 178 179 180 181 182
   Fixed header length, where 4.x and 5.0 agree. That is, 5.0 may have a longer
   header (it will for sure when we have the unique event's ID), but at least
   the first 19 bytes are the same in 4.x and 5.0. So when we have the unique
   event's ID, LOG_EVENT_HEADER_LEN will be something like 26, but
   LOG_EVENT_MINIMAL_HEADER_LEN will remain 19.
*/
unknown's avatar
unknown committed
183 184
#define LOG_EVENT_MINIMAL_HEADER_LEN 19

185
/* event-specific post-header sizes */
186 187 188
// where 3.23, 4.x and 5.0 agree
#define QUERY_HEADER_MINIMAL_LEN     (4 + 4 + 1 + 2)
// where 5.0 differs: 2 for len of N-bytes vars.
unknown's avatar
unknown committed
189
#define QUERY_HEADER_LEN     (QUERY_HEADER_MINIMAL_LEN + 2)
190
#define LOAD_HEADER_LEN      (4 + 4 + 4 + 1 +1 + 4)
191 192
#define START_V3_HEADER_LEN     (2 + ST_SERVER_VER_LEN + 4)
#define ROTATE_HEADER_LEN    8 // this is FROZEN (the Rotate post-header is frozen)
193 194 195 196
#define CREATE_FILE_HEADER_LEN 4
#define APPEND_BLOCK_HEADER_LEN 4
#define EXEC_LOAD_HEADER_LEN   4
#define DELETE_FILE_HEADER_LEN 4
197
#define FORMAT_DESCRIPTION_HEADER_LEN (START_V3_HEADER_LEN+1+LOG_EVENT_TYPES)
198 199
#define ROWS_HEADER_LEN        8
#define TABLE_MAP_HEADER_LEN   8
unknown's avatar
unknown committed
200 201
#define EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN (4 + 4 + 4 + 1)
#define EXECUTE_LOAD_QUERY_HEADER_LEN  (QUERY_HEADER_LEN + EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN)
202
#define INCIDENT_HEADER_LEN    2
203 204
/* 
  Max number of possible extra bytes in a replication event compared to a
205 206
  packet (i.e. a query) sent from client to master;
  First, an auxiliary log_event status vars estimation:
207
*/
208 209 210 211 212 213 214 215 216 217 218 219
#define MAX_SIZE_LOG_EVENT_STATUS (4 /* flags2 */   + \
                                   8 /* sql mode */ + \
                                   1 + 1 + 255 /* catalog */ + \
                                   4 /* autoinc */ + \
                                   6 /* charset */ + \
                                   MAX_TIME_ZONE_NAME_LENGTH)
#define MAX_LOG_EVENT_HEADER   ( /* in order of Query_log_event::write */ \
  LOG_EVENT_HEADER_LEN + /* write_header */ \
  QUERY_HEADER_LEN     + /* write_data */   \
  EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN + /*write_post_header_for_derived */ \
  MAX_SIZE_LOG_EVENT_STATUS + /* status */ \
  NAME_LEN + 1)
220

221 222 223 224
/* 
   Event header offsets; 
   these point to places inside the fixed header.
*/
unknown's avatar
unknown committed
225

226
#define EVENT_TYPE_OFFSET    4
227 228
#define SERVER_ID_OFFSET     5
#define EVENT_LEN_OFFSET     9
229
#define LOG_POS_OFFSET       13
230 231
#define FLAGS_OFFSET         17

232
/* start event post-header (for v3 and v4) */
233 234 235 236

#define ST_BINLOG_VER_OFFSET  0
#define ST_SERVER_VER_OFFSET  2
#define ST_CREATED_OFFSET     (ST_SERVER_VER_OFFSET + ST_SERVER_VER_LEN)
237
#define ST_COMMON_HEADER_LEN_OFFSET (ST_CREATED_OFFSET + 4)
238

239
/* slave event post-header (this event is never written) */
240

unknown's avatar
unknown committed
241 242 243
#define SL_MASTER_PORT_OFFSET   8
#define SL_MASTER_POS_OFFSET    0
#define SL_MASTER_HOST_OFFSET   10
244 245 246

/* query event post-header */

247 248 249 250
#define Q_THREAD_ID_OFFSET	0
#define Q_EXEC_TIME_OFFSET	4
#define Q_DB_LEN_OFFSET		8
#define Q_ERR_CODE_OFFSET	9
251
#define Q_STATUS_VARS_LEN_OFFSET 11
252
#define Q_DATA_OFFSET		QUERY_HEADER_LEN
253 254 255
/* these are codes, not offsets; not more than 256 values (1 byte). */
#define Q_FLAGS2_CODE           0
#define Q_SQL_MODE_CODE         1
256 257
/*
  Q_CATALOG_CODE is catalog with end zero stored; it is used only by MySQL
258 259
  5.0.x where 0<=x<=3. We have to keep it to be able to replicate these
  old masters.
260
*/
261
#define Q_CATALOG_CODE          2
262
#define Q_AUTO_INCREMENT	3
263
#define Q_CHARSET_CODE          4
264
#define Q_TIME_ZONE_CODE        5
265 266 267 268 269 270 271 272
/*
  Q_CATALOG_NZ_CODE is catalog withOUT end zero stored; it is used by MySQL
  5.0.x where x>=4. Saves one byte in every Query_log_event in binlog,
  compared to Q_CATALOG_CODE. The reason we didn't simply re-use
  Q_CATALOG_CODE is that then a 5.0.3 slave of this 5.0.x (x>=4) master would
  crash (segfault etc) because it would expect a 0 when there is none.
*/
#define Q_CATALOG_NZ_CODE       6
273

274 275
#define Q_LC_TIME_NAMES_CODE    7

276
#define Q_CHARSET_DATABASE_CODE 8
277 278 279 280 281
/* Intvar event post-header */

#define I_TYPE_OFFSET        0
#define I_VAL_OFFSET         1

unknown's avatar
unknown committed
282 283 284 285 286
/* Rand event post-header */

#define RAND_SEED1_OFFSET 0
#define RAND_SEED2_OFFSET 8

unknown's avatar
unknown committed
287 288 289 290 291 292 293 294
/* User_var event post-header */

#define UV_VAL_LEN_SIZE        4
#define UV_VAL_IS_NULL         1
#define UV_VAL_TYPE_SIZE       1
#define UV_NAME_LEN_SIZE       4
#define UV_CHARSET_NUMBER_SIZE 4

295 296 297 298 299
/* Load event post-header */

#define L_THREAD_ID_OFFSET   0
#define L_EXEC_TIME_OFFSET   4
#define L_SKIP_LINES_OFFSET  8
unknown's avatar
unknown committed
300 301
#define L_TBL_LEN_OFFSET     12
#define L_DB_LEN_OFFSET      13
302
#define L_NUM_FIELDS_OFFSET  14
303
#define L_SQL_EX_OFFSET      18
304
#define L_DATA_OFFSET        LOAD_HEADER_LEN
305

306 307 308 309
/* Rotate event post-header */

#define R_POS_OFFSET       0
#define R_IDENT_OFFSET     8
310

311 312 313
/* CF to DF handle LOAD DATA INFILE */

/* CF = "Create File" */
314 315 316
#define CF_FILE_ID_OFFSET  0
#define CF_DATA_OFFSET     CREATE_FILE_HEADER_LEN

317
/* AB = "Append Block" */
318 319 320
#define AB_FILE_ID_OFFSET  0
#define AB_DATA_OFFSET     APPEND_BLOCK_HEADER_LEN

321
/* EL = "Execute Load" */
322 323
#define EL_FILE_ID_OFFSET  0

324
/* DF = "Delete File" */
325
#define DF_FILE_ID_OFFSET  0
326

327 328 329 330 331 332 333 334
/* TM = "Table Map" */
#define TM_MAPID_OFFSET    0
#define TM_FLAGS_OFFSET    6

/* RW = "RoWs" */
#define RW_MAPID_OFFSET    0
#define RW_FLAGS_OFFSET    6

unknown's avatar
unknown committed
335 336 337 338 339 340
/* ELQ = "Execute Load Query" */
#define ELQ_FILE_ID_OFFSET QUERY_HEADER_LEN
#define ELQ_FN_POS_START_OFFSET ELQ_FILE_ID_OFFSET + 4
#define ELQ_FN_POS_END_OFFSET ELQ_FILE_ID_OFFSET + 8
#define ELQ_DUP_HANDLING_OFFSET ELQ_FILE_ID_OFFSET + 12

341
/* 4 bytes which all binlogs should begin with */
unknown's avatar
unknown committed
342
#define BINLOG_MAGIC        "\xfe\x62\x69\x6e"
343

344 345 346 347 348 349 350 351
/*
  The 2 flags below were useless :
  - the first one was never set
  - the second one was set in all Rotate events on the master, but not used for
  anything useful.
  So they are now removed and their place may later be reused for other
  flags. Then one must remember that Rotate events in 4.x have
  LOG_EVENT_FORCED_ROTATE_F set, so one should not rely on the value of the
unknown's avatar
unknown committed
352
  replacing flag when reading a Rotate event.
353 354 355
  I keep the defines here just to remember what they were.
*/
#ifdef TO_BE_REMOVED
unknown's avatar
unknown committed
356
#define LOG_EVENT_TIME_F            0x1
unknown's avatar
unknown committed
357
#define LOG_EVENT_FORCED_ROTATE_F   0x2
358
#endif
359 360

/*
361 362 363 364 365 366 367 368
   This flag only makes sense for Format_description_log_event. It is set
   when the event is written, and *reset* when a binlog file is
   closed (yes, it's the only case when MySQL modifies already written
   part of binlog).  Thus it is a reliable indicator that binlog was
   closed correctly.  (Stop_log_event is not enough, there's always a
   small chance that mysqld crashes in the middle of insert and end of
   the binlog would look like a Stop_log_event).

369 370 371 372 373 374 375 376
   This flag is used to detect a restart after a crash, and to provide
   "unbreakable" binlog. The problem is that on a crash storage engines
   rollback automatically, while binlog does not.  To solve this we use this
   flag and automatically append ROLLBACK to every non-closed binlog (append
   virtually, on reading, file itself is not changed). If this flag is found,
   mysqlbinlog simply prints "ROLLBACK" Replication master does not abort on
   binlog corruption, but takes it as EOF, and replication slave forces a
   rollback in this case.
377 378 379

   Note, that old binlogs does not have this flag set, so we get a
   a backward-compatible behaviour.
380 381
*/

382 383
#define LOG_EVENT_BINLOG_IN_USE_F       0x1

unknown's avatar
unknown committed
384
/*
385 386 387 388 389
   If the query depends on the thread (for example: TEMPORARY TABLE).
   Currently this is used by mysqlbinlog to know it must print
   SET @@PSEUDO_THREAD_ID=xx; before the query (it would not hurt to print it
   for every query but this would be slow).
*/
unknown's avatar
unknown committed
390
#define LOG_EVENT_THREAD_SPECIFIC_F 0x4
391

392 393 394 395 396 397 398 399 400 401 402 403 404
/*
  Suppress the generation of 'USE' statements before the actual
  statement. This flag should be set for any events that does not need
  the current database set to function correctly. Most notable cases
  are 'CREATE DATABASE' and 'DROP DATABASE'.

  This flags should only be used in exceptional circumstances, since
  it introduce a significant change in behaviour regarding the
  replication logic together with the flags --binlog-do-db and
  --replicated-do-db.
 */
#define LOG_EVENT_SUPPRESS_USE_F    0x8

405 406 407 408 409 410
/*
  The table map version internal to the log should be increased after
  the event has been written to the binary log.
 */
#define LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F 0x10

unknown's avatar
unknown committed
411
/*
412 413 414 415 416 417 418
   OPTIONS_WRITTEN_TO_BIN_LOG are the bits of thd->options which must be
   written to the binlog. OPTIONS_WRITTEN_TO_BINLOG could be written
   into the Format_description_log_event, so that if later we don't want
   to replicate a variable we did replicate, or the contrary, it's
   doable. But it should not be too hard to decide once for all of what
   we replicate and what we don't, among the fixed 32 bits of
   thd->options.
419
   I (Guilhem) have read through every option's usage, and it looks like
420 421 422 423
   OPTION_AUTO_IS_NULL and OPTION_NO_FOREIGN_KEYS are the only ones
   which alter how the query modifies the table. It's good to replicate
   OPTION_RELAXED_UNIQUE_CHECKS too because otherwise, the slave may
   insert data slower than the master, in InnoDB.
424
   OPTION_BIG_SELECTS is not needed (the slave thread runs with
425 426 427
   max_join_size=HA_POS_ERROR) and OPTION_BIG_TABLES is not needed
   either, as the manual says (because a too big in-memory temp table is
   automatically written to disk).
unknown's avatar
unknown committed
428
*/
429 430 431
#define OPTIONS_WRITTEN_TO_BIN_LOG \
  (OPTION_AUTO_IS_NULL | OPTION_NO_FOREIGN_KEY_CHECKS |  \
   OPTION_RELAXED_UNIQUE_CHECKS | OPTION_NOT_AUTOCOMMIT)
432

433 434 435
/* Shouldn't be defined before */
#define EXPECTED_OPTIONS \
  ((ULL(1) << 14) | (ULL(1) << 26) | (ULL(1) << 27) | (ULL(1) << 19))
436

437
#if OPTIONS_WRITTEN_TO_BIN_LOG != EXPECTED_OPTIONS
unknown's avatar
unknown committed
438 439
#error OPTIONS_WRITTEN_TO_BIN_LOG must NOT change their values!
#endif
440
#undef EXPECTED_OPTIONS         /* You shouldn't use this one */
unknown's avatar
unknown committed
441

442 443
enum Log_event_type
{
444 445
  /*
    Every time you update this enum (when you add a type), you have to
unknown's avatar
unknown committed
446
    fix Format_description_log_event::Format_description_log_event().
447
  */
unknown's avatar
unknown committed
448 449 450 451 452 453 454 455 456 457 458
  UNKNOWN_EVENT= 0,
  START_EVENT_V3= 1,
  QUERY_EVENT= 2,
  STOP_EVENT= 3,
  ROTATE_EVENT= 4,
  INTVAR_EVENT= 5,
  LOAD_EVENT= 6,
  SLAVE_EVENT= 7,
  CREATE_FILE_EVENT= 8,
  APPEND_BLOCK_EVENT= 9,
  EXEC_LOAD_EVENT= 10,
459
  DELETE_FILE_EVENT= 11,
460
  /*
unknown's avatar
unknown committed
461 462 463
    NEW_LOAD_EVENT is like LOAD_EVENT except that it has a longer
    sql_ex, allowing multibyte TERMINATED BY etc; both types share the
    same class (Load_log_event)
464
  */
465
  NEW_LOAD_EVENT= 12,
unknown's avatar
unknown committed
466 467 468 469 470 471
  RAND_EVENT= 13,
  USER_VAR_EVENT= 14,
  FORMAT_DESCRIPTION_EVENT= 15,
  XID_EVENT= 16,
  BEGIN_LOAD_QUERY_EVENT= 17,
  EXECUTE_LOAD_QUERY_EVENT= 18,
472

473
  TABLE_MAP_EVENT = 19,
474 475 476 477 478 479 480 481 482 483 484 485 486 487 488

  /*
    These event numbers were used for 5.1.0 to 5.1.15 and are
    therefore obsolete.
   */
  PRE_GA_WRITE_ROWS_EVENT = 20,
  PRE_GA_UPDATE_ROWS_EVENT = 21,
  PRE_GA_DELETE_ROWS_EVENT = 22,

  /*
    These event numbers are used from 5.1.16 and forward
   */
  WRITE_ROWS_EVENT = 23,
  UPDATE_ROWS_EVENT = 24,
  DELETE_ROWS_EVENT = 25,
unknown's avatar
unknown committed
489

490 491 492
  /*
    Something out of the ordinary happened on the master
   */
unknown's avatar
unknown committed
493
  INCIDENT_EVENT= 26,
494

unknown's avatar
unknown committed
495
  /*
unknown's avatar
unknown committed
496
    Add new events here - right above this comment!
unknown's avatar
unknown committed
497
    Existing events (except ENUM_END_EVENT) should never change their numbers
unknown's avatar
unknown committed
498 499
  */

unknown's avatar
unknown committed
500
  ENUM_END_EVENT /* end marker */
501 502
};

unknown's avatar
unknown committed
503
/*
504 505 506 507 508 509
   The number of types we handle in Format_description_log_event (UNKNOWN_EVENT
   is not to be handled, it does not exist in binlogs, it does not have a
   format).
*/
#define LOG_EVENT_TYPES (ENUM_END_EVENT-1)

510 511 512 513 514
enum Int_event_type
{
  INVALID_INT_EVENT = 0, LAST_INSERT_ID_EVENT = 1, INSERT_ID_EVENT = 2
};

unknown's avatar
unknown committed
515 516 517

#ifndef MYSQL_CLIENT
class String;
518
class MYSQL_BIN_LOG;
519
class THD;
unknown's avatar
unknown committed
520 521
#endif

522 523
class Format_description_log_event;

524
struct st_relay_log_info;
525
typedef st_relay_log_info RELAY_LOG_INFO;
526

527 528
#ifdef MYSQL_CLIENT
/*
unknown's avatar
unknown committed
529 530
  A structure for mysqlbinlog to know how to print events

unknown's avatar
unknown committed
531 532 533 534 535 536 537 538
  This structure is passed to the event's print() methods,

  There are two types of settings stored here:
  1. Last db, flags2, sql_mode etc comes from the last printed event.
     They are stored so that only the necessary USE and SET commands
     are printed.
  2. Other information on how to print the events, e.g. short_form,
     hexdump_from.  These are not dependent on the last event.
539
*/
unknown's avatar
unknown committed
540
typedef struct st_print_event_info
541
{
unknown's avatar
unknown committed
542 543 544 545
  /*
    Settings for database, sql_mode etc that comes from the last event
    that was printed.
   */
546 547 548 549 550
  // TODO: have the last catalog here ??
  char db[FN_REFLEN+1]; // TODO: make this a LEX_STRING when thd->db is
  bool flags2_inited;
  uint32 flags2;
  bool sql_mode_inited;
unknown's avatar
unknown committed
551
  ulong sql_mode;		/* must be same as THD.variables.sql_mode */
552
  ulong auto_increment_increment, auto_increment_offset;
553 554
  bool charset_inited;
  char charset[6]; // 3 variables, each of them storable in 2 bytes
555
  char time_zone_str[MAX_TIME_ZONE_NAME_LENGTH];
556
  uint lc_time_names_number;
557
  uint charset_database_number;
unknown's avatar
unknown committed
558
  st_print_event_info()
559
    :flags2_inited(0), sql_mode_inited(0),
560
     auto_increment_increment(1),auto_increment_offset(1), charset_inited(0),
561
     lc_time_names_number(0), charset_database_number(0)
562
    {
563
      /*
unknown's avatar
unknown committed
564
        Currently we only use static PRINT_EVENT_INFO objects, so zeroed at
565 566 567 568 569
        program's startup, but these explicit bzero() is for the day someone
        creates dynamic instances.
      */
      bzero(db, sizeof(db));
      bzero(charset, sizeof(charset));
570
      bzero(time_zone_str, sizeof(time_zone_str));
571 572 573 574 575
      delimiter[0]= ';';
      delimiter[1]= 0;
      myf const flags = MYF(MY_WME | MY_NABP);
      open_cached_file(&head_cache, NULL, NULL, 0, flags);
      open_cached_file(&body_cache, NULL, NULL, 0, flags);
576
    }
unknown's avatar
unknown committed
577

578
  ~st_print_event_info() {
579 580
    close_cached_file(&head_cache);
    close_cached_file(&body_cache);
581
  }
582 583
  bool init_ok() /* tells if construction was successful */
    { return my_b_inited(&head_cache) && my_b_inited(&body_cache); }
584 585


unknown's avatar
unknown committed
586 587
  /* Settings on how to print the events */
  bool short_form;
588
  bool base64_output;
unknown's avatar
unknown committed
589 590
  my_off_t hexdump_from;
  uint8 common_header_len;
591
  char delimiter[16];
unknown's avatar
unknown committed
592

593 594 595 596 597 598 599
  /*
     These two caches are used by the row-based replication events to
     collect the header information and the main body of the events
     making up a statement.
   */
  IO_CACHE head_cache;
  IO_CACHE body_cache;
unknown's avatar
unknown committed
600
} PRINT_EVENT_INFO;
601 602 603
#endif


604 605 606 607 608 609 610
/*****************************************************************************

  Log_event class

  This is the abstract base class for binary log events.

 ****************************************************************************/
unknown's avatar
unknown committed
611 612 613
class Log_event
{
public:
614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640
  /**
     Enumeration of what kinds of skipping (and non-skipping) that can
     occur when the slave executes an event.

     @see shall_skip
     @see do_shall_skip
   */
  enum enum_skip_reason {
    /**
       Don't skip event.
    */
    EVENT_SKIP_NOT,

    /**
       Skip event by ignoring it.

       This means that the slave skip counter will not be changed.
    */
    EVENT_SKIP_IGNORE,

    /**
       Skip event and decrease skip counter.
    */
    EVENT_SKIP_COUNT
  };


641 642 643 644 645 646 647
  /*
    The following type definition is to be used whenever data is placed 
    and manipulated in a common buffer. Use this typedef for buffers
    that contain data containing binary and character data.
  */
  typedef unsigned char Byte;

unknown's avatar
unknown committed
648
  /*
649 650 651 652 653 654 655 656
    The offset in the log where this event originally appeared (it is
    preserved in relay logs, making SHOW SLAVE STATUS able to print
    coordinates of the event in the master's binlog). Note: when a
    transaction is written by the master to its binlog (wrapped in
    BEGIN/COMMIT) the log_pos of all the queries it contains is the
    one of the BEGIN (this way, when one does SHOW SLAVE STATUS it
    sees the offset of the BEGIN, which is logical as rollback may
    occur), except the COMMIT query which has its real offset.
657
  */
658
  my_off_t log_pos;
unknown's avatar
unknown committed
659
  /*
660 661 662
     A temp buffer for read_log_event; it is later analysed according to the
     event's type, and its content is distributed in the event-specific fields.
  */
unknown's avatar
unknown committed
663
  char *temp_buf;
664
  /*
665 666 667 668 669 670
    Timestamp on the master(for debugging and replication of
    NOW()/TIMESTAMP).  It is important for queries and LOAD DATA
    INFILE. This is set at the event's creation time, except for Query
    and Load (et al.) events where this is set at the query's
    execution time, which guarantees good replication (otherwise, we
    could have a query and its event with different timestamps).
671
  */
672
  time_t when;
673
  /* The number of seconds the query took to run on the master. */
unknown's avatar
unknown committed
674
  ulong exec_time;
675 676 677
  /* Number of bytes written by write() function */
  ulong data_written;

unknown's avatar
unknown committed
678
  /*
679 680
    The master's server id (is preserved in the relay log; used to
    prevent from infinite loops in circular replication).
681
  */
682
  uint32 server_id;
683 684

  /*
685 686 687
    Some 16 flags. Look above for LOG_EVENT_TIME_F,
    LOG_EVENT_FORCED_ROTATE_F, LOG_EVENT_THREAD_SPECIFIC_F, and
    LOG_EVENT_SUPPRESS_USE_F for notes.
688
  */
689
  uint16 flags;
690

691
  bool cache_stmt;
692

693
#ifndef MYSQL_CLIENT
694
  THD* thd;
695

696
  Log_event();
697
  Log_event(THD* thd_arg, uint16 flags_arg, bool cache_stmt);
698
  /*
699 700 701 702 703 704 705 706 707
    read_log_event() functions read an event from a binlog or relay
    log; used by SHOW BINLOG EVENTS, the binlog_dump thread on the
    master (reads master's binlog), the slave IO thread (reads the
    event sent by binlog_dump), the slave SQL thread (reads the event
    from the relay log).  If mutex is 0, the read will proceed without
    mutex.  We need the description_event to be able to parse the
    event (to know the post-header's size); in fact in read_log_event
    we detect the event's type, then call the specific event's
    constructor and pass description_event as an argument.
708
  */
709 710
  static Log_event* read_log_event(IO_CACHE* file,
				   pthread_mutex_t* log_lock,
711
                                   const Format_description_log_event *description_event);
712 713
  static int read_log_event(IO_CACHE* file, String* packet,
			    pthread_mutex_t* log_lock);
714
  /*
715 716 717
    init_show_field_list() prepares the column names and types for the
    output of SHOW BINLOG EVENTS; it is used only by SHOW BINLOG
    EVENTS.
718
  */
719
  static void init_show_field_list(List<Item>* field_list);
unknown's avatar
SCRUM  
unknown committed
720
#ifdef HAVE_REPLICATION
unknown's avatar
unknown committed
721
  int net_send(Protocol *protocol, const char* log_name, my_off_t pos);
722

723 724 725 726
  /*
    pack_info() is used by SHOW BINLOG EVENTS; as print() it prepares and sends
    a string to display to the user, so it resembles print().
  */
727

unknown's avatar
unknown committed
728
  virtual void pack_info(Protocol *protocol);
729

unknown's avatar
SCRUM  
unknown committed
730
#endif /* HAVE_REPLICATION */
731 732 733 734 735
  virtual const char* get_db()
  {
    return thd ? thd->db : 0;
  }
#else
736
  Log_event() : temp_buf(0) {}
737
    /* avoid having to link mysqlbinlog against libpthread */
738 739
  static Log_event* read_log_event(IO_CACHE* file,
                                   const Format_description_log_event *description_event);
740
  /* print*() functions are used by mysqlbinlog */
741
  virtual void print(FILE* file, PRINT_EVENT_INFO* print_event_info) = 0;
742 743 744 745 746
  void print_timestamp(IO_CACHE* file, time_t *ts = 0);
  void print_header(IO_CACHE* file, PRINT_EVENT_INFO* print_event_info,
                    bool is_more);
  void print_base64(IO_CACHE* file, PRINT_EVENT_INFO* print_event_info,
                    bool is_more);
unknown's avatar
unknown committed
747
#endif
unknown's avatar
unknown committed
748

749 750 751 752
  static void *operator new(size_t size)
  {
    return (void*) my_malloc((uint)size, MYF(MY_WME|MY_FAE));
  }
753

754 755
  static void operator delete(void *ptr, size_t size)
  {
756
    my_free((gptr) ptr, MYF(MY_WME|MY_ALLOW_ZERO_PTR));
757
  }
unknown's avatar
unknown committed
758

759 760 761 762
  /* Placement version of the above operators */
  static void *operator new(size_t, void* ptr) { return ptr; }
  static void operator delete(void*, void*) { }

763
#ifndef MYSQL_CLIENT
764 765 766 767 768 769 770 771
  bool write_header(IO_CACHE* file, ulong data_length);
  virtual bool write(IO_CACHE* file)
  {
    return (write_header(file, get_data_size()) ||
            write_data_header(file) ||
            write_data_body(file));
  }
  virtual bool write_data_header(IO_CACHE* file)
772
  { return 0; }
773
  virtual bool write_data_body(IO_CACHE* file __attribute__((unused)))
774
  { return 0; }
775
#endif
unknown's avatar
unknown committed
776
  virtual Log_event_type get_type_code() = 0;
unknown's avatar
unknown committed
777
  virtual bool is_valid() const = 0;
778
  virtual bool is_artificial_event() { return 0; }
779
  inline bool get_cache_stmt() const { return cache_stmt; }
780
  Log_event(const char* buf, const Format_description_log_event* description_event);
781 782 783
  virtual ~Log_event() { free_temp_buf();}
  void register_temp_buf(char* buf) { temp_buf = buf; }
  void free_temp_buf()
784 785
  {
    if (temp_buf)
786
    {
787 788
      my_free(temp_buf, MYF(0));
      temp_buf = 0;
789
    }
790
  }
791 792 793 794
  /*
    Get event length for simple events. For complicated events the length
    is calculated during write()
  */
795
  virtual int get_data_size() { return 0;}
796 797 798
  static Log_event* read_log_event(const char* buf, uint event_len,
				   const char **error,
                                   const Format_description_log_event
unknown's avatar
unknown committed
799
                                   *description_event);
800
  /* returns the human readable name of the event's type */
unknown's avatar
unknown committed
801
  const char* get_type_str();
802 803

#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843
public:

  /**
     Apply the event to the database.

     This function represents the public interface for applying an
     event.

     @see do_apply_event
   */
  int apply_event(RELAY_LOG_INFO const *rli) {
    return do_apply_event(rli);
  }


  /**
     Update the relay log position.

     This function represents the public interface for "stepping over"
     the event and will update the relay log information.

     @see do_update_pos
   */
  int update_pos(RELAY_LOG_INFO *rli)
  {
    return do_update_pos(rli);
  }

  /**
     Decide if the event shall be skipped, and the reason for skipping
     it.

     @see do_shall_skip
   */
  enum_skip_reason shall_skip(RELAY_LOG_INFO *rli)
  {
    return do_shall_skip(rli);
  }

protected:
844

845 846 847 848 849
  /**
    Primitive to apply an event to the database.

    This is where the change to the database is made.

850 851 852 853 854
    @note The primitive is protected instead of private, since there
    is a hierarchy of actions to be performed in some cases.

    @see Format_description_log_event::do_apply_event()

855 856 857 858 859
    @param rli Pointer to relay log info structure

    @retval 0     Event applied successfully
    @retval errno Error code if event application failed
  */
860 861 862 863 864
  virtual int do_apply_event(RELAY_LOG_INFO const *rli)
  {
    return 0;                /* Default implementation does nothing */
  }

865 866

  /**
867 868 869 870 871 872
     Advance relay log coordinates.

     This function is called to advance the relay log coordinates to
     just after the event.  It is essential that both the relay log
     coordinate and the group log position is updated correctly, since
     this function is used also for skipping events.
873

874 875 876 877 878 879 880
     Normally, each implementation of do_update_pos() shall:

     - Update the event position to refer to the position just after
       the event.

     - Update the group log position to refer to the position just
       after the event <em>if the event is last in a group</em>
881 882 883 884

     @param rli Pointer to relay log info structure

     @retval 0     Coordinates changed successfully
885 886 887
     @retval errno Error code if advancing failed (usually just
                   1). Observe that handler errors are returned by the
                   do_apply_event() function, and not by this one.
888
   */
889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922
  virtual int do_update_pos(RELAY_LOG_INFO *rli);


  /**
     Decide if this event shall be skipped or not and the reason for
     skipping it.

     The default implementation decide that the event shall be skipped
     if either:

     - the server id of the event is the same as the server id of the
       server and <code>rli->replicate_same_server_id</code> is true,
       or

     - if <code>rli->slave_skip_counter</code> is greater than zero.

     @see do_apply_event
     @see do_update_pos

     @retval Log_event::EVENT_SKIP_NOT
     The event shall not be skipped and should be applied.

     @retval Log_event::EVENT_SKIP_IGNORE
     The event shall be skipped by just ignoring it, i.e., the slave
     skip counter shall not be changed. This happends if, for example,
     the originating server id of the event is the same as the server
     id of the slave.

     @retval Log_event::EVENT_SKIP_COUNT
     The event shall be skipped because the slave skip counter was
     non-zero. The caller shall decrease the counter by one.
   */
  virtual enum_skip_reason do_shall_skip(RELAY_LOG_INFO *rli);

923
#endif
unknown's avatar
unknown committed
924 925
};

unknown's avatar
unknown committed
926
/*
927 928 929 930 931 932 933 934 935 936 937
   One class for each type of event.
   Two constructors for each class:
   - one to create the event for logging (when the server acts as a master),
   called after an update to the database is done,
   which accepts parameters like the query, the database, the options for LOAD
   DATA INFILE...
   - one to create the event from a packet (when the server acts as a slave),
   called before reproducing the update, which accepts parameters (like a
   buffer). Used to read from the master, from the relay log, and in
   mysqlbinlog. This constructor must be format-tolerant.
*/
unknown's avatar
unknown committed
938

939 940 941 942 943 944 945
/*****************************************************************************

  Query Log Event class

  Logs SQL queries

 ****************************************************************************/
unknown's avatar
unknown committed
946 947 948
class Query_log_event: public Log_event
{
protected:
949
  Log_event::Byte* data_buf;
unknown's avatar
unknown committed
950 951
public:
  const char* query;
952
  const char* catalog;
unknown's avatar
unknown committed
953
  const char* db;
954 955 956 957 958 959
  /*
    If we already know the length of the query string
    we pass it with q_len, so we would not have to call strlen()
    otherwise, set it to 0, in which case, we compute it with strlen()
  */
  uint32 q_len;
unknown's avatar
unknown committed
960
  uint32 db_len;
961
  uint16 error_code;
962
  ulong thread_id;
unknown's avatar
unknown committed
963
  /*
964 965
    For events created by Query_log_event::do_apply_event (and
    Load_log_event::do_apply_event()) we need the *original* thread
966 967
    id, to be able to log the event with the original (=master's)
    thread id (fix for BUG#1686).
unknown's avatar
unknown committed
968 969
  */
  ulong slave_proxy_id;
unknown's avatar
unknown committed
970 971

  /*
972 973
    Binlog format 3 and 4 start to differ (as far as class members are
    concerned) from here.
974
  */
unknown's avatar
unknown committed
975

976
  uint catalog_len;			// <= 255 char; 0 means uninited
unknown's avatar
unknown committed
977

978 979
  /*
    We want to be able to store a variable number of N-bit status vars:
980 981 982
    (generally N=32; but N=64 for SQL_MODE) a user may want to log the number
    of affected rows (for debugging) while another does not want to lose 4
    bytes in this.
983 984 985 986 987
    The storage on disk is the following:
    status_vars_len is part of the post-header,
    status_vars are in the variable-length part, after the post-header, before
    the db & query.
    status_vars on disk is a sequence of pairs (code, value) where 'code' means
988 989
    'sql_mode', 'affected' etc. Sometimes 'value' must be a short string, so
    its first byte is its length. For now the order of status vars is:
990
    flags2 - sql_mode - catalog - autoinc - charset
991 992 993 994 995 996 997 998
    We should add the same thing to Load_log_event, but in fact
    LOAD DATA INFILE is going to be logged with a new type of event (logging of
    the plain text query), so Load_log_event would be frozen, so no need. The
    new way of logging LOAD DATA INFILE would use a derived class of
    Query_log_event, so automatically benefit from the work already done for
    status variables in Query_log_event.
 */
  uint16 status_vars_len;
unknown's avatar
unknown committed
999

1000 1001 1002 1003 1004 1005 1006 1007 1008
  /*
    'flags2' is a second set of flags (on top of those in Log_event), for
    session variables. These are thd->options which is & against a mask
    (OPTIONS_WRITTEN_TO_BINLOG).
    flags2_inited helps make a difference between flags2==0 (3.23 or 4.x
    master, we don't know flags2, so use the slave server's global options) and
    flags2==0 (5.0 master, we know this has a meaning of flags all down which
    must influence the query).
  */
unknown's avatar
unknown committed
1009
  bool flags2_inited;
1010
  bool sql_mode_inited;
1011
  bool charset_inited;
unknown's avatar
unknown committed
1012 1013

  uint32 flags2;
1014
  /* In connections sql_mode is 32 bits now but will be 64 bits soon */
unknown's avatar
unknown committed
1015
  ulong sql_mode;
1016
  ulong auto_increment_increment, auto_increment_offset;
1017
  char charset[6];
1018 1019
  uint time_zone_len; /* 0 means uninited */
  const char *time_zone_str;
1020
  uint lc_time_names_number; /* 0 means en_US */
1021
  uint charset_database_number;
unknown's avatar
unknown committed
1022

1023
#ifndef MYSQL_CLIENT
1024

1025
  Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length,
1026
		  bool using_trans, bool suppress_use);
1027
  const char* get_db() { return db; }
unknown's avatar
SCRUM  
unknown committed
1028
#ifdef HAVE_REPLICATION
1029
  void pack_info(Protocol* protocol);
unknown's avatar
SCRUM  
unknown committed
1030
#endif /* HAVE_REPLICATION */
1031
#else
1032
  void print_query_header(IO_CACHE* file, PRINT_EVENT_INFO* print_event_info);
1033
  void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
unknown's avatar
unknown committed
1034 1035
#endif

1036
  Query_log_event();
1037
  Query_log_event(const char* buf, uint event_len,
unknown's avatar
unknown committed
1038 1039
                  const Format_description_log_event *description_event,
                  Log_event_type event_type);
unknown's avatar
unknown committed
1040 1041 1042
  ~Query_log_event()
  {
    if (data_buf)
1043
      my_free((gptr) data_buf, MYF(0));
unknown's avatar
unknown committed
1044 1045
  }
  Log_event_type get_type_code() { return QUERY_EVENT; }
1046
#ifndef MYSQL_CLIENT
1047
  bool write(IO_CACHE* file);
1048 1049
  virtual bool write_post_header_for_derived(IO_CACHE* file) { return FALSE; }
#endif
unknown's avatar
unknown committed
1050
  bool is_valid() const { return query != 0; }
unknown's avatar
unknown committed
1051 1052 1053 1054 1055 1056 1057

  /*
    Returns number of bytes additionaly written to post header by derived
    events (so far it is only Execute_load_query event).
  */
  virtual ulong get_post_header_size_for_derived() { return 0; }
  /* Writes derived event-specific part of post header. */
1058 1059 1060

public:        /* !!! Public in this patch to allow old usage */
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
1061 1062 1063 1064
  virtual int do_apply_event(RELAY_LOG_INFO const *rli);
  virtual int do_update_pos(RELAY_LOG_INFO *rli);

  int do_apply_event(RELAY_LOG_INFO const *rli,
1065 1066 1067
                       const char *query_arg,
                       uint32 q_len_arg);
#endif /* HAVE_REPLICATION */
unknown's avatar
unknown committed
1068 1069
};

1070 1071 1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084 1085

/*****************************************************************************

  Muted Query Log Event class

  Pretends to Log SQL queries, but doesn't actually do so.

 ****************************************************************************/
class Muted_query_log_event: public Query_log_event
{
public:
#ifndef MYSQL_CLIENT
  Muted_query_log_event();

  bool write(IO_CACHE* file) { return(false); };
  virtual bool write_post_header_for_derived(IO_CACHE* file) { return FALSE; }
1086 1087
#else
  Muted_query_log_event() {}
1088 1089 1090 1091
#endif
};


unknown's avatar
SCRUM  
unknown committed
1092
#ifdef HAVE_REPLICATION
1093

1094 1095 1096
/*****************************************************************************

  Slave Log Event class
1097 1098
  Note that this class is currently not used at all; no code writes a
  Slave_log_event (though some code in repl_failsafe.cc reads Slave_log_event).
1099
  So it's not a problem if this code is not maintained.
1100 1101

 ****************************************************************************/
1102 1103 1104 1105 1106 1107
class Slave_log_event: public Log_event
{
protected:
  char* mem_pool;
  void init_from_mem_pool(int data_size);
public:
unknown's avatar
unknown committed
1108
  my_off_t master_pos;
1109 1110
  char* master_host;
  char* master_log;
unknown's avatar
unknown committed
1111
  int master_host_len;
1112
  int master_log_len;
unknown's avatar
unknown committed
1113
  uint16 master_port;
1114

unknown's avatar
unknown committed
1115
#ifndef MYSQL_CLIENT
1116
  Slave_log_event(THD* thd_arg, RELAY_LOG_INFO* rli);
1117
  void pack_info(Protocol* protocol);
1118
#else
1119
  void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
unknown's avatar
unknown committed
1120
#endif
1121

1122
  Slave_log_event(const char* buf, uint event_len);
1123 1124
  ~Slave_log_event();
  int get_data_size();
unknown's avatar
unknown committed
1125
  bool is_valid() const { return master_host != 0; }
1126
  Log_event_type get_type_code() { return SLAVE_EVENT; }
1127
#ifndef MYSQL_CLIENT
1128
  bool write(IO_CACHE* file);
1129
#endif
1130 1131 1132

private:
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
1133
  virtual int do_apply_event(RELAY_LOG_INFO const* rli);
1134
#endif
1135 1136
};

unknown's avatar
SCRUM  
unknown committed
1137
#endif /* HAVE_REPLICATION */
1138

1139 1140 1141 1142 1143 1144

/*****************************************************************************

  Load Log Event class

 ****************************************************************************/
unknown's avatar
unknown committed
1145 1146
class Load_log_event: public Log_event
{
unknown's avatar
unknown committed
1147 1148 1149 1150
private:
  uint get_query_buffer_length();
  void print_query(bool need_db, char *buf, char **end,
                   char **fn_start, char **fn_end);
unknown's avatar
unknown committed
1151
protected:
unknown's avatar
unknown committed
1152
  int copy_log_event(const char *buf, ulong event_len,
1153
                     int body_offset, const Format_description_log_event* description_event);
1154

unknown's avatar
unknown committed
1155
public:
1156
  ulong thread_id;
unknown's avatar
unknown committed
1157
  ulong slave_proxy_id;
unknown's avatar
unknown committed
1158
  uint32 table_name_len;
1159 1160 1161 1162 1163
  /*
    No need to have a catalog, as these events can only come from 4.x.
    TODO: this may become false if Dmitri pushes his new LOAD DATA INFILE in
    5.0 only (not in 4.x).
  */
unknown's avatar
unknown committed
1164 1165 1166
  uint32 db_len;
  uint32 fname_len;
  uint32 num_fields;
unknown's avatar
unknown committed
1167 1168
  const char* fields;
  const uchar* field_lens;
unknown's avatar
unknown committed
1169
  uint32 field_block_len;
unknown's avatar
unknown committed
1170 1171 1172 1173

  const char* table_name;
  const char* db;
  const char* fname;
unknown's avatar
unknown committed
1174
  uint32 skip_lines;
unknown's avatar
unknown committed
1175
  sql_ex_info sql_ex;
1176
  bool local_fname;
1177

1178 1179
  /* fname doesn't point to memory inside Log_event::temp_buf  */
  void set_fname_outside_temp_buf(const char *afname, uint alen)
unknown's avatar
unknown committed
1180 1181 1182
  {
    fname= afname;
    fname_len= alen;
unknown's avatar
unknown committed
1183
    local_fname= TRUE;
unknown's avatar
unknown committed
1184
  }
1185 1186
  /* fname doesn't point to memory inside Log_event::temp_buf  */
  int  check_fname_outside_temp_buf()
unknown's avatar
unknown committed
1187
  {
1188
    return local_fname;
unknown's avatar
unknown committed
1189
  }
1190

1191
#ifndef MYSQL_CLIENT
unknown's avatar
unknown committed
1192 1193
  String field_lens_buf;
  String fields_buf;
unknown's avatar
unknown committed
1194

1195
  Load_log_event(THD* thd, sql_exchange* ex, const char* db_arg,
1196
		 const char* table_name_arg,
1197
		 List<Item>& fields_arg, enum enum_duplicates handle_dup, bool ignore,
1198
		 bool using_trans);
1199 1200
  void set_fields(const char* db, List<Item> &fields_arg,
                  Name_resolution_context *context);
1201
  const char* get_db() { return db; }
unknown's avatar
SCRUM  
unknown committed
1202
#ifdef HAVE_REPLICATION
unknown's avatar
unknown committed
1203
  void pack_info(Protocol* protocol);
unknown's avatar
SCRUM  
unknown committed
1204
#endif /* HAVE_REPLICATION */
1205
#else
1206
  void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
unknown's avatar
unknown committed
1207
  void print(FILE* file, PRINT_EVENT_INFO* print_event_info, bool commented);
unknown's avatar
unknown committed
1208 1209
#endif

1210 1211 1212 1213 1214 1215 1216
  /*
    Note that for all the events related to LOAD DATA (Load_log_event,
    Create_file/Append/Exec/Delete, we pass description_event; however as
    logging of LOAD DATA is going to be changed in 4.1 or 5.0, this is only used
    for the common_header_len (post_header_len will not be changed).
  */
  Load_log_event(const char* buf, uint event_len,
unknown's avatar
unknown committed
1217
                 const Format_description_log_event* description_event);
unknown's avatar
unknown committed
1218
  ~Load_log_event()
1219
  {}
1220 1221 1222 1223
  Log_event_type get_type_code()
  {
    return sql_ex.new_format() ? NEW_LOAD_EVENT: LOAD_EVENT;
  }
1224
#ifndef MYSQL_CLIENT
1225 1226
  bool write_data_header(IO_CACHE* file);
  bool write_data_body(IO_CACHE* file);
1227
#endif
unknown's avatar
unknown committed
1228
  bool is_valid() const { return table_name != 0; }
unknown's avatar
unknown committed
1229 1230
  int get_data_size()
  {
1231 1232
    return (table_name_len + db_len + 2 + fname_len
	    + LOAD_HEADER_LEN
1233
	    + sql_ex.data_size() + field_block_len + num_fields);
unknown's avatar
unknown committed
1234
  }
1235 1236 1237

public:        /* !!! Public in this patch to allow old usage */
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
1238
  virtual int do_apply_event(RELAY_LOG_INFO const* rli)
1239
  {
1240
    return do_apply_event(thd->slave_net,rli,0);
1241 1242
  }

1243 1244
  int do_apply_event(NET *net, RELAY_LOG_INFO const *rli,
                     bool use_rli_only_for_errors);
1245
#endif
unknown's avatar
unknown committed
1246 1247
};

unknown's avatar
unknown committed
1248
extern char server_version[SERVER_VERSION_LENGTH];
unknown's avatar
unknown committed
1249

1250 1251
/*****************************************************************************

1252
  Start Log Event_v3 class
1253

1254 1255 1256 1257 1258 1259 1260
  Start_log_event_v3 is the Start_log_event of binlog format 3 (MySQL 3.23 and
  4.x).
  Format_description_log_event derives from Start_log_event_v3; it is the
  Start_log_event of binlog format 4 (MySQL 5.0), that is, the event that
  describes the other events' header/postheader lengths. This event is sent by
  MySQL 5.0 whenever it starts sending a new binlog if the requested position
  is >4 (otherwise if ==4 the event will be sent naturally).
unknown's avatar
unknown committed
1261

1262
 ****************************************************************************/
1263

1264
class Start_log_event_v3: public Log_event
unknown's avatar
unknown committed
1265 1266
{
public:
unknown's avatar
unknown committed
1267
  /*
1268 1269 1270 1271 1272
    If this event is at the start of the first binary log since server
    startup 'created' should be the timestamp when the event (and the
    binary log) was created.  In the other case (i.e. this event is at
    the start of a binary log created by FLUSH LOGS or automatic
    rotation), 'created' should be 0.  This "trick" is used by MySQL
1273 1274
    >=4.0.14 slaves to know whether they must drop stale temporary
    tables and whether they should abort unfinished transaction.
1275 1276 1277 1278 1279 1280 1281 1282

    Note that when 'created'!=0, it is always equal to the event's
    timestamp; indeed Start_log_event is written only in log.cc where
    the first constructor below is called, in which 'created' is set
    to 'when'.  So in fact 'created' is a useless variable. When it is
    0 we can read the actual value from timestamp ('when') and when it
    is non-zero we can read the same value from timestamp
    ('when'). Conclusion:
1283 1284 1285 1286 1287
     - we use timestamp to print when the binlog was created.
     - we use 'created' only to know if this is a first binlog or not.
     In 3.23.57 we did not pay attention to this identity, so mysqlbinlog in
     3.23.57 does not print 'created the_date' if created was zero. This is now
     fixed.
1288
  */
1289
  time_t created;
1290
  uint16 binlog_version;
1291
  char server_version[ST_SERVER_VER_LEN];
1292 1293 1294 1295 1296 1297
  /*
    artifical_event is 1 in the case where this is a generated event that
    should not case any cleanup actions. We handle this in the log by
    setting log_event == 0 (for now).
  */
  bool artificial_event;
1298 1299

#ifndef MYSQL_CLIENT
1300
  Start_log_event_v3();
unknown's avatar
SCRUM  
unknown committed
1301
#ifdef HAVE_REPLICATION
1302
  void pack_info(Protocol* protocol);
unknown's avatar
SCRUM  
unknown committed
1303
#endif /* HAVE_REPLICATION */
1304
#else
1305
  Start_log_event_v3() {}
1306
  void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
unknown's avatar
unknown committed
1307
#endif
1308

1309 1310 1311 1312
  Start_log_event_v3(const char* buf,
                     const Format_description_log_event* description_event);
  ~Start_log_event_v3() {}
  Log_event_type get_type_code() { return START_EVENT_V3;}
1313
#ifndef MYSQL_CLIENT
1314
  bool write(IO_CACHE* file);
1315
#endif
unknown's avatar
unknown committed
1316
  bool is_valid() const { return 1; }
1317 1318
  int get_data_size()
  {
1319 1320
    return START_V3_HEADER_LEN; //no variable-sized part
  }
1321
  virtual bool is_artificial_event() { return artificial_event; }
1322

1323
protected:
1324
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336
  virtual int do_apply_event(RELAY_LOG_INFO const *rli);
  virtual enum_skip_reason do_shall_skip(RELAY_LOG_INFO*)
  {
    /*
      Events from ourself should be skipped, but they should not
      decrease the slave skip counter.
     */
    if (this->server_id == ::server_id)
      return Log_event::EVENT_SKIP_IGNORE;
    else
      return Log_event::EVENT_SKIP_NOT;
  }
1337
#endif
1338 1339
};

1340

unknown's avatar
unknown committed
1341
/*
1342 1343 1344 1345 1346 1347 1348 1349
   For binlog version 4.
   This event is saved by threads which read it, as they need it for future
   use (to decode the ordinary events).
*/

class Format_description_log_event: public Start_log_event_v3
{
public:
unknown's avatar
unknown committed
1350
  /*
1351 1352 1353 1354 1355 1356 1357 1358 1359
     The size of the fixed header which _all_ events have
     (for binlogs written by this version, this is equal to
     LOG_EVENT_HEADER_LEN), except FORMAT_DESCRIPTION_EVENT and ROTATE_EVENT
     (those have a header of size LOG_EVENT_MINIMAL_HEADER_LEN).
  */
  uint8 common_header_len;
  uint8 number_of_event_types;
  /* The list of post-headers' lengthes */
  uint8 *post_header_len;
unknown's avatar
unknown committed
1360
  uchar server_version_split[3];
1361 1362 1363 1364 1365 1366

  Format_description_log_event(uint8 binlog_ver, const char* server_ver=0);
  Format_description_log_event(const char* buf, uint event_len,
                               const Format_description_log_event* description_event);
  ~Format_description_log_event() { my_free((gptr)post_header_len, MYF(0)); }
  Log_event_type get_type_code() { return FORMAT_DESCRIPTION_EVENT;}
1367
#ifndef MYSQL_CLIENT
1368
  bool write(IO_CACHE* file);
1369
#endif
unknown's avatar
unknown committed
1370
  bool is_valid() const
1371
  {
1372 1373 1374
    return ((common_header_len >= ((binlog_version==1) ? OLD_HEADER_LEN :
                                   LOG_EVENT_MINIMAL_HEADER_LEN)) &&
            (post_header_len != NULL));
1375 1376 1377 1378 1379 1380 1381 1382 1383
  }
  int get_data_size()
  {
    /*
      The vector of post-header lengths is considered as part of the
      post-header, because in a given version it never changes (contrary to the
      query in a Query_log_event).
    */
    return FORMAT_DESCRIPTION_HEADER_LEN;
1384
  }
1385

unknown's avatar
unknown committed
1386
  void calc_server_version_split();
1387

1388
protected:
1389
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
1390 1391 1392
  virtual int do_apply_event(RELAY_LOG_INFO const *rli);
  virtual int do_update_pos(RELAY_LOG_INFO *rli);
  virtual enum_skip_reason do_shall_skip(RELAY_LOG_INFO *rli);
1393
#endif
unknown's avatar
unknown committed
1394 1395
};

1396

1397 1398 1399 1400 1401 1402 1403
/*****************************************************************************

  Intvar Log Event class

  Logs special variables such as auto_increment values

 ****************************************************************************/
1404

unknown's avatar
unknown committed
1405 1406 1407 1408 1409
class Intvar_log_event: public Log_event
{
public:
  ulonglong val;
  uchar type;
1410

unknown's avatar
unknown committed
1411
#ifndef MYSQL_CLIENT
1412
  Intvar_log_event(THD* thd_arg,uchar type_arg, ulonglong val_arg)
1413
    :Log_event(thd_arg,0,0),val(val_arg),type(type_arg)
unknown's avatar
unknown committed
1414
  {}
unknown's avatar
SCRUM  
unknown committed
1415
#ifdef HAVE_REPLICATION
1416
  void pack_info(Protocol* protocol);
unknown's avatar
SCRUM  
unknown committed
1417
#endif /* HAVE_REPLICATION */
1418
#else
1419
  void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
unknown's avatar
unknown committed
1420
#endif
1421

1422
  Intvar_log_event(const char* buf, const Format_description_log_event* description_event);
unknown's avatar
unknown committed
1423 1424
  ~Intvar_log_event() {}
  Log_event_type get_type_code() { return INTVAR_EVENT;}
unknown's avatar
unknown committed
1425
  const char* get_var_type_name();
1426
  int get_data_size() { return  9; /* sizeof(type) + sizeof(val) */;}
1427
#ifndef MYSQL_CLIENT
1428
  bool write(IO_CACHE* file);
1429
#endif
unknown's avatar
unknown committed
1430
  bool is_valid() const { return 1; }
1431 1432 1433

private:
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
1434 1435 1436
  virtual int do_apply_event(RELAY_LOG_INFO const *rli);
  virtual int do_update_pos(RELAY_LOG_INFO *rli);
  virtual enum_skip_reason do_shall_skip(RELAY_LOG_INFO *rli);
1437
#endif
unknown's avatar
unknown committed
1438 1439
};

1440

unknown's avatar
unknown committed
1441
/*****************************************************************************
1442 1443 1444

  Rand Log Event class

unknown's avatar
unknown committed
1445
  Logs random seed used by the next RAND(), and by PASSWORD() in 4.1.0.
1446 1447 1448
  4.1.1 does not need it (it's repeatable again) so this event needn't be
  written in 4.1.1 for PASSWORD() (but the fact that it is written is just a
  waste, it does not cause bugs).
1449

unknown's avatar
unknown committed
1450
 ****************************************************************************/
1451

unknown's avatar
unknown committed
1452 1453 1454 1455 1456 1457 1458 1459
class Rand_log_event: public Log_event
{
 public:
  ulonglong seed1;
  ulonglong seed2;

#ifndef MYSQL_CLIENT
  Rand_log_event(THD* thd_arg, ulonglong seed1_arg, ulonglong seed2_arg)
1460
    :Log_event(thd_arg,0,0),seed1(seed1_arg),seed2(seed2_arg)
unknown's avatar
unknown committed
1461
  {}
unknown's avatar
SCRUM  
unknown committed
1462
#ifdef HAVE_REPLICATION
1463
  void pack_info(Protocol* protocol);
unknown's avatar
SCRUM  
unknown committed
1464
#endif /* HAVE_REPLICATION */
unknown's avatar
unknown committed
1465
#else
1466
  void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
unknown's avatar
unknown committed
1467 1468
#endif

1469
  Rand_log_event(const char* buf, const Format_description_log_event* description_event);
unknown's avatar
unknown committed
1470 1471
  ~Rand_log_event() {}
  Log_event_type get_type_code() { return RAND_EVENT;}
1472
  int get_data_size() { return 16; /* sizeof(ulonglong) * 2*/ }
1473
#ifndef MYSQL_CLIENT
1474
  bool write(IO_CACHE* file);
1475
#endif
unknown's avatar
unknown committed
1476
  bool is_valid() const { return 1; }
1477 1478 1479

private:
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
1480 1481 1482
  virtual int do_apply_event(RELAY_LOG_INFO const *rli);
  virtual int do_update_pos(RELAY_LOG_INFO *rli);
  virtual enum_skip_reason do_shall_skip(RELAY_LOG_INFO *rli);
1483
#endif
unknown's avatar
unknown committed
1484 1485
};

1486 1487 1488 1489 1490 1491 1492 1493 1494
/*****************************************************************************

  Xid Log Event class

  Logs xid of the transaction-to-be-committed in the 2pc protocol.
  Has no meaning in replication, slaves ignore it.

 ****************************************************************************/
#ifdef MYSQL_CLIENT
1495
typedef ulonglong my_xid; // this line is the same as in handler.h
1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508
#endif

class Xid_log_event: public Log_event
{
 public:
   my_xid xid;

#ifndef MYSQL_CLIENT
  Xid_log_event(THD* thd_arg, my_xid x): Log_event(thd_arg,0,0), xid(x) {}
#ifdef HAVE_REPLICATION
  void pack_info(Protocol* protocol);
#endif /* HAVE_REPLICATION */
#else
1509
  void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
1510 1511 1512 1513 1514 1515
#endif

  Xid_log_event(const char* buf, const Format_description_log_event* description_event);
  ~Xid_log_event() {}
  Log_event_type get_type_code() { return XID_EVENT;}
  int get_data_size() { return sizeof(xid); }
1516
#ifndef MYSQL_CLIENT
1517
  bool write(IO_CACHE* file);
1518
#endif
1519
  bool is_valid() const { return 1; }
1520 1521 1522

private:
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
1523
  virtual int do_apply_event(RELAY_LOG_INFO const *rli);
1524
#endif
1525
};
1526

unknown's avatar
unknown committed
1527 1528 1529 1530
/*****************************************************************************

  User var Log Event class

1531 1532 1533
  Every time a query uses the value of a user variable, a User_var_log_event is
  written before the Query_log_event, to set the user variable.

unknown's avatar
unknown committed
1534
 ****************************************************************************/
1535

unknown's avatar
unknown committed
1536 1537 1538 1539 1540 1541 1542 1543 1544
class User_var_log_event: public Log_event
{
public:
  char *name;
  uint name_len;
  char *val;
  ulong val_len;
  Item_result type;
  uint charset_number;
1545
  bool is_null;
unknown's avatar
unknown committed
1546 1547 1548 1549 1550 1551 1552 1553 1554
#ifndef MYSQL_CLIENT
  User_var_log_event(THD* thd_arg, char *name_arg, uint name_len_arg,
                     char *val_arg, ulong val_len_arg, Item_result type_arg,
		     uint charset_number_arg)
    :Log_event(), name(name_arg), name_len(name_len_arg), val(val_arg),
    val_len(val_len_arg), type(type_arg), charset_number(charset_number_arg)
    { is_null= !val; }
  void pack_info(Protocol* protocol);
#else
1555
  void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
unknown's avatar
unknown committed
1556 1557
#endif

1558
  User_var_log_event(const char* buf, const Format_description_log_event* description_event);
unknown's avatar
unknown committed
1559 1560
  ~User_var_log_event() {}
  Log_event_type get_type_code() { return USER_VAR_EVENT;}
1561
#ifndef MYSQL_CLIENT
1562
  bool write(IO_CACHE* file);
1563
#endif
unknown's avatar
unknown committed
1564
  bool is_valid() const { return 1; }
1565 1566 1567

private:
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
1568 1569 1570
  virtual int do_apply_event(RELAY_LOG_INFO const *rli);
  virtual int do_update_pos(RELAY_LOG_INFO *rli);
  virtual enum_skip_reason do_shall_skip(RELAY_LOG_INFO *rli);
1571
#endif
unknown's avatar
unknown committed
1572
};
1573

1574

1575 1576 1577 1578 1579
/*****************************************************************************

  Stop Log Event class

 ****************************************************************************/
unknown's avatar
unknown committed
1580 1581 1582
class Stop_log_event: public Log_event
{
public:
unknown's avatar
unknown committed
1583
#ifndef MYSQL_CLIENT
1584
  Stop_log_event() :Log_event()
unknown's avatar
unknown committed
1585
  {}
1586
#else
1587
  void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
unknown's avatar
unknown committed
1588
#endif
1589

1590 1591
  Stop_log_event(const char* buf, const Format_description_log_event* description_event):
    Log_event(buf, description_event)
1592
  {}
unknown's avatar
unknown committed
1593 1594
  ~Stop_log_event() {}
  Log_event_type get_type_code() { return STOP_EVENT;}
unknown's avatar
unknown committed
1595
  bool is_valid() const { return 1; }
1596 1597 1598

private:
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610
  virtual int do_update_pos(RELAY_LOG_INFO *rli);
  virtual enum_skip_reason do_shall_skip(RELAY_LOG_INFO *rli)
  {
    /*
      Events from ourself should be skipped, but they should not
      decrease the slave skip counter.
     */
    if (this->server_id == ::server_id)
      return Log_event::EVENT_SKIP_IGNORE;
    else
      return Log_event::EVENT_SKIP_NOT;
  }
1611
#endif
unknown's avatar
unknown committed
1612 1613
};

1614 1615 1616 1617
/*****************************************************************************

  Rotate Log Event class

1618
  This will be deprecated when we move to using sequence ids.
1619 1620

 ****************************************************************************/
1621

unknown's avatar
unknown committed
1622 1623 1624
class Rotate_log_event: public Log_event
{
public:
1625 1626 1627
  enum {
    DUP_NAME= 2 // if constructor should dup the string argument
  };
unknown's avatar
unknown committed
1628
  const char* new_log_ident;
1629
  ulonglong pos;
unknown's avatar
unknown committed
1630
  uint ident_len;
1631
  uint flags;
unknown's avatar
unknown committed
1632
#ifndef MYSQL_CLIENT
1633
  Rotate_log_event(const char* new_log_ident_arg,
1634 1635
		   uint ident_len_arg,
		   ulonglong pos_arg, uint flags);
unknown's avatar
SCRUM  
unknown committed
1636
#ifdef HAVE_REPLICATION
1637
  void pack_info(Protocol* protocol);
unknown's avatar
SCRUM  
unknown committed
1638
#endif /* HAVE_REPLICATION */
1639
#else
1640
  void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
1641 1642
#endif

1643 1644
  Rotate_log_event(const char* buf, uint event_len,
                   const Format_description_log_event* description_event);
unknown's avatar
unknown committed
1645 1646
  ~Rotate_log_event()
  {
1647 1648
    if (flags & DUP_NAME)
      my_free((gptr) new_log_ident, MYF(MY_ALLOW_ZERO_PTR));
unknown's avatar
unknown committed
1649 1650
  }
  Log_event_type get_type_code() { return ROTATE_EVENT;}
1651
  int get_data_size() { return  ident_len + ROTATE_HEADER_LEN;}
unknown's avatar
unknown committed
1652
  bool is_valid() const { return new_log_ident != 0; }
1653
#ifndef MYSQL_CLIENT
1654
  bool write(IO_CACHE* file);
1655
#endif
1656 1657 1658

private:
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
1659 1660
  virtual int do_update_pos(RELAY_LOG_INFO *rli);
  virtual enum_skip_reason do_shall_skip(RELAY_LOG_INFO *rli);
1661
#endif
1662 1663
};

1664

1665 1666
/* the classes below are for the new LOAD DATA INFILE logging */

1667 1668 1669
/*****************************************************************************
  Create File Log Event class
 ****************************************************************************/
1670

1671
class Create_file_log_event: public Load_log_event
1672
{
1673
protected:
1674 1675 1676 1677 1678
  /*
    Pretend we are Load event, so we can write out just
    our Load part - used on the slave when writing event out to
    SQL_LOAD-*.info file
  */
unknown's avatar
unknown committed
1679
  bool fake_base;
1680 1681
public:
  char* block;
1682
  const char *event_buf;
1683 1684
  uint block_len;
  uint file_id;
unknown's avatar
unknown committed
1685
  bool inited_from_old;
1686

1687 1688
#ifndef MYSQL_CLIENT
  Create_file_log_event(THD* thd, sql_exchange* ex, const char* db_arg,
1689 1690
			const char* table_name_arg,
			List<Item>& fields_arg,
1691
			enum enum_duplicates handle_dup, bool ignore,
1692 1693
			char* block_arg, uint block_len_arg,
			bool using_trans);
unknown's avatar
SCRUM  
unknown committed
1694
#ifdef HAVE_REPLICATION
1695
  void pack_info(Protocol* protocol);
unknown's avatar
SCRUM  
unknown committed
1696
#endif /* HAVE_REPLICATION */
1697
#else
1698
  void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
unknown's avatar
unknown committed
1699
  void print(FILE* file, PRINT_EVENT_INFO* print_event_info, bool enable_local);
unknown's avatar
unknown committed
1700 1701
#endif

1702 1703
  Create_file_log_event(const char* buf, uint event_len,
                        const Format_description_log_event* description_event);
1704 1705 1706 1707
  ~Create_file_log_event()
  {
    my_free((char*) event_buf, MYF(MY_ALLOW_ZERO_PTR));
  }
1708 1709

  Log_event_type get_type_code()
1710
  {
1711 1712 1713 1714 1715 1716 1717 1718
    return fake_base ? Load_log_event::get_type_code() : CREATE_FILE_EVENT;
  }
  int get_data_size()
  {
    return (fake_base ? Load_log_event::get_data_size() :
	    Load_log_event::get_data_size() +
	    4 + 1 + block_len);
  }
unknown's avatar
unknown committed
1719
  bool is_valid() const { return inited_from_old || block != 0; }
1720
#ifndef MYSQL_CLIENT
1721 1722
  bool write_data_header(IO_CACHE* file);
  bool write_data_body(IO_CACHE* file);
1723 1724 1725 1726
  /*
    Cut out Create_file extentions and
    write it as Load event - used on the slave
  */
1727
  bool write_base(IO_CACHE* file);
1728
#endif
1729 1730 1731

private:
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
1732
  virtual int do_apply_event(RELAY_LOG_INFO const *rli);
1733
#endif
1734 1735
};

1736

1737 1738 1739 1740 1741
/*****************************************************************************

  Append Block Log Event class

 ****************************************************************************/
1742

1743 1744 1745 1746 1747 1748
class Append_block_log_event: public Log_event
{
public:
  char* block;
  uint block_len;
  uint file_id;
unknown's avatar
unknown committed
1749
  /*
1750 1751 1752 1753 1754 1755 1756 1757 1758
    'db' is filled when the event is created in mysql_load() (the
    event needs to have a 'db' member to be well filtered by
    binlog-*-db rules). 'db' is not written to the binlog (it's not
    used by Append_block_log_event::write()), so it can't be read in
    the Append_block_log_event(const char* buf, int event_len)
    constructor.  In other words, 'db' is used only for filtering by
    binlog-*-db rules.  Create_file_log_event is different: it's 'db'
    (which is inherited from Load_log_event) is written to the binlog
    and can be re-read.
unknown's avatar
unknown committed
1759 1760 1761
  */
  const char* db;

1762
#ifndef MYSQL_CLIENT
unknown's avatar
unknown committed
1763
  Append_block_log_event(THD* thd, const char* db_arg, char* block_arg,
1764
			 uint block_len_arg, bool using_trans);
unknown's avatar
SCRUM  
unknown committed
1765
#ifdef HAVE_REPLICATION
1766
  void pack_info(Protocol* protocol);
1767
  virtual int get_create_or_append() const;
unknown's avatar
SCRUM  
unknown committed
1768
#endif /* HAVE_REPLICATION */
1769
#else
1770
  void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
1771
#endif
unknown's avatar
unknown committed
1772 1773

  Append_block_log_event(const char* buf, uint event_len,
1774
                         const Format_description_log_event* description_event);
1775
  ~Append_block_log_event() {}
1776 1777
  Log_event_type get_type_code() { return APPEND_BLOCK_EVENT;}
  int get_data_size() { return  block_len + APPEND_BLOCK_HEADER_LEN ;}
unknown's avatar
unknown committed
1778
  bool is_valid() const { return block != 0; }
1779
#ifndef MYSQL_CLIENT
1780
  bool write(IO_CACHE* file);
unknown's avatar
unknown committed
1781
  const char* get_db() { return db; }
1782
#endif
1783 1784 1785

private:
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
1786
  virtual int do_apply_event(RELAY_LOG_INFO const *rli);
1787
#endif
1788 1789
};

1790

1791
/*****************************************************************************
1792

1793 1794 1795
  Delete File Log Event class

 ****************************************************************************/
1796

1797 1798 1799 1800
class Delete_file_log_event: public Log_event
{
public:
  uint file_id;
unknown's avatar
unknown committed
1801
  const char* db; /* see comment in Append_block_log_event */
unknown's avatar
unknown committed
1802

1803
#ifndef MYSQL_CLIENT
unknown's avatar
unknown committed
1804
  Delete_file_log_event(THD* thd, const char* db_arg, bool using_trans);
unknown's avatar
SCRUM  
unknown committed
1805
#ifdef HAVE_REPLICATION
1806
  void pack_info(Protocol* protocol);
unknown's avatar
SCRUM  
unknown committed
1807
#endif /* HAVE_REPLICATION */
1808
#else
1809
  void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
unknown's avatar
unknown committed
1810
  void print(FILE* file, PRINT_EVENT_INFO* print_event_info, bool enable_local);
unknown's avatar
unknown committed
1811 1812
#endif

1813 1814
  Delete_file_log_event(const char* buf, uint event_len,
                        const Format_description_log_event* description_event);
1815
  ~Delete_file_log_event() {}
1816 1817
  Log_event_type get_type_code() { return DELETE_FILE_EVENT;}
  int get_data_size() { return DELETE_FILE_HEADER_LEN ;}
unknown's avatar
unknown committed
1818
  bool is_valid() const { return file_id != 0; }
1819
#ifndef MYSQL_CLIENT
1820
  bool write(IO_CACHE* file);
unknown's avatar
unknown committed
1821
  const char* get_db() { return db; }
1822
#endif
1823 1824 1825

private:
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
1826
  virtual int do_apply_event(RELAY_LOG_INFO const *rli);
1827
#endif
1828 1829
};

1830

1831 1832 1833 1834 1835
/*****************************************************************************

  Execute Load Log Event class

 ****************************************************************************/
1836

1837 1838 1839 1840
class Execute_load_log_event: public Log_event
{
public:
  uint file_id;
unknown's avatar
unknown committed
1841
  const char* db; /* see comment in Append_block_log_event */
unknown's avatar
unknown committed
1842

1843
#ifndef MYSQL_CLIENT
unknown's avatar
unknown committed
1844
  Execute_load_log_event(THD* thd, const char* db_arg, bool using_trans);
unknown's avatar
SCRUM  
unknown committed
1845
#ifdef HAVE_REPLICATION
1846
  void pack_info(Protocol* protocol);
unknown's avatar
SCRUM  
unknown committed
1847
#endif /* HAVE_REPLICATION */
1848
#else
1849
  void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
unknown's avatar
unknown committed
1850 1851 1852
#endif

  Execute_load_log_event(const char* buf, uint event_len,
1853
                         const Format_description_log_event* description_event);
1854
  ~Execute_load_log_event() {}
1855 1856
  Log_event_type get_type_code() { return EXEC_LOAD_EVENT;}
  int get_data_size() { return  EXEC_LOAD_HEADER_LEN ;}
unknown's avatar
unknown committed
1857
  bool is_valid() const { return file_id != 0; }
1858
#ifndef MYSQL_CLIENT
1859
  bool write(IO_CACHE* file);
unknown's avatar
unknown committed
1860
  const char* get_db() { return db; }
1861
#endif
1862 1863 1864

private:
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
1865
  virtual int do_apply_event(RELAY_LOG_INFO const *rli);
1866
#endif
unknown's avatar
unknown committed
1867 1868
};

1869

unknown's avatar
unknown committed
1870 1871 1872 1873 1874 1875 1876 1877 1878 1879 1880 1881 1882 1883 1884 1885 1886 1887
/***************************************************************************

  Begin load query Log Event class

  Event for the first block of file to be loaded, its only difference from
  Append_block event is that this event creates or truncates existing file
  before writing data.

****************************************************************************/
class Begin_load_query_log_event: public Append_block_log_event
{
public:
#ifndef MYSQL_CLIENT
  Begin_load_query_log_event(THD* thd_arg, const char *db_arg,
                             char* block_arg, uint block_len_arg,
                             bool using_trans);
#ifdef HAVE_REPLICATION
  Begin_load_query_log_event(THD* thd);
1888
  int get_create_or_append() const;
unknown's avatar
unknown committed
1889 1890 1891 1892 1893 1894 1895 1896 1897 1898 1899 1900 1901 1902 1903 1904 1905 1906 1907 1908 1909 1910 1911 1912 1913 1914 1915 1916 1917 1918 1919 1920 1921 1922 1923 1924 1925 1926 1927 1928 1929 1930 1931 1932 1933 1934 1935 1936 1937
#endif /* HAVE_REPLICATION */
#endif
  Begin_load_query_log_event(const char* buf, uint event_len,
                             const Format_description_log_event* description_event);
  ~Begin_load_query_log_event() {}
  Log_event_type get_type_code() { return BEGIN_LOAD_QUERY_EVENT; }
};


/*
  Elements of this enum describe how LOAD DATA handles duplicates.
*/
enum enum_load_dup_handling { LOAD_DUP_ERROR= 0, LOAD_DUP_IGNORE,
                              LOAD_DUP_REPLACE };

/****************************************************************************

  Execute load query Log Event class

  Event responsible for LOAD DATA execution, it similar to Query_log_event
  but before executing the query it substitutes original filename in LOAD DATA
  query with name of temporary file.

****************************************************************************/
class Execute_load_query_log_event: public Query_log_event
{
public:
  uint file_id;       // file_id of temporary file
  uint fn_pos_start;  // pointer to the part of the query that should
                      // be substituted
  uint fn_pos_end;    // pointer to the end of this part of query
  /*
    We have to store type of duplicate handling explicitly, because
    for LOAD DATA it also depends on LOCAL option. And this part
    of query will be rewritten during replication so this information
    may be lost...
  */
  enum_load_dup_handling dup_handling;

#ifndef MYSQL_CLIENT
  Execute_load_query_log_event(THD* thd, const char* query_arg,
                       ulong query_length, uint fn_pos_start_arg,
                       uint fn_pos_end_arg,
                       enum_load_dup_handling dup_handling_arg,
                       bool using_trans, bool suppress_use);
#ifdef HAVE_REPLICATION
  void pack_info(Protocol* protocol);
#endif /* HAVE_REPLICATION */
#else
1938
  void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
unknown's avatar
unknown committed
1939
  /* Prints the query as LOAD DATA LOCAL and with rewritten filename */
unknown's avatar
unknown committed
1940
  void print(FILE* file, PRINT_EVENT_INFO* print_event_info,
unknown's avatar
unknown committed
1941
	     const char *local_fname);
unknown's avatar
unknown committed
1942 1943 1944 1945 1946 1947 1948 1949 1950
#endif
  Execute_load_query_log_event(const char* buf, uint event_len,
                               const Format_description_log_event *description_event);
  ~Execute_load_query_log_event() {}

  Log_event_type get_type_code() { return EXECUTE_LOAD_QUERY_EVENT; }
  bool is_valid() const { return Query_log_event::is_valid() && file_id != 0; }

  ulong get_post_header_size_for_derived();
1951
#ifndef MYSQL_CLIENT
unknown's avatar
unknown committed
1952
  bool write_post_header_for_derived(IO_CACHE* file);
1953
#endif
1954 1955 1956

private:
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
1957
  virtual int do_apply_event(RELAY_LOG_INFO const *rli);
1958 1959
#endif
};
unknown's avatar
unknown committed
1960 1961


1962 1963 1964 1965
#ifdef MYSQL_CLIENT
class Unknown_log_event: public Log_event
{
public:
1966 1967 1968 1969 1970 1971 1972
  /*
    Even if this is an unknown event, we still pass description_event to
    Log_event's ctor, this way we can extract maximum information from the
    event's header (the unique ID for example).
  */
  Unknown_log_event(const char* buf, const Format_description_log_event* description_event):
    Log_event(buf, description_event)
1973 1974
  {}
  ~Unknown_log_event() {}
1975
  void print(FILE* file, PRINT_EVENT_INFO* print_event_info);
1976
  Log_event_type get_type_code() { return UNKNOWN_EVENT;}
unknown's avatar
unknown committed
1977
  bool is_valid() const { return 1; }
1978
};
unknown's avatar
unknown committed
1979
#endif
1980
char *str_to_hex(char *to, const char *from, uint len);
1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998

/*****************************************************************************

  Table map log event class

  Create a mapping from a (database name, table name) couple to a table
  identifier (an integer number).

 ****************************************************************************/
class Table_map_log_event : public Log_event
{
public:
  /* Constants */
  enum
  {
    TYPE_CODE = TABLE_MAP_EVENT
  };

1999 2000 2001
  /**
     Enumeration of the errors that can be returned.
   */
2002 2003
  enum enum_error
  {
2004 2005 2006 2007 2008 2009
    ERR_OPEN_FAILURE = -1,               /**< Failure to open table */
    ERR_OK = 0,                                 /**< No error */
    ERR_TABLE_LIMIT_EXCEEDED = 1,      /**< No more room for tables */
    ERR_OUT_OF_MEM = 2,                         /**< Out of memory */
    ERR_BAD_TABLE_DEF = 3,     /**< Table definition does not match */
    ERR_RBR_TO_SBR = 4  /**< daisy-chanining RBR to SBR not allowed */
2010 2011 2012 2013 2014 2015
  };

  enum enum_flag
  {
    /* 
       Nothing here right now, but the flags support is there in
unknown's avatar
unknown committed
2016 2017 2018
       preparation for changes that are coming.  Need to add a
       constant to make it compile under HP-UX: aCC does not like
       empty enumerations.
2019
    */
unknown's avatar
unknown committed
2020
    ENUM_FLAG_COUNT
2021 2022 2023 2024 2025 2026 2027
  };

  typedef uint16 flag_set;

  /* Special constants representing sets of flags */
  enum 
  {
unknown's avatar
unknown committed
2028
    TM_NO_FLAGS = 0U
2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046
  };

  void set_flags(flag_set flag) { m_flags |= flag; }
  void clear_flags(flag_set flag) { m_flags &= ~flag; }
  flag_set get_flags(flag_set flag) const { return m_flags & flag; }

#ifndef MYSQL_CLIENT
  Table_map_log_event(THD *thd, TABLE *tbl, ulong tid, 
		      bool is_transactional, uint16 flags);
#endif
#ifdef HAVE_REPLICATION
  Table_map_log_event(const char *buf, uint event_len, 
                      const Format_description_log_event *description_event);
#endif

  ~Table_map_log_event();

  virtual Log_event_type get_type_code() { return TABLE_MAP_EVENT; }
2047
  virtual bool is_valid() const { return m_memory != NULL; /* we check malloc */ }
2048 2049 2050

  virtual int get_data_size() { return m_data_size; } 
#ifndef MYSQL_CLIENT
2051 2052
  virtual const int calc_field_metadata_size();
  virtual int save_field_metadata();
2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067
  virtual bool write_data_header(IO_CACHE *file);
  virtual bool write_data_body(IO_CACHE *file);
  virtual const char *get_db() { return m_dbnam; }
#endif

#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
  virtual void pack_info(Protocol *protocol);
#endif

#ifdef MYSQL_CLIENT
  virtual void print(FILE *file, PRINT_EVENT_INFO *print_event_info);
#endif


private:
2068
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
2069 2070
  virtual int do_apply_event(RELAY_LOG_INFO const *rli);
  virtual int do_update_pos(RELAY_LOG_INFO *rli);
2071 2072
#endif

2073 2074 2075 2076 2077 2078 2079 2080 2081 2082 2083 2084 2085 2086 2087
#ifndef MYSQL_CLIENT
  TABLE      *m_table;
#endif
  char const    *m_dbnam;
  my_size_t      m_dblen;
  char const    *m_tblnam;
  my_size_t      m_tbllen;
  ulong          m_colcnt;
  unsigned char *m_coltype;

  gptr           m_memory;
  ulong          m_table_id;
  flag_set       m_flags;

  my_size_t      m_data_size;
2088 2089 2090 2091 2092 2093 2094 2095

  uchar          *m_field_metadata;        // buffer for field metadata
  /*
    The size of field metadata buffer set by calling calc_field_metadata_size()
  */
  ulong         m_field_metadata_size;   
  uchar        *m_null_bits;
  gptr          m_meta_memory;
2096 2097 2098 2099 2100 2101 2102
};


/*****************************************************************************

 Row level log event class.

2103
 Common base class for all row-containing log events.
2104 2105 2106 2107 2108 2109 2110 2111 2112

 RESPONSIBILITIES

   Encode the common parts of all events containing rows, which are:
   - Write data header and data body to an IO_CACHE.
   - Provide an interface for adding an individual row to the event.

 ****************************************************************************/

2113

2114 2115 2116
class Rows_log_event : public Log_event
{
public:
2117 2118 2119 2120 2121 2122 2123 2124 2125 2126 2127 2128 2129
  /**
     Enumeration of the errors that can be returned.
   */
  enum enum_error
  {
    ERR_OPEN_FAILURE = -1,               /**< Failure to open table */
    ERR_OK = 0,                                 /**< No error */
    ERR_TABLE_LIMIT_EXCEEDED = 1,      /**< No more room for tables */
    ERR_OUT_OF_MEM = 2,                         /**< Out of memory */
    ERR_BAD_TABLE_DEF = 3,     /**< Table definition does not match */
    ERR_RBR_TO_SBR = 4  /**< daisy-chanining RBR to SBR not allowed */
  };

2130 2131 2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153
  /*
    These definitions allow you to combine the flags into an
    appropriate flag set using the normal bitwise operators.  The
    implicit conversion from an enum-constant to an integer is
    accepted by the compiler, which is then used to set the real set
    of flags.
  */
  enum enum_flag
  {
    /* Last event of a statement */
    STMT_END_F = (1U << 0),

    /* Value of the OPTION_NO_FOREIGN_KEY_CHECKS flag in thd->options */
    NO_FOREIGN_KEY_CHECKS_F = (1U << 1),

    /* Value of the OPTION_RELAXED_UNIQUE_CHECKS flag in thd->options */
    RELAXED_UNIQUE_CHECKS_F = (1U << 2)
  };

  typedef uint16 flag_set;

  /* Special constants representing sets of flags */
  enum 
  {
2154
      RLE_NO_FLAGS = 0U
2155 2156 2157 2158
  };

  virtual ~Rows_log_event();

2159 2160 2161
  void set_flags(flag_set flags_arg) { m_flags |= flags_arg; }
  void clear_flags(flag_set flags_arg) { m_flags &= ~flags_arg; }
  flag_set get_flags(flag_set flags_arg) const { return m_flags & flags_arg; }
2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179

#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
  virtual void pack_info(Protocol *protocol);
#endif

#ifdef MYSQL_CLIENT
  /* not for direct call, each derived has its own ::print() */
  virtual void print(FILE *file, PRINT_EVENT_INFO *print_event_info)= 0;
#endif

#ifndef MYSQL_CLIENT
  int add_row_data(byte *data, my_size_t length)
  {
    return do_add_row_data(data,length); 
  }
#endif

  /* Member functions to implement superclass interface */
2180
  virtual int get_data_size();
2181 2182 2183 2184 2185 2186 2187 2188 2189 2190

  MY_BITMAP const *get_cols() const { return &m_cols; }
  my_size_t get_width() const       { return m_width; }
  ulong get_table_id() const        { return m_table_id; }

#ifndef MYSQL_CLIENT
  virtual bool write_data_header(IO_CACHE *file);
  virtual bool write_data_body(IO_CACHE *file);
  virtual const char *get_db() { return m_table->s->db.str; }
#endif
2191 2192 2193 2194 2195 2196
  /*
    Check that malloc() succeeded in allocating memory for the rows
    buffer and the COLS vector. Checking that an Update_rows_log_event
    is valid is done in the Update_rows_log_event::is_valid()
    function.
  */
2197 2198 2199 2200 2201
  virtual bool is_valid() const
  {
    return m_rows_buf && m_cols.bitmap;
  }

2202
  uint     m_row_count;         /* The number of rows added to the event */
2203 2204 2205 2206 2207 2208 2209 2210 2211 2212 2213 2214 2215 2216

protected:
  /* 
     The constructors are protected since you're supposed to inherit
     this class, not create instances of this class.
  */
#ifndef MYSQL_CLIENT
  Rows_log_event(THD*, TABLE*, ulong table_id, 
		 MY_BITMAP const *cols, bool is_transactional);
#endif
  Rows_log_event(const char *row_data, uint event_len, 
		 Log_event_type event_type,
		 const Format_description_log_event *description_event);

2217 2218 2219 2220
#ifdef MYSQL_CLIENT
  void print_helper(FILE *, PRINT_EVENT_INFO *, char const *const name);
#endif

2221 2222 2223 2224 2225 2226 2227 2228 2229 2230
#ifndef MYSQL_CLIENT
  virtual int do_add_row_data(byte *data, my_size_t length);
#endif

#ifndef MYSQL_CLIENT
  TABLE *m_table;		/* The table the rows belong to */
#endif
  ulong       m_table_id;	/* Table ID */
  MY_BITMAP   m_cols;		/* Bitmap denoting columns available */
  ulong       m_width;          /* The width of the columns bitmap */
2231 2232 2233 2234 2235 2236 2237 2238 2239
  /*
    Bitmap for columns available in the after image, if present. These
    fields are only available for Update_rows events. Observe that the
    width of both the before image COLS vector and the after image
    COLS vector is the same: the number of columns of the table on the
    master.
  */
  MY_BITMAP   m_cols_ai;

2240
  ulong       m_master_reclength; /* Length of record on master side */
2241

2242
  /* Bit buffers in the same memory as the class */
2243
  uint32    m_bitbuf[128/(sizeof(uint32)*8)];
2244
  uint32    m_bitbuf_ai[128/(sizeof(uint32)*8)];
2245 2246 2247 2248 2249 2250 2251 2252 2253 2254

  byte    *m_rows_buf;		/* The rows in packed format */
  byte    *m_rows_cur;		/* One-after the end of the data */
  byte    *m_rows_end;		/* One-after the end of the allocated space */

  flag_set m_flags;		/* Flags for row-level events */

private:

#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
2255
  virtual int do_apply_event(RELAY_LOG_INFO const *rli);
2256
  virtual int do_update_pos(RELAY_LOG_INFO *rli);
2257

2258 2259 2260 2261 2262 2263 2264 2265 2266 2267 2268 2269 2270 2271 2272 2273 2274 2275 2276 2277 2278 2279 2280 2281 2282 2283 2284 2285 2286 2287 2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300
  /*
    Primitive to prepare for a sequence of row executions.

    DESCRIPTION

      Before doing a sequence of do_prepare_row() and do_exec_row()
      calls, this member function should be called to prepare for the
      entire sequence. Typically, this member function will allocate
      space for any buffers that are needed for the two member
      functions mentioned above.

    RETURN VALUE

      The member function will return 0 if all went OK, or a non-zero
      error code otherwise.
  */
  virtual int do_before_row_operations(TABLE *table) = 0;

  /*
    Primitive to clean up after a sequence of row executions.

    DESCRIPTION
    
      After doing a sequence of do_prepare_row() and do_exec_row(),
      this member function should be called to clean up and release
      any allocated buffers.
  */
  virtual int do_after_row_operations(TABLE *table, int error) = 0;

  /*
    Primitive to prepare for handling one row in a row-level event.
    
    DESCRIPTION 

      The member function prepares for execution of operations needed for one
      row in a row-level event by reading up data from the buffer containing
      the row. No specific interpretation of the data is normally done here,
      since SQL thread specific data is not available: that data is made
      available for the do_exec function.

      A pointer to the start of the next row, or NULL if the preparation
      failed. Currently, preparation cannot fail, but don't rely on this
      behavior. 
2301 2302 2303

    RETURN VALUE
      Error code, if something went wrong, 0 otherwise.
2304
   */
2305
  virtual int do_prepare_row(THD*, RELAY_LOG_INFO const*, TABLE*,
2306
                             char const *row_start, char const **row_end) = 0;
2307 2308 2309 2310 2311 2312 2313 2314 2315 2316 2317 2318 2319 2320 2321 2322 2323 2324 2325 2326 2327 2328 2329 2330 2331 2332 2333 2334 2335 2336 2337 2338 2339 2340 2341 2342 2343 2344 2345 2346 2347 2348

  /*
    Primitive to do the actual execution necessary for a row.

    DESCRIPTION
      The member function will do the actual execution needed to handle a row.

    RETURN VALUE
      0 if execution succeeded, 1 if execution failed.
      
  */
  virtual int do_exec_row(TABLE *table) = 0;
#endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */
};


/*****************************************************************************

  Write row log event class

  Log row insertions and updates. The event contain several
  insert/update rows for a table. Note that each event contains only
  rows for one table.

 ****************************************************************************/
class Write_rows_log_event : public Rows_log_event
{
public:
  enum 
  {
    /* Support interface to THD::binlog_prepare_pending_rows_event */
    TYPE_CODE = WRITE_ROWS_EVENT
  };

#if !defined(MYSQL_CLIENT)
  Write_rows_log_event(THD*, TABLE*, ulong table_id, 
		       MY_BITMAP const *cols, bool is_transactional);
#endif
#ifdef HAVE_REPLICATION
  Write_rows_log_event(const char *buf, uint event_len, 
                       const Format_description_log_event *description_event);
#endif
2349
#if !defined(MYSQL_CLIENT) 
2350 2351 2352 2353 2354 2355 2356 2357 2358 2359 2360 2361 2362 2363 2364 2365 2366 2367 2368 2369 2370 2371
  static bool binlog_row_logging_function(THD *thd, TABLE *table,
                                          bool is_transactional,
                                          MY_BITMAP *cols,
                                          uint fields,
                                          const byte *before_record
                                          __attribute__((unused)),
                                          const byte *after_record)
  {
    return thd->binlog_write_row(table, is_transactional,
                                 cols, fields, after_record);
  }
#endif

private:
  virtual Log_event_type get_type_code() { return (Log_event_type)TYPE_CODE; }

#ifdef MYSQL_CLIENT
  void print(FILE *file, PRINT_EVENT_INFO *print_event_info);
#endif

#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
  gptr  m_memory;
2372
  byte *m_after_image;
2373

2374 2375
  virtual int do_before_row_operations(TABLE *table);
  virtual int do_after_row_operations(TABLE *table, int error);
2376
  virtual int do_prepare_row(THD*, RELAY_LOG_INFO const*, TABLE*,
2377 2378
                             char const *row_start, char const **row_end);
  virtual int do_exec_row(TABLE *table);
2379 2380 2381 2382 2383 2384 2385 2386 2387 2388 2389 2390 2391 2392 2393 2394 2395 2396 2397 2398 2399 2400 2401 2402 2403 2404
#endif
};


/*****************************************************************************

  Update rows log event class

  Log row updates with a before image. The event contain several
  update rows for a table. Note that each event contains only rows for
  one table.

  Also note that the row data consists of pairs of row data: one row
  for the old data and one row for the new data.

 ****************************************************************************/
class Update_rows_log_event : public Rows_log_event
{
public:
  enum 
  {
    /* Support interface to THD::binlog_prepare_pending_rows_event */
    TYPE_CODE = UPDATE_ROWS_EVENT
  };

#ifndef MYSQL_CLIENT
2405 2406 2407 2408 2409 2410 2411 2412 2413 2414
  Update_rows_log_event(THD*, TABLE*, ulong table_id,
			MY_BITMAP const *cols_bi,
			MY_BITMAP const *cols_ai,
                        bool is_transactional);

  Update_rows_log_event(THD*, TABLE*, ulong table_id,
			MY_BITMAP const *cols,
                        bool is_transactional);

  void init(MY_BITMAP const *cols);
2415 2416
#endif

2417 2418
  virtual ~Update_rows_log_event();

2419 2420 2421 2422 2423
#ifdef HAVE_REPLICATION
  Update_rows_log_event(const char *buf, uint event_len, 
			const Format_description_log_event *description_event);
#endif

2424
#if !defined(MYSQL_CLIENT) 
2425 2426 2427 2428 2429 2430 2431 2432 2433 2434 2435 2436
  static bool binlog_row_logging_function(THD *thd, TABLE *table,
                                          bool is_transactional,
                                          MY_BITMAP *cols,
                                          uint fields,
                                          const byte *before_record,
                                          const byte *after_record)
  {
    return thd->binlog_update_row(table, is_transactional,
                                  cols, fields, before_record, after_record);
  }
#endif

2437 2438 2439 2440 2441
  virtual bool is_valid() const
  {
    return Rows_log_event::is_valid() && m_cols_ai.bitmap;
  }

2442
protected:
2443 2444 2445 2446 2447 2448 2449 2450 2451
  virtual Log_event_type get_type_code() { return (Log_event_type)TYPE_CODE; }

#ifdef MYSQL_CLIENT
  void print(FILE *file, PRINT_EVENT_INFO *print_event_info);
#endif

#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
  gptr  m_memory;
  byte *m_key;
2452
  byte *m_after_image;
2453

2454 2455
  virtual int do_before_row_operations(TABLE *table);
  virtual int do_after_row_operations(TABLE *table, int error);
2456
  virtual int do_prepare_row(THD*, RELAY_LOG_INFO const*, TABLE*,
2457 2458
                             char const *row_start, char const **row_end);
  virtual int do_exec_row(TABLE *table);
2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479 2480 2481 2482 2483 2484 2485 2486 2487 2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498
#endif /* !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION) */
};

/*****************************************************************************

  Delete rows log event class.

  Log row deletions. The event contain several delete rows for a
  table. Note that each event contains only rows for one table.

  RESPONSIBILITIES

    - Act as a container for rows that has been deleted on the master
      and should be deleted on the slave. 

  COLLABORATION

    Row_writer
      Create the event and add rows to the event.
    Row_reader
      Extract the rows from the event.

 ****************************************************************************/
class Delete_rows_log_event : public Rows_log_event
{
public:
  enum 
  {
    /* Support interface to THD::binlog_prepare_pending_rows_event */
    TYPE_CODE = DELETE_ROWS_EVENT
  };

#ifndef MYSQL_CLIENT
  Delete_rows_log_event(THD*, TABLE*, ulong, 
			MY_BITMAP const *cols, bool is_transactional);
#endif
#ifdef HAVE_REPLICATION
  Delete_rows_log_event(const char *buf, uint event_len, 
			const Format_description_log_event *description_event);
#endif
2499
#if !defined(MYSQL_CLIENT) 
2500 2501 2502 2503 2504 2505 2506 2507 2508 2509 2510 2511 2512
  static bool binlog_row_logging_function(THD *thd, TABLE *table,
                                          bool is_transactional,
                                          MY_BITMAP *cols,
                                          uint fields,
                                          const byte *before_record,
                                          const byte *after_record
                                          __attribute__((unused)))
  {
    return thd->binlog_delete_row(table, is_transactional,
                                  cols, fields, before_record);
  }
#endif
  
2513
protected:
2514 2515 2516 2517 2518 2519 2520 2521 2522
  virtual Log_event_type get_type_code() { return (Log_event_type)TYPE_CODE; }

#ifdef MYSQL_CLIENT
  void print(FILE *file, PRINT_EVENT_INFO *print_event_info);
#endif

#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
  gptr  m_memory;
  byte *m_key;
2523
  byte *m_after_image;
2524

2525 2526
  virtual int do_before_row_operations(TABLE *table);
  virtual int do_after_row_operations(TABLE *table, int error);
2527
  virtual int do_prepare_row(THD*, RELAY_LOG_INFO const*, TABLE*,
2528 2529
                             char const *row_start, char const **row_end);
  virtual int do_exec_row(TABLE *table);
2530 2531 2532
#endif
};

2533

2534 2535
#include "log_event_old.h"

2536 2537 2538 2539 2540 2541 2542 2543 2544 2545 2546 2547 2548 2549 2550 2551 2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595 2596 2597 2598 2599 2600 2601 2602 2603 2604
/**
   Class representing an incident, an occurance out of the ordinary,
   that happened on the master.

   The event is used to inform the slave that something out of the
   ordinary happened on the master that might cause the database to be
   in an inconsistent state.

   <table id="IncidentFormat">
   <caption>Incident event format</caption>
   <tr>
     <th>Symbol</th>
     <th>Size<br/>(bytes)</th>
     <th>Description</th>
   </tr>
   <tr>
     <td>INCIDENT</td>
     <td align="right">2</td>
     <td>Incident number as an unsigned integer</td>
   </tr>
   <tr>
     <td>MSGLEN</td>
     <td align="right">1</td>
     <td>Message length as an unsigned integer</td>
   </tr>
   <tr>
     <td>MESSAGE</td>
     <td align="right">MSGLEN</td>
     <td>The message, if present. Not null terminated.</td>
   </tr>
   </table>
 */
class Incident_log_event : public Log_event {
public:
#ifndef MYSQL_CLIENT
  Incident_log_event(THD *thd_arg, Incident incident)
    : Log_event(thd_arg, 0, FALSE), m_incident(incident)
  {
    DBUG_ENTER("Incident_log_event::Incident_log_event");
    DBUG_PRINT("enter", ("m_incident: %d", m_incident));
    m_message.str= NULL;                    /* Just as a precaution */
    m_message.length= 0;
    DBUG_VOID_RETURN;
  }

  Incident_log_event(THD *thd_arg, Incident incident, LEX_STRING const msg)
    : Log_event(thd_arg, 0, FALSE), m_incident(incident)
  {
    DBUG_ENTER("Incident_log_event::Incident_log_event");
    DBUG_PRINT("enter", ("m_incident: %d", m_incident));
    m_message= msg;
    DBUG_VOID_RETURN;
  }
#endif

#ifndef MYSQL_CLIENT
  void pack_info(Protocol*);
#endif

  Incident_log_event(const char *buf, uint event_len,
                     const Format_description_log_event *descr_event);

  virtual ~Incident_log_event();

#ifdef MYSQL_CLIENT
  virtual void print(FILE *file, PRINT_EVENT_INFO *print_event_info);
#endif

#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
2605
  virtual int do_apply_event(RELAY_LOG_INFO const *rli);
2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624
#endif

  virtual bool write_data_header(IO_CACHE *file);
  virtual bool write_data_body(IO_CACHE *file);

  virtual Log_event_type get_type_code() { return INCIDENT_EVENT; }

  virtual bool is_valid() const { return 1; }
  virtual int get_data_size() {
    return INCIDENT_HEADER_LEN + 1 + m_message.length;
  }

private:
  const char *description() const;

  Incident m_incident;
  LEX_STRING m_message;
};

2625 2626 2627 2628 2629 2630 2631 2632
static inline bool copy_event_cache_to_file_and_reinit(IO_CACHE *cache,
                                                       FILE *file)
{
  return         
    my_b_copy_to_file(cache, file) ||
    reinit_io_cache(cache, WRITE_CACHE, 0, FALSE, TRUE);
}

2633
#endif /* _log_event_h */