[Commits] 2a181ea: MDEV-8713 Add continuous binary log backup to mysqlbinlog.

Alexey Botchkov holyfoot at askmonty.org
Fri Nov 27 14:40:25 EET 2015


revision-id: 2a181ea7b16dcbc6dd30af5a2396760261d7d500 (mariadb-10.1.8-81-g2a181ea)
parent(s): 9d5c9379a6fd3662d4388cda177a3b1ea7b070cc
committer: Alexey Botchkov
timestamp: 2015-11-27 16:33:23 +0400
message:

MDEV-8713 Add continuous binary log backup to mysqlbinlog.
        --raw, --stop-never and --stop-never-slave-server-id=id options
        added to the mysqlbinlog tool.

---
 client/client_priv.h                     |   1 +
 client/mysqlbinlog.cc                    | 515 ++++++++++++++++++++++---------
 mysql-test/r/mysqlbinlog_raw_mode.result | 280 +++++++++++++++++
 mysql-test/t/mysqlbinlog_raw_mode.test   | 387 +++++++++++++++++++++++
 sql/sql_priv.h                           |   4 +-
 5 files changed, 1035 insertions(+), 152 deletions(-)

diff --git a/client/client_priv.h b/client/client_priv.h
index 656c8fc..44f0b21 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -92,6 +92,7 @@ enum options_client
   OPT_REPORT_PROGRESS,
   OPT_SKIP_ANNOTATE_ROWS_EVENTS,
   OPT_SSL_CRL, OPT_SSL_CRLPATH,
+  OPT_RAW_OUTPUT, OPT_WAIT_SERVER_ID, OPT_STOP_NEVER,
   OPT_MAX_CLIENT_OPTION /* should be always the last */
 };
 
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index 5b07232..a2509b7 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -73,6 +73,8 @@ ulong opt_binlog_rows_event_max_size;
 uint test_flags = 0; 
 static uint opt_protocol= 0;
 static FILE *result_file;
+static char *result_file_name= 0;
+static const char *output_prefix= "";
 
 #ifndef DBUG_OFF
 static const char* default_dbug_option = "d:t:o,/tmp/mysqlbinlog.trace";
@@ -96,6 +98,8 @@ static char* database= 0;
 static my_bool force_opt= 0, short_form= 0, remote_opt= 0;
 static my_bool debug_info_flag, debug_check_flag;
 static my_bool force_if_open_opt= 1;
+static my_bool opt_raw_mode= 0, opt_stop_never= 0;
+static int64 opt_stop_never_slave_server_id= -1;
 static my_bool opt_verify_binlog_checksum= 1;
 static ulonglong offset = 0;
 static char* host = 0;
@@ -120,7 +124,6 @@ static ulonglong start_position, stop_position;
 static char *start_datetime_str, *stop_datetime_str;
 static my_time_t start_datetime= 0, stop_datetime= MY_TIME_T_MAX;
 static ulonglong rec_count= 0;
-static short binlog_flags = 0; 
 static MYSQL* mysql = NULL;
 static const char* dirname_for_local_load= 0;
 static bool opt_skip_annotate_row_events= 0;
@@ -142,7 +145,9 @@ enum Exit_status {
   /** An error occurred and execution should stop. */
   ERROR_STOP,
   /** No error occurred but execution should stop. */
-  OK_STOP
+  OK_STOP,
+  /** No error occurred - end of file reached. */
+  OK_EOF,
 };
 
 /**
@@ -1368,8 +1373,14 @@ static struct my_option my_options[] =
   {"read-from-remote-server", 'R', "Read binary logs from a MySQL server.",
    &remote_opt, &remote_opt, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
    0, 0},
-  {"result-file", 'r', "Direct output to a given file.", 0, 0, 0, GET_STR,
-   REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+  {"raw", OPT_RAW_OUTPUT, "Requires -R. Output raw binlog data instead of SQL "
+   "statements and write it to files corresponding to server logs.",
+   &opt_raw_mode, &opt_raw_mode, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
+   0, 0},
+  {"result-file", 'r', "Direct output to a given file. With --raw this is a "
+   "prefix for the file names.",
+   &result_file_name, &result_file_name, 0, GET_STR, REQUIRED_ARG,
+   0, 0, 0, 0, 0, 0},
   {"server-id", 0,
    "Extract only binlog entries created by the server having the given id.",
    &server_id, &server_id, 0, GET_ULONG,
@@ -1418,6 +1429,16 @@ static struct my_option my_options[] =
    "(you should probably use quotes for your shell to set it properly).",
    &stop_datetime_str, &stop_datetime_str,
    0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+  {"stop-never", OPT_STOP_NEVER, "Wait for more data from the server "
+   "instead of stopping at the end of the last log. Implicitly sets "
+   "--to-last-log but instead of stopping at the end of the last log "
+   "it continues to wait till the server disconnects.",
+   &opt_stop_never, &opt_stop_never, 0,
+   GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+  {"stop-never-slave-server-id", OPT_WAIT_SERVER_ID,
+   "The slave server_id used for --read-from-remote-server --stop-never.",
+   &opt_stop_never_slave_server_id, &opt_stop_never_slave_server_id, 0,
+   GET_LL, REQUIRED_ARG, -1, -1, 0xFFFFFFFFLL, 0, 0, 0},
   {"stop-position", OPT_STOP_POSITION,
    "Stop reading the binlog at position N. Applies to the last binlog "
    "passed on the command line.",
@@ -1618,10 +1639,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
     else
       tty_password=1;
     break;
-  case 'r':
-    if (!(result_file = my_fopen(argument, O_WRONLY | O_BINARY, MYF(MY_WME))))
-      exit(1);
-    break;
   case 'R':
     remote_opt= 1;
     break;
@@ -1701,6 +1718,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
     print_version();
     opt_version= 1;
     break;
+  case OPT_STOP_NEVER:
+    to_last_remote_log= 1;
+    break;
   case '?':
     usage();
     opt_version= 1;
@@ -1717,7 +1737,6 @@ static int parse_args(int *argc, char*** argv)
 {
   int ho_error;
 
-  result_file = stdout;
   if ((ho_error=handle_options(argc, argv, my_options, get_one_option)))
     exit(ho_error);
   if (debug_info_flag)
@@ -1807,7 +1826,8 @@ static Exit_status dump_log_entries(const char* logname)
      Set safe delimiter, to dump things
      like CREATE PROCEDURE safely
   */
-  fprintf(result_file, "DELIMITER /*!*/;\n");
+  if (!opt_raw_mode)
+    fprintf(result_file, "DELIMITER /*!*/;\n");
   strmov(print_event_info.delimiter, "/*!*/;");
   
   print_event_info.verbose= short_form ? 0 : verbose;
@@ -1816,7 +1836,8 @@ static Exit_status dump_log_entries(const char* logname)
        dump_local_log_entries(&print_event_info, logname));
 
   /* Set delimiter back to semicolon */
-  fprintf(result_file, "DELIMITER ;\n");
+  if (!opt_raw_mode)
+    fprintf(result_file, "DELIMITER ;\n");
   strmov(print_event_info.delimiter, ";");
   return rc;
 }
@@ -1922,6 +1943,240 @@ static Exit_status check_master_version()
 }
 
 
+static Exit_status handle_event_text_mode(PRINT_EVENT_INFO *print_event_info,
+                                          ulong *len,
+                                          const char* logname,
+                                          uint logname_len, my_off_t old_off)
+{
+  const char *error_msg;
+  Log_event *ev;
+  NET *net= &mysql->net;
+  DBUG_ENTER("handle_event_text_mode");
+
+  if (net->read_pos[5] == ANNOTATE_ROWS_EVENT)
+  {
+    if (!(ev= read_remote_annotate_event(net->read_pos + 1, *len - 1,
+                                         &error_msg)))
+    {
+      error("Could not construct annotate event object: %s", error_msg);
+      DBUG_RETURN(ERROR_STOP);
+    }   
+  }
+  else
+  {
+    if (!(ev= Log_event::read_log_event((const char*) net->read_pos + 1 ,
+                                        *len - 1, &error_msg,
+                                        glob_description_event,
+                                        opt_verify_binlog_checksum)))
+    {
+      error("Could not construct log event object: %s", error_msg);
+      DBUG_RETURN(ERROR_STOP);
+    }   
+    /*
+      If reading from a remote host, ensure the temp_buf for the
+      Log_event class is pointing to the incoming stream.
+    */
+    ev->register_temp_buf((char *) net->read_pos + 1, FALSE);
+  }
+
+  Log_event_type type= ev->get_type_code();
+  if (glob_description_event->binlog_version >= 3 ||
+      (type != LOAD_EVENT && type != CREATE_FILE_EVENT))
+  {
+    /*
+      If this is a Rotate event, maybe it's the end of the requested binlog;
+      in this case we are done (stop transfer).
+      This is suitable for binlogs, not relay logs (but for now we don't read
+      relay logs remotely because the server is not able to do that). If one
+      day we read relay logs remotely, then we will have a problem with the
+      detection below: relay logs contain Rotate events which are about the
+      binlogs, so which would trigger the end-detection below.
+    */
+    if (type == ROTATE_EVENT)
+    {
+      Rotate_log_event *rev= (Rotate_log_event *)ev;
+      /*
+        If this is a fake Rotate event, and not about our log, we can stop
+        transfer. If this a real Rotate event (so it's not about our log,
+        it's in our log describing the next log), we print it (because it's
+        part of our log) and then we will stop when we receive the fake one
+        soon.
+      */
+      if (rev->when == 0)
+      {
+        if (!to_last_remote_log)
+        {
+          if ((rev->ident_len != logname_len) ||
+              memcmp(rev->new_log_ident, logname, logname_len))
+          {
+            DBUG_RETURN(OK_EOF);
+          }
+          /*
+            Otherwise, this is a fake Rotate for our log, at the very
+            beginning for sure. Skip it, because it was not in the original
+            log. If we are running with to_last_remote_log, we print it,
+            because it serves as a useful marker between binlogs then.
+          */
+          DBUG_RETURN(OK_CONTINUE);
+        }
+        *len= 1; // fake Rotate, so don't increment old_off
+      }
+    }
+    else if (type == FORMAT_DESCRIPTION_EVENT)
+    {
+      /*
+        This could be an fake Format_description_log_event that server
+        (5.0+) automatically sends to a slave on connect, before sending
+        a first event at the requested position.  If this is the case,
+        don't increment old_off. Real Format_description_log_event always
+        starts from BIN_LOG_HEADER_SIZE position.
+      */
+      if (old_off != BIN_LOG_HEADER_SIZE)
+        *len= 1;         // fake event, don't increment old_off
+    }
+    Exit_status retval= process_event(print_event_info, ev, old_off, logname);
+    if (retval != OK_CONTINUE)
+      DBUG_RETURN(retval);
+  }
+  else
+  {
+    Load_log_event *le= (Load_log_event*)ev;
+    const char *old_fname= le->fname;
+    uint old_len= le->fname_len;
+    File file;
+    Exit_status retval;
+    char fname[FN_REFLEN+1];
+
+    if ((file= load_processor.prepare_new_file_for_old_format(le,fname)) < 0)
+      DBUG_RETURN(ERROR_STOP);
+
+    retval= process_event(print_event_info, ev, old_off, logname);
+    if (retval != OK_CONTINUE)
+    {
+      my_close(file,MYF(MY_WME));
+      DBUG_RETURN(retval);
+    }
+    retval= load_processor.load_old_format_file(net,old_fname,old_len,file);
+    my_close(file,MYF(MY_WME));
+    if (retval != OK_CONTINUE)
+      DBUG_RETURN(retval);
+  }
+
+  DBUG_RETURN(OK_CONTINUE);
+}
+
+
+static char out_file_name[FN_REFLEN + 1];
+
+static Exit_status handle_event_raw_mode(PRINT_EVENT_INFO *print_event_info,
+                                         ulong *len,
+                                         const char* logname, uint logname_len)
+{
+  const char *error_msg;
+  const unsigned char *read_pos= mysql->net.read_pos + 1;
+  Log_event_type type;
+  DBUG_ENTER("handle_event_raw_mode");
+  DBUG_ASSERT(opt_raw_mode && remote_opt);
+
+  type= (Log_event_type) read_pos[EVENT_TYPE_OFFSET];
+
+  if (type == HEARTBEAT_LOG_EVENT)
+    DBUG_RETURN(OK_CONTINUE);
+
+  if (type == ROTATE_EVENT || type == FORMAT_DESCRIPTION_EVENT)
+  {
+    Log_event *ev;
+    if (!(ev= Log_event::read_log_event((const char*) read_pos ,
+                                        *len - 1, &error_msg,
+                                        glob_description_event,
+                                        opt_verify_binlog_checksum)))
+    {
+      error("Could not construct annotate event object: %s", error_msg);
+      DBUG_RETURN(ERROR_STOP);
+    }
+    /*
+      If reading from a remote host, ensure the temp_buf for the
+      Log_event class is pointing to the incoming stream.
+    */
+    ev->register_temp_buf((char *) read_pos, FALSE);
+
+    if (type == ROTATE_EVENT)
+    {
+      Exit_status ret_val= OK_CONTINUE;
+      Rotate_log_event *rev= (Rotate_log_event *)ev;
+      char *pe= strmake(out_file_name, output_prefix, sizeof(out_file_name)-1);
+      strmake(pe, rev->new_log_ident, sizeof(out_file_name) - (pe-out_file_name));
+
+      /*
+        If this is a fake Rotate event, and not about our log, we can stop
+        transfer. If this a real Rotate event (so it's not about our log,
+        it's in our log describing the next log), we print it (because it's
+        part of our log) and then we will stop when we receive the fake one
+        soon.
+      */
+      if (rev->when == 0)
+      {
+        if (!to_last_remote_log)
+        {
+          if ((rev->ident_len != logname_len) ||
+              memcmp(rev->new_log_ident, logname, logname_len))
+          {
+            ret_val= OK_EOF;
+          }
+          /*
+            Otherwise, this is a fake Rotate for our log, at the very
+            beginning for sure. Skip it, because it was not in the original
+            log. If we are running with to_last_remote_log, we print it,
+            because it serves as a useful marker between binlogs then.
+          */
+        }
+        *len= 1; // fake Rotate, so don't increment old_off
+      }
+      ev->temp_buf= 0;
+      delete ev;
+      DBUG_RETURN(ret_val);
+    }
+    else /* if (type == FORMAT_DESCRIPTION_EVENT */
+    {
+      DBUG_ASSERT(type == FORMAT_DESCRIPTION_EVENT);
+
+      if (result_file)
+        my_fclose(result_file, MYF(0));
+
+      if (!(result_file= my_fopen(out_file_name,
+                                  O_WRONLY | O_BINARY, MYF(MY_WME))))
+      {
+        error("Could not create output log file: %s", out_file_name);
+        DBUG_RETURN(ERROR_STOP);
+      }
+      /* TODO - add write error simulation here */
+
+      if (my_fwrite(result_file, (const uchar *) BINLOG_MAGIC,
+                    BIN_LOG_HEADER_SIZE, MYF(MY_NABP)))
+      {
+        error("Could not write into log file '%s'", out_file_name);
+        DBUG_RETURN(ERROR_STOP);
+      }
+
+      delete glob_description_event;
+      glob_description_event= (Format_description_log_event*) ev;
+      print_event_info->common_header_len=
+        glob_description_event->common_header_len;
+      ev->temp_buf= 0;
+      /* We do not want to delete the event here. */
+    }
+  }
+
+  if (my_fwrite(result_file, read_pos, *len - 1, MYF(MY_NABP)))
+  {
+    error("Could not write into log file '%s'", out_file_name);
+    DBUG_RETURN(ERROR_STOP);
+  }
+
+  DBUG_RETURN(OK_CONTINUE);
+}
+
+
 /**
   Requests binlog dump from a remote server and prints the events it
   receives.
@@ -1944,8 +2199,9 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
   uint logname_len;
   NET* net;
   my_off_t old_off= start_position_mot;
-  char fname[FN_REFLEN+1];
   Exit_status retval= OK_CONTINUE;
+  short binlog_flags = 0; 
+  ulong slave_id;
   DBUG_ENTER("dump_remote_log_entries");
 
   /*
@@ -1968,6 +2224,9 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
   int4store(buf, (uint32)start_position);
   if (!opt_skip_annotate_row_events)
     binlog_flags|= BINLOG_SEND_ANNOTATE_ROWS_EVENT;
+  if (!opt_stop_never)
+    binlog_flags|= BINLOG_DUMP_NON_BLOCK;
+
   int2store(buf + BIN_LOG_HEADER_SIZE, binlog_flags);
 
   size_t tlen = strlen(logname);
@@ -1977,7 +2236,15 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
     DBUG_RETURN(ERROR_STOP);
   }
   logname_len = (uint) tlen;
-  int4store(buf + 6, 0);
+  if (opt_stop_never)
+  {
+    DBUG_ASSERT(to_last_remote_log);
+    slave_id= (opt_stop_never_slave_server_id == -1) ?
+                1 : opt_stop_never_slave_server_id;
+  }
+  else
+    slave_id= 0;
+  int4store(buf + 6, slave_id);
   memcpy(buf + 10, logname, logname_len);
   if (simple_command(mysql, COM_BINLOG_DUMP, buf, logname_len + 10, 1))
   {
@@ -1987,9 +2254,6 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
 
   for (;;)
   {
-    const char *error_msg;
-    Log_event *ev;
-
     len= cli_safe_read(mysql);
     if (len == packet_error)
     {
@@ -2000,113 +2264,23 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
       break; // end of data
     DBUG_PRINT("info",( "len: %lu  net->read_pos[5]: %d\n",
 			len, net->read_pos[5]));
-    if (net->read_pos[5] == ANNOTATE_ROWS_EVENT)
+    if (opt_raw_mode)
     {
-      if (!(ev= read_remote_annotate_event(net->read_pos + 1, len - 1,
-                                           &error_msg)))
-      {
-        error("Could not construct annotate event object: %s", error_msg);
-        DBUG_RETURN(ERROR_STOP);
-      }   
+      retval= handle_event_raw_mode(print_event_info, &len,
+                                    logname, logname_len);
     }
     else
     {
-      if (!(ev= Log_event::read_log_event((const char*) net->read_pos + 1 ,
-                                          len - 1, &error_msg,
-                                          glob_description_event,
-                                          opt_verify_binlog_checksum)))
-      {
-        error("Could not construct log event object: %s", error_msg);
-        DBUG_RETURN(ERROR_STOP);
-      }   
-      /*
-        If reading from a remote host, ensure the temp_buf for the
-        Log_event class is pointing to the incoming stream.
-      */
-      ev->register_temp_buf((char *) net->read_pos + 1, FALSE);
+      retval= handle_event_text_mode(print_event_info, &len,
+                                     logname, logname_len, old_off);
     }
-
-    Log_event_type type= ev->get_type_code();
-    if (glob_description_event->binlog_version >= 3 ||
-        (type != LOAD_EVENT && type != CREATE_FILE_EVENT))
+    if (retval != OK_CONTINUE)
     {
-      /*
-        If this is a Rotate event, maybe it's the end of the requested binlog;
-        in this case we are done (stop transfer).
-        This is suitable for binlogs, not relay logs (but for now we don't read
-        relay logs remotely because the server is not able to do that). If one
-        day we read relay logs remotely, then we will have a problem with the
-        detection below: relay logs contain Rotate events which are about the
-        binlogs, so which would trigger the end-detection below.
-      */
-      if (type == ROTATE_EVENT)
-      {
-        Rotate_log_event *rev= (Rotate_log_event *)ev;
-        /*
-          If this is a fake Rotate event, and not about our log, we can stop
-          transfer. If this a real Rotate event (so it's not about our log,
-          it's in our log describing the next log), we print it (because it's
-          part of our log) and then we will stop when we receive the fake one
-          soon.
-        */
-        if (rev->when == 0)
-        {
-          if (!to_last_remote_log)
-          {
-            if ((rev->ident_len != logname_len) ||
-                memcmp(rev->new_log_ident, logname, logname_len))
-            {
-              DBUG_RETURN(OK_CONTINUE);
-            }
-            /*
-              Otherwise, this is a fake Rotate for our log, at the very
-              beginning for sure. Skip it, because it was not in the original
-              log. If we are running with to_last_remote_log, we print it,
-              because it serves as a useful marker between binlogs then.
-            */
-            continue;
-          }
-          len= 1; // fake Rotate, so don't increment old_off
-        }
-      }
-      else if (type == FORMAT_DESCRIPTION_EVENT)
-      {
-        /*
-          This could be an fake Format_description_log_event that server
-          (5.0+) automatically sends to a slave on connect, before sending
-          a first event at the requested position.  If this is the case,
-          don't increment old_off. Real Format_description_log_event always
-          starts from BIN_LOG_HEADER_SIZE position.
-        */
-        if (old_off != BIN_LOG_HEADER_SIZE)
-          len= 1;         // fake event, don't increment old_off
-      }
-      Exit_status retval= process_event(print_event_info, ev, old_off, logname);
-      if (retval != OK_CONTINUE)
-        DBUG_RETURN(retval);
+      if (retval == OK_EOF)
+        break;
+      DBUG_RETURN(retval);
     }
-    else
-    {
-      Load_log_event *le= (Load_log_event*)ev;
-      const char *old_fname= le->fname;
-      uint old_len= le->fname_len;
-      File file;
-      Exit_status retval;
 
-      if ((file= load_processor.prepare_new_file_for_old_format(le,fname)) < 0)
-        DBUG_RETURN(ERROR_STOP);
-
-      retval= process_event(print_event_info, ev, old_off, logname);
-      if (retval != OK_CONTINUE)
-      {
-        my_close(file,MYF(MY_WME));
-        DBUG_RETURN(retval);
-      }
-      retval= load_processor.load_old_format_file(net,old_fname,old_len,file);
-      my_close(file,MYF(MY_WME));
-      if (retval != OK_CONTINUE)
-        DBUG_RETURN(retval);
-    }
     /*
       Let's adjust offset for remote log as for local log to produce
       similar text and to have --stop-position to work identically.
@@ -2443,6 +2617,7 @@ static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info,
   return retval;
 }
 
+
 int main(int argc, char** argv)
 {
   char **defaults_argv;
@@ -2489,6 +2664,40 @@ int main(int argc, char** argv)
 
   my_set_max_open_files(open_files_limit);
 
+  if (opt_raw_mode)
+  {
+    if (!remote_opt)
+    {
+      error("The --raw mode only works with --read-from-remote-server");
+      exit(1);
+    }
+    if (one_database)
+      warning("The --database option is ignored in raw mode");
+
+    if (stop_position != (ulonglong)(~(my_off_t)0))
+      warning("The --stop-position option is ignored in raw mode");
+
+    if (stop_datetime != MY_TIME_T_MAX)
+      warning("The --stop-datetime option is ignored in raw mode");
+    result_file= 0;
+    if (result_file_name)
+      output_prefix= result_file_name;
+  }
+  else
+  {
+    if (result_file_name)
+    {
+      if (!(result_file= my_fopen(result_file_name,
+                                  O_WRONLY | O_BINARY, MYF(MY_WME))))
+      {
+        error("Could not create log file '%s'", result_file_name);
+        exit(1);
+      }
+    }
+    else
+      result_file= stdout;
+  }
+
   MY_TMPDIR tmpdir;
   tmpdir.list= 0;
   if (!dirname_for_local_load)
@@ -2505,29 +2714,32 @@ int main(int argc, char** argv)
   else
     load_processor.init_by_cur_dir();
 
-  fprintf(result_file, "/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;\n");
-
-  fprintf(result_file,
-	  "/*!40019 SET @@session.max_insert_delayed_threads=0*/;\n");
+  if (!opt_raw_mode)
+  {
+    fprintf(result_file, "/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;\n");
 
-  if (disable_log_bin)
     fprintf(result_file,
-            "/*!32316 SET @OLD_SQL_LOG_BIN=@@SQL_LOG_BIN, SQL_LOG_BIN=0*/;\n");
+	    "/*!40019 SET @@session.max_insert_delayed_threads=0*/;\n");
 
-  /*
-    In mysqlbinlog|mysql, don't want mysql to be disconnected after each
-    transaction (which would be the case with GLOBAL.COMPLETION_TYPE==2).
-  */
-  fprintf(result_file,
-          "/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,"
-          "COMPLETION_TYPE=0*/;\n");
+    if (disable_log_bin)
+      fprintf(result_file,
+              "/*!32316 SET @OLD_SQL_LOG_BIN=@@SQL_LOG_BIN, SQL_LOG_BIN=0*/;\n");
 
-  if (charset)
+    /*
+      In mysqlbinlog|mysql, don't want mysql to be disconnected after each
+      transaction (which would be the case with GLOBAL.COMPLETION_TYPE==2).
+    */
     fprintf(result_file,
-            "\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;"
-            "\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;"
-            "\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;"  
-            "\n/*!40101 SET NAMES %s */;\n", charset);
+            "/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,"
+            "COMPLETION_TYPE=0*/;\n");
+
+    if (charset)
+      fprintf(result_file,
+              "\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;"
+              "\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;"
+              "\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;"  
+              "\n/*!40101 SET NAMES %s */;\n", charset);
+  }
 
   for (save_stop_position= stop_position, stop_position= ~(my_off_t)0 ;
        (--argc >= 0) ; )
@@ -2541,27 +2753,30 @@ int main(int argc, char** argv)
     start_position= BIN_LOG_HEADER_SIZE;
   }
 
-  /*
-    Issue a ROLLBACK in case the last printed binlog was crashed and had half
-    of transaction.
-  */
-  fprintf(result_file,
-          "# End of log file\nROLLBACK /* added by mysqlbinlog */;\n"
-          "/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;\n");
-  if (disable_log_bin)
-    fprintf(result_file, "/*!32316 SET SQL_LOG_BIN=@OLD_SQL_LOG_BIN*/;\n");
-
-  if (charset)
+  if (!opt_raw_mode)
+  {
+    /*
+      Issue a ROLLBACK in case the last printed binlog was crashed and had half
+      of transaction.
+    */
     fprintf(result_file,
-            "/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n"
-            "/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n"
-            "/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n");
-
-  fprintf(result_file, "/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;\n");
+            "# End of log file\nROLLBACK /* added by mysqlbinlog */;\n"
+            "/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;\n");
+    if (disable_log_bin)
+      fprintf(result_file, "/*!32316 SET SQL_LOG_BIN=@OLD_SQL_LOG_BIN*/;\n");
+
+    if (charset)
+      fprintf(result_file,
+              "/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n"
+              "/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n"
+              "/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n");
+
+    fprintf(result_file, "/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;\n");
+  }
 
   if (tmpdir.list)
     free_tmpdir(&tmpdir);
-  if (result_file != stdout)
+  if (result_file && result_file != stdout)
     my_fclose(result_file, MYF(0));
   cleanup();
   free_annotate_event();
diff --git a/mysql-test/r/mysqlbinlog_raw_mode.result b/mysql-test/r/mysqlbinlog_raw_mode.result
new file mode 100644
index 0000000..4dc8086
--- /dev/null
+++ b/mysql-test/r/mysqlbinlog_raw_mode.result
@@ -0,0 +1,280 @@
+reset master;
+set timestamp=1000000000;
+drop table if exists t1;
+CREATE TABLE t1 (c01 BIT);
+INSERT INTO t1 VALUES (0);
+INSERT INTO t1 VALUES (1);
+DROP TABLE t1;
+CREATE TABLE t1 (c01 BIT(7));
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (16);
+INSERT INTO t1 VALUES (32);
+INSERT INTO t1 VALUES (64);
+INSERT INTO t1 VALUES (127);
+DELETE FROM t1 WHERE c01=127;
+UPDATE t1 SET c01=15 WHERE c01=16;
+DROP TABLE t1;
+CREATE TABLE t1 (a BIT(20), b CHAR(2));
+INSERT INTO t1 VALUES (b'00010010010010001001', 'ab');
+DROP TABLE t1;
+CREATE TABLE t1 (c02 BIT(64));
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (128);
+INSERT INTO t1 VALUES (b'1111111111111111111111111111111111111111111111111111111111111111');
+DROP TABLE t1;
+CREATE TABLE t1 (c03 TINYINT);
+INSERT INTO t1 VALUES (1),(2),(3);
+INSERT INTO t1 VALUES (-128);
+UPDATE t1 SET c03=2 WHERE c03=1;
+DELETE FROM t1 WHERE c03=-128;
+DROP TABLE t1;
+CREATE TABLE t1 (c04 TINYINT UNSIGNED);
+INSERT INTO t1 VALUES (128), (255);
+UPDATE t1 SET c04=2 WHERE c04=1;
+DELETE FROM t1 WHERE c04=255;
+DROP TABLE t1;
+CREATE TABLE t1 (c06 BOOL);
+INSERT INTO t1 VALUES (TRUE);
+DELETE FROM t1 WHERE c06=TRUE;
+DROP TABLE t1;
+CREATE TABLE t1 (c07 SMALLINT);
+INSERT INTO t1 VALUES (1234);
+DELETE FROM t1 WHERE c07=1234;
+DROP TABLE t1;
+CREATE TABLE t1 (c08 SMALLINT UNSIGNED);
+INSERT INTO t1 VALUES (32768), (65535);
+UPDATE t1 SET c08=2 WHERE c08=32768;
+DELETE FROM t1 WHERE c08=65535;
+DROP TABLE t1;
+CREATE TABLE t1 (c10 MEDIUMINT);
+INSERT INTO t1 VALUES (12345);
+DELETE FROM t1 WHERE c10=12345;
+DROP TABLE t1;
+CREATE TABLE t1 (c11 MEDIUMINT UNSIGNED);
+INSERT INTO t1 VALUES (8388608), (16777215);
+UPDATE t1 SET c11=2 WHERE c11=8388608;
+DELETE FROM t1 WHERE c11=16777215;
+DROP TABLE t1;
+CREATE TABLE t1 (c13 INT);
+INSERT INTO t1 VALUES (123456);
+DELETE FROM t1 WHERE c13=123456;
+DROP TABLE t1;
+CREATE TABLE t1 (c14 INT UNSIGNED);
+INSERT INTO t1 VALUES (2147483648), (4294967295);
+UPDATE t1 SET c14=2 WHERE c14=2147483648;
+DELETE FROM t1 WHERE c14=4294967295;
+DROP TABLE t1;
+CREATE TABLE t1 (c16 BIGINT);
+INSERT INTO t1 VALUES (1234567890);
+DELETE FROM t1 WHERE c16=1234567890;
+DROP TABLE t1;
+CREATE TABLE t1 (c17 BIGINT UNSIGNED);
+INSERT INTO t1 VALUES (9223372036854775808), (18446744073709551615);
+UPDATE t1 SET c17=2 WHERE c17=9223372036854775808;
+DELETE FROM t1 WHERE c17=18446744073709551615;
+DROP TABLE t1;
+CREATE TABLE t1 (c19 FLOAT);
+INSERT INTO t1 VALUES (123.2234);
+DELETE FROM t1 WHERE c19>123;
+DROP TABLE t1;
+CREATE TABLE t1 (c22 DOUBLE);
+INSERT INTO t1 VALUES (123434.22344545);
+DELETE FROM t1 WHERE c22>123434;
+DROP TABLE t1;
+CREATE TABLE t1 (c25 DECIMAL(10,5));
+INSERT INTO t1 VALUES (124.45);
+INSERT INTO t1 VALUES (-543.21);
+DELETE FROM t1 WHERE c25=124.45;
+DROP TABLE t1;
+CREATE TABLE t1 (c28 DATE);
+INSERT INTO t1 VALUES ('2001-02-03');
+DELETE FROM t1 WHERE c28='2001-02-03';
+DROP TABLE t1;
+CREATE TABLE t1 (c29 DATETIME);
+INSERT INTO t1 VALUES ('2001-02-03 10:20:30');
+DELETE FROM t1 WHERE c29='2001-02-03 10:20:30';
+DROP TABLE t1;
+CREATE TABLE t1 (c30 TIMESTAMP);
+INSERT INTO t1 VALUES ('2001-02-03 10:20:30');
+DELETE FROM t1 WHERE c30='2001-02-03 10:20:30';
+DROP TABLE t1;
+CREATE TABLE t1 (c31 TIME);
+INSERT INTO t1 VALUES ('11:22:33');
+DELETE FROM t1 WHERE c31='11:22:33';
+DROP TABLE t1;
+CREATE TABLE t1 (c32 YEAR);
+INSERT INTO t1 VALUES ('2001');
+DELETE FROM t1 WHERE c32=2001;
+DROP TABLE t1;
+CREATE TABLE t1 (c33 CHAR);
+INSERT INTO t1 VALUES ('a');
+DELETE FROM t1 WHERE c33='a';
+DROP TABLE t1;
+CREATE TABLE t1 (c34 CHAR(0));
+INSERT INTO t1 VALUES ('');
+DELETE FROM t1 WHERE c34='';
+DROP TABLE t1;
+CREATE TABLE t1 (c35 CHAR(1));
+INSERT INTO t1 VALUES ('b');
+DELETE FROM t1 WHERE c35='b';
+DROP TABLE t1;
+CREATE TABLE t1 (c36 CHAR(255));
+INSERT INTO t1 VALUES (repeat('c',255));
+DELETE FROM t1 WHERE c36>'c';
+DROP TABLE t1;
+CREATE TABLE t1 (c37 NATIONAL CHAR);
+INSERT INTO t1 VALUES ('a');
+DELETE FROM t1 WHERE c37='a';
+DROP TABLE t1;
+CREATE TABLE t1 (c38 NATIONAL CHAR(0));
+INSERT INTO t1 VALUES ('');
+DELETE FROM t1 WHERE c38='';
+DROP TABLE t1;
+CREATE TABLE t1 (c39 NATIONAL CHAR(1));
+INSERT INTO t1 VALUES ('a');
+DELETE FROM t1 WHERE c39='a';
+DROP TABLE t1;
+CREATE TABLE t1 (c40 NATIONAL CHAR(255));
+INSERT INTO t1 VALUES (repeat('a', 255));
+INSERT INTO t1 VALUES (repeat(_latin1 0xDF, 255));
+DELETE FROM t1 WHERE c40>'a';
+DROP TABLE t1;
+CREATE TABLE t1 (c45 VARCHAR(0));
+INSERT INTO t1 VALUES ('');
+DELETE FROM t1 WHERE c45='';
+DROP TABLE t1;
+CREATE TABLE t1 (c46 VARCHAR(1));
+INSERT INTO t1 VALUES ('a');
+DELETE FROM t1 WHERE c46='a';
+DROP TABLE t1;
+CREATE TABLE t1 (c47 VARCHAR(255));
+INSERT INTO t1 VALUES (repeat('a',255));
+DELETE FROM t1 WHERE c47>'a';
+DROP TABLE t1;
+CREATE TABLE t1 (c48 VARCHAR(261));
+INSERT INTO t1 VALUES (repeat('a',261));
+DELETE FROM t1 WHERE c48>'a';
+DROP TABLE t1;
+CREATE TABLE t1 (c49 NATIONAL VARCHAR(0));
+INSERT INTO t1 VALUES ('');
+DELETE FROM t1 WHERE c49='';
+DROP TABLE t1;
+CREATE TABLE t1 (c50 NATIONAL VARCHAR(1));
+INSERT INTO t1 VALUES ('a');
+DELETE FROM t1 WHERE c50='a';
+DROP TABLE t1;
+CREATE TABLE t1 (c51 NATIONAL VARCHAR(255));
+INSERT INTO t1 VALUES (repeat('a',255));
+INSERT INTO t1 VALUES (repeat(_latin1 0xDF, 255));
+DELETE FROM t1 WHERE c51>'a';
+DROP TABLE t1;
+CREATE TABLE t1 (c52 NATIONAL VARCHAR(261));
+INSERT INTO t1 VALUES (repeat('a',261));
+INSERT INTO t1 VALUES (repeat(_latin1 0xDF, 261));
+DELETE FROM t1 WHERE c52>'a';
+DROP TABLE t1;
+CREATE TABLE t1 (c57 BINARY);
+INSERT INTO t1 VALUES (0x00);
+INSERT INTO t1 VALUES (0x02);
+INSERT INTO t1 VALUES ('a');
+DELETE FROM t1 WHERE c57='a';
+DROP TABLE t1;
+CREATE TABLE t1 (c58 BINARY(0));
+INSERT INTO t1 VALUES ('');
+DELETE FROM t1 WHERE c58='';
+DROP TABLE t1;
+CREATE TABLE t1 (c59 BINARY(1));
+INSERT INTO t1 VALUES (0x00);
+INSERT INTO t1 VALUES (0x02);
+INSERT INTO t1 VALUES ('a');
+DELETE FROM t1 WHERE c59='a';
+DROP TABLE t1;
+CREATE TABLE t1 (c60 BINARY(255));
+INSERT INTO t1 VALUES (0x00);
+INSERT INTO t1 VALUES (0x02);
+INSERT INTO t1 VALUES (repeat('a\0',120));
+DELETE FROM t1 WHERE c60<0x02;
+DROP TABLE t1;
+CREATE TABLE t1 (c61 VARBINARY(0));
+INSERT INTO t1 VALUES ('');
+DELETE FROM t1 WHERE c61='';
+DROP TABLE t1;
+CREATE TABLE t1 (c62 VARBINARY(1));
+INSERT INTO t1 VALUES (0x00);
+INSERT INTO t1 VALUES (0x02);
+INSERT INTO t1 VALUES ('a');
+DELETE FROM t1 WHERE c62=0x02;
+DROP TABLE t1;
+CREATE TABLE t1 (c63 VARBINARY(255));
+INSERT INTO t1 VALUES (0x00);
+INSERT INTO t1 VALUES (0x02);
+INSERT INTO t1 VALUES (repeat('a\0',120));
+DELETE FROM t1 WHERE c63=0x02;
+DROP TABLE t1;
+flush logs;
+CREATE TABLE t1 (c65 TINYBLOB);
+INSERT INTO t1 VALUES ('tinyblob1');
+DELETE FROM t1 WHERE c65='tinyblob1';
+DROP TABLE t1;
+CREATE TABLE t1 (c68 BLOB);
+INSERT INTO t1 VALUES ('blob1');
+DELETE FROM t1 WHERE c68='blob1';
+DROP TABLE t1;
+CREATE TABLE t1 (c71 MEDIUMBLOB);
+INSERT INTO t1 VALUES ('mediumblob1');
+DELETE FROM t1 WHERE c71='mediumblob1';
+DROP TABLE t1;
+CREATE TABLE t1 (c74 LONGBLOB);
+INSERT INTO t1 VALUES ('longblob1');
+DELETE FROM t1 WHERE c74='longblob1';
+DROP TABLE t1;
+CREATE TABLE t1 (c66 TINYTEXT);
+INSERT INTO t1 VALUES ('tinytext1');
+DELETE FROM t1 WHERE c66='tinytext1';
+DROP TABLE t1;
+CREATE TABLE t1 (c69 TEXT);
+INSERT INTO t1 VALUES ('text1');
+DELETE FROM t1 WHERE c69='text1';
+DROP TABLE t1;
+CREATE TABLE t1 (c72 MEDIUMTEXT);
+INSERT INTO t1 VALUES ('mediumtext1');
+DELETE FROM t1 WHERE c72='mediumtext1';
+DROP TABLE t1;
+CREATE TABLE t1 (c75 LONGTEXT);
+INSERT INTO t1 VALUES ('longtext1');
+DELETE FROM t1 WHERE c75='longtext1';
+DROP TABLE t1;
+CREATE TABLE t1 (c77 ENUM('a','b','c'));
+INSERT INTO t1 VALUES ('b');
+DELETE FROM t1 WHERE c77='b';
+DROP TABLE t1;
+CREATE TABLE t1 (c78 SET('a','b','c','d','e','f'));
+INSERT INTO t1 VALUES ('a,b');
+INSERT INTO t1 VALUES ('a,c');
+INSERT INTO t1 VALUES ('b,c');
+INSERT INTO t1 VALUES ('a,b,c');
+INSERT INTO t1 VALUES ('a,b,c,d');
+INSERT INTO t1 VALUES ('a,b,c,d,e');
+INSERT INTO t1 VALUES ('a,b,c,d,e,f');
+DELETE FROM t1 WHERE c78='a,b';
+DROP TABLE t1;
+CREATE TABLE t1 (a int NOT NULL DEFAULT 0, b int NOT NULL DEFAULT 0);
+CREATE TABLE t2 (a int NOT NULL DEFAULT 0, b int NOT NULL DEFAULT 0);
+INSERT INTO t1 SET a=1;
+INSERT INTO t1 SET b=1;
+INSERT INTO t2 SET a=1;
+INSERT INTO t2 SET b=1;
+UPDATE t1, t2 SET t1.a=10, t2.a=20;
+DROP TABLE t1,t2;
+flush logs;
+CREATE TABLE raw_mode_exit (exit_code INT);
+SELECT ((@id := id) - id) from information_schema.processlist where processlist.command like '%Binlog%' and state like '%Master has sent%';
+((@id := id) - id)
+0
+kill @id;
+DROP TABLE raw_mode_exit;
+End of tests
diff --git a/mysql-test/t/mysqlbinlog_raw_mode.test b/mysql-test/t/mysqlbinlog_raw_mode.test
new file mode 100644
index 0000000..26fb315
--- /dev/null
+++ b/mysql-test/t/mysqlbinlog_raw_mode.test
@@ -0,0 +1,387 @@
+--source include/have_log_bin.inc
+reset master;
+
+# we need this for getting fixed timestamps inside of this test
+set timestamp=1000000000;
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+CREATE TABLE t1 (c01 BIT);
+INSERT INTO t1 VALUES (0);
+INSERT INTO t1 VALUES (1);
+DROP TABLE t1;
+
+CREATE TABLE t1 (c01 BIT(7));
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (4);
+INSERT INTO t1 VALUES (8);
+INSERT INTO t1 VALUES (16);
+INSERT INTO t1 VALUES (32);
+INSERT INTO t1 VALUES (64);
+INSERT INTO t1 VALUES (127);
+DELETE FROM t1 WHERE c01=127;
+UPDATE t1 SET c01=15 WHERE c01=16;
+DROP TABLE t1;
+
+CREATE TABLE t1 (a BIT(20), b CHAR(2));
+INSERT INTO t1 VALUES (b'00010010010010001001', 'ab');
+DROP TABLE t1;
+
+CREATE TABLE t1 (c02 BIT(64));
+INSERT INTO t1 VALUES (1);
+INSERT INTO t1 VALUES (2);
+INSERT INTO t1 VALUES (128);
+INSERT INTO t1 VALUES (b'1111111111111111111111111111111111111111111111111111111111111111');
+DROP TABLE t1;
+
+
+CREATE TABLE t1 (c03 TINYINT);
+INSERT INTO t1 VALUES (1),(2),(3);
+INSERT INTO t1 VALUES (-128);
+UPDATE t1 SET c03=2 WHERE c03=1;
+DELETE FROM t1 WHERE c03=-128;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c04 TINYINT UNSIGNED);
+INSERT INTO t1 VALUES (128), (255);
+UPDATE t1 SET c04=2 WHERE c04=1;
+DELETE FROM t1 WHERE c04=255;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c06 BOOL);
+INSERT INTO t1 VALUES (TRUE);
+DELETE FROM t1 WHERE c06=TRUE;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c07 SMALLINT);
+INSERT INTO t1 VALUES (1234);
+DELETE FROM t1 WHERE c07=1234;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c08 SMALLINT UNSIGNED);
+INSERT INTO t1 VALUES (32768), (65535);
+UPDATE t1 SET c08=2 WHERE c08=32768;
+DELETE FROM t1 WHERE c08=65535;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c10 MEDIUMINT);
+INSERT INTO t1 VALUES (12345);
+DELETE FROM t1 WHERE c10=12345;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c11 MEDIUMINT UNSIGNED);
+INSERT INTO t1 VALUES (8388608), (16777215);
+UPDATE t1 SET c11=2 WHERE c11=8388608;
+DELETE FROM t1 WHERE c11=16777215;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c13 INT);
+INSERT INTO t1 VALUES (123456);
+DELETE FROM t1 WHERE c13=123456;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c14 INT UNSIGNED);
+INSERT INTO t1 VALUES (2147483648), (4294967295);
+UPDATE t1 SET c14=2 WHERE c14=2147483648;
+DELETE FROM t1 WHERE c14=4294967295;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c16 BIGINT);
+INSERT INTO t1 VALUES (1234567890);
+DELETE FROM t1 WHERE c16=1234567890;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c17 BIGINT UNSIGNED);
+INSERT INTO t1 VALUES (9223372036854775808), (18446744073709551615);
+UPDATE t1 SET c17=2 WHERE c17=9223372036854775808;
+DELETE FROM t1 WHERE c17=18446744073709551615;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c19 FLOAT);
+INSERT INTO t1 VALUES (123.2234);
+DELETE FROM t1 WHERE c19>123;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c22 DOUBLE);
+INSERT INTO t1 VALUES (123434.22344545);
+DELETE FROM t1 WHERE c22>123434;
+DROP TABLE t1;
+
+#
+
+CREATE TABLE t1 (c25 DECIMAL(10,5));
+INSERT INTO t1 VALUES (124.45);
+INSERT INTO t1 VALUES (-543.21);
+DELETE FROM t1 WHERE c25=124.45;
+DROP TABLE t1;
+
+#
+
+CREATE TABLE t1 (c28 DATE);
+INSERT INTO t1 VALUES ('2001-02-03');
+DELETE FROM t1 WHERE c28='2001-02-03';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c29 DATETIME);
+INSERT INTO t1 VALUES ('2001-02-03 10:20:30');
+DELETE FROM t1 WHERE c29='2001-02-03 10:20:30';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c30 TIMESTAMP);
+INSERT INTO t1 VALUES ('2001-02-03 10:20:30');
+DELETE FROM t1 WHERE c30='2001-02-03 10:20:30';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c31 TIME);
+INSERT INTO t1 VALUES ('11:22:33');
+DELETE FROM t1 WHERE c31='11:22:33';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c32 YEAR);
+INSERT INTO t1 VALUES ('2001');
+DELETE FROM t1 WHERE c32=2001;
+DROP TABLE t1;
+
+#
+
+CREATE TABLE t1 (c33 CHAR);
+INSERT INTO t1 VALUES ('a');
+DELETE FROM t1 WHERE c33='a';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c34 CHAR(0));
+INSERT INTO t1 VALUES ('');
+DELETE FROM t1 WHERE c34='';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c35 CHAR(1));
+INSERT INTO t1 VALUES ('b');
+DELETE FROM t1 WHERE c35='b';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c36 CHAR(255));
+INSERT INTO t1 VALUES (repeat('c',255));
+DELETE FROM t1 WHERE c36>'c';
+DROP TABLE t1;
+
+#
+
+CREATE TABLE t1 (c37 NATIONAL CHAR);
+INSERT INTO t1 VALUES ('a');
+DELETE FROM t1 WHERE c37='a';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c38 NATIONAL CHAR(0));
+INSERT INTO t1 VALUES ('');
+DELETE FROM t1 WHERE c38='';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c39 NATIONAL CHAR(1));
+INSERT INTO t1 VALUES ('a');
+DELETE FROM t1 WHERE c39='a';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c40 NATIONAL CHAR(255));
+INSERT INTO t1 VALUES (repeat('a', 255));
+INSERT INTO t1 VALUES (repeat(_latin1 0xDF, 255));
+DELETE FROM t1 WHERE c40>'a';
+DROP TABLE t1;
+
+#
+
+CREATE TABLE t1 (c45 VARCHAR(0));
+INSERT INTO t1 VALUES ('');
+DELETE FROM t1 WHERE c45='';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c46 VARCHAR(1));
+INSERT INTO t1 VALUES ('a');
+DELETE FROM t1 WHERE c46='a';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c47 VARCHAR(255));
+INSERT INTO t1 VALUES (repeat('a',255));
+DELETE FROM t1 WHERE c47>'a';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c48 VARCHAR(261));
+INSERT INTO t1 VALUES (repeat('a',261));
+DELETE FROM t1 WHERE c48>'a';
+DROP TABLE t1;
+
+#
+
+CREATE TABLE t1 (c49 NATIONAL VARCHAR(0));
+INSERT INTO t1 VALUES ('');
+DELETE FROM t1 WHERE c49='';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c50 NATIONAL VARCHAR(1));
+INSERT INTO t1 VALUES ('a');
+DELETE FROM t1 WHERE c50='a';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c51 NATIONAL VARCHAR(255));
+INSERT INTO t1 VALUES (repeat('a',255));
+INSERT INTO t1 VALUES (repeat(_latin1 0xDF, 255));
+DELETE FROM t1 WHERE c51>'a';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c52 NATIONAL VARCHAR(261));
+INSERT INTO t1 VALUES (repeat('a',261));
+INSERT INTO t1 VALUES (repeat(_latin1 0xDF, 261));
+DELETE FROM t1 WHERE c52>'a';
+DROP TABLE t1;
+
+#
+
+CREATE TABLE t1 (c57 BINARY);
+INSERT INTO t1 VALUES (0x00);
+INSERT INTO t1 VALUES (0x02);
+INSERT INTO t1 VALUES ('a');
+DELETE FROM t1 WHERE c57='a';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c58 BINARY(0));
+INSERT INTO t1 VALUES ('');
+DELETE FROM t1 WHERE c58='';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c59 BINARY(1));
+INSERT INTO t1 VALUES (0x00);
+INSERT INTO t1 VALUES (0x02);
+INSERT INTO t1 VALUES ('a');
+DELETE FROM t1 WHERE c59='a';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c60 BINARY(255));
+INSERT INTO t1 VALUES (0x00);
+INSERT INTO t1 VALUES (0x02);
+INSERT INTO t1 VALUES (repeat('a\0',120));
+DELETE FROM t1 WHERE c60<0x02;
+DROP TABLE t1;
+
+#
+
+CREATE TABLE t1 (c61 VARBINARY(0));
+INSERT INTO t1 VALUES ('');
+DELETE FROM t1 WHERE c61='';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c62 VARBINARY(1));
+INSERT INTO t1 VALUES (0x00);
+INSERT INTO t1 VALUES (0x02);
+INSERT INTO t1 VALUES ('a');
+DELETE FROM t1 WHERE c62=0x02;
+DROP TABLE t1;
+
+CREATE TABLE t1 (c63 VARBINARY(255));
+INSERT INTO t1 VALUES (0x00);
+INSERT INTO t1 VALUES (0x02);
+INSERT INTO t1 VALUES (repeat('a\0',120));
+DELETE FROM t1 WHERE c63=0x02;
+DROP TABLE t1;
+
+#
+flush logs;
+
+CREATE TABLE t1 (c65 TINYBLOB);
+INSERT INTO t1 VALUES ('tinyblob1');
+DELETE FROM t1 WHERE c65='tinyblob1';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c68 BLOB);
+INSERT INTO t1 VALUES ('blob1');
+DELETE FROM t1 WHERE c68='blob1';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c71 MEDIUMBLOB);
+INSERT INTO t1 VALUES ('mediumblob1');
+DELETE FROM t1 WHERE c71='mediumblob1';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c74 LONGBLOB);
+INSERT INTO t1 VALUES ('longblob1');
+DELETE FROM t1 WHERE c74='longblob1';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c66 TINYTEXT);
+INSERT INTO t1 VALUES ('tinytext1');
+DELETE FROM t1 WHERE c66='tinytext1';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c69 TEXT);
+INSERT INTO t1 VALUES ('text1');
+DELETE FROM t1 WHERE c69='text1';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c72 MEDIUMTEXT);
+INSERT INTO t1 VALUES ('mediumtext1');
+DELETE FROM t1 WHERE c72='mediumtext1';
+DROP TABLE t1;
+
+CREATE TABLE t1 (c75 LONGTEXT);
+INSERT INTO t1 VALUES ('longtext1');
+DELETE FROM t1 WHERE c75='longtext1';
+DROP TABLE t1;
+
+#
+
+CREATE TABLE t1 (c77 ENUM('a','b','c'));
+INSERT INTO t1 VALUES ('b');
+DELETE FROM t1 WHERE c77='b';
+DROP TABLE t1;
+
+#
+
+CREATE TABLE t1 (c78 SET('a','b','c','d','e','f'));
+INSERT INTO t1 VALUES ('a,b');
+INSERT INTO t1 VALUES ('a,c');
+INSERT INTO t1 VALUES ('b,c');
+INSERT INTO t1 VALUES ('a,b,c');
+INSERT INTO t1 VALUES ('a,b,c,d');
+INSERT INTO t1 VALUES ('a,b,c,d,e');
+INSERT INTO t1 VALUES ('a,b,c,d,e,f');
+DELETE FROM t1 WHERE c78='a,b';
+DROP TABLE t1;
+
+#
+# Check multi-table update
+#
+CREATE TABLE t1 (a int NOT NULL DEFAULT 0, b int NOT NULL DEFAULT 0);
+CREATE TABLE t2 (a int NOT NULL DEFAULT 0, b int NOT NULL DEFAULT 0);
+INSERT INTO t1 SET a=1;
+INSERT INTO t1 SET b=1;
+INSERT INTO t2 SET a=1;
+INSERT INTO t2 SET b=1;
+UPDATE t1, t2 SET t1.a=10, t2.a=20;
+DROP TABLE t1,t2;
+
+flush logs;
+
+let $MYSQLD_DATADIR= `select @@datadir`;
+
+# Test reading one file in raw mode
+--exec $MYSQL_BINLOG --raw --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --result-file=$MYSQLTEST_VARDIR/tmp/ master-bin.000001
+--diff_files $MYSQLTEST_VARDIR/tmp/master-bin.000001 $MYSQLD_DATADIR/master-bin.000001
+--remove_file $MYSQLTEST_VARDIR/tmp/master-bin.000001
+
+# Test reading all files in raw mode
+# Don't test the end file since this is still open with mysqld so will be different
+--exec $MYSQL_BINLOG --raw --read-from-remote-server --to-last-log --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --result-file=$MYSQLTEST_VARDIR/tmp/ master-bin.000001
+--diff_files $MYSQLTEST_VARDIR/tmp/master-bin.000001 $MYSQLD_DATADIR/master-bin.000001
+--diff_files $MYSQLTEST_VARDIR/tmp/master-bin.000002 $MYSQLD_DATADIR/master-bin.000002
+
+--remove_file $MYSQLTEST_VARDIR/tmp/master-bin.000001
+--remove_file $MYSQLTEST_VARDIR/tmp/master-bin.000002
+--remove_file $MYSQLTEST_VARDIR/tmp/master-bin.000003
+
+
+# Test output to different filename
+--exec $MYSQL_BINLOG --raw --read-from-remote-server --user=root --host=127.0.0.1 --port=$MASTER_MYPORT --result-file=$MYSQLTEST_VARDIR/tmp/server1- master-bin.000001
+--diff_files $MYSQLTEST_VARDIR/tmp/server1-master-bin.000001 $MYSQLD_DATADIR/master-bin.000001
+--remove_file $MYSQLTEST_VARDIR/tmp/server1-master-bin.000001
+
+--echo End of tests
diff --git a/sql/sql_priv.h b/sql/sql_priv.h
index 4d62f72..cc56daa 100644
--- a/sql/sql_priv.h
+++ b/sql/sql_priv.h
@@ -320,11 +320,11 @@
 /* Used to check GROUP BY list in the MODE_ONLY_FULL_GROUP_BY mode */
 #define UNDEF_POS (-1)
 
+#endif /* !MYSQL_CLIENT */
+
 /* BINLOG_DUMP options */
 
 #define BINLOG_DUMP_NON_BLOCK   1
-#endif /* !MYSQL_CLIENT */
-
 #define BINLOG_SEND_ANNOTATE_ROWS_EVENT   2
 
 #ifndef MYSQL_CLIENT



More information about the commits mailing list