List:Commits« Previous MessageNext Message »
From:Libing Song Date:January 26 2011 7:14am
Subject:[Resend] bzr commit into mysql-trunk branch (anders.song:3515) Bug#33048
View as plain text  
[This commit e-mail is a repeat.]

#At file:///home/anders/Work/bzrwork/wt1/mysql-trunk/ based on
revid:anders.song@stripped

 3515 Libing Song	2011-01-26
      BUG#33048 Not able to recover binary/blob data correctly using mysqlbinlog
      
      The queries generated by mysqlbinlog could not be executed by 'mysql' client
      if there was any 0x00 in it. Or the queries recovered diverged data if there
      was any 0x0D0A sequence in it. The reason is that 'mysql' client always
      translated '0x0D0A'('\r\n') to '0x0A'('\n') and treated '0x00' as the end
      of a query if it is in non-interactive mode(receiving queries from a file
      or a pipe).
      
      This patch added the option 'binary-mode' in 'mysql' program.  'mysql' will
      not translated '0x0D0A' to '0x0A' and not treat '0x00' as the end of a query
      if binary-mode is set 1 and it is in non-interactive mode.

    added:
      mysql-test/r/mysql_binary_mode.result
      mysql-test/t/mysql_binary_mode.test
    modified:
      client/client_priv.h
      client/my_readline.h
      client/mysql.cc
      client/readline.cc
=== modified file 'client/client_priv.h'
--- a/client/client_priv.h	2010-11-24 13:09:52 +0000
+++ b/client/client_priv.h	2011-01-26 07:13:45 +0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2001-2006 MySQL AB, 2009 Sun Microsystems, Inc
+/* Copyright 2000, 2011, Oracle and/or its affiliates. All rights reserved.
 
    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
@@ -85,6 +85,7 @@ enum options_client
   OPT_DEFAULT_PLUGIN,
   OPT_RAW_OUTPUT, OPT_WAIT_SERVER_ID, OPT_STOP_NEVER,
   OPT_BINLOG_ROWS_EVENT_MAX_SIZE,
+  OPT_BINARY_MODE,
   OPT_MAX_CLIENT_OPTION
 };
 

=== modified file 'client/my_readline.h'
--- a/client/my_readline.h	2009-09-23 21:32:31 +0000
+++ b/client/my_readline.h	2011-01-26 07:13:45 +0000
@@ -1,7 +1,7 @@
 #ifndef CLIENT_MY_READLINE_INCLUDED
 #define CLIENT_MY_READLINE_INCLUDED
 
-/* Copyright (C) 2000 MySQL AB
+/* Copyright 2000, 2011, Oracle and/or its affiliates. All rights reserved.
 
    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
@@ -32,7 +32,8 @@ typedef struct st_line_buffer
 
 extern LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file);
 extern LINE_BUFFER *batch_readline_command(LINE_BUFFER *buffer, char * str);
-extern char *batch_readline(LINE_BUFFER *buffer, bool *truncated);
+extern char *batch_readline(LINE_BUFFER *buffer, bool *truncated,
+                            bool binary_mode);
 extern void batch_readline_end(LINE_BUFFER *buffer);
 
 #endif /* CLIENT_MY_READLINE_INCLUDED */

=== modified file 'client/mysql.cc'
--- a/client/mysql.cc	2010-11-26 14:37:59 +0000
+++ b/client/mysql.cc	2011-01-26 07:13:45 +0000
@@ -1,4 +1,4 @@
-/* Copyright 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright 2000, 2011, Oracle and/or its affiliates. All rights reserved.
 
    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
@@ -150,6 +150,7 @@ static uint my_end_arg;
 static char * opt_mysql_unix_port=0;
 static char *opt_bind_addr = NULL;
 static int connect_flag=CLIENT_INTERACTIVE;
+static my_bool opt_binary_mode= FALSE;
 static char *current_host,*current_db,*current_user=0,*opt_password=0,
             *current_prompt=0, *delimiter_str= 0,
             *default_charset= (char*) MYSQL_AUTODETECT_CHARSET_NAME,
@@ -1045,8 +1046,8 @@ static void fix_history(String *final_co
 #endif
 
 static COMMANDS *find_command(char *name,char cmd_name);
-static bool add_line(String &buffer,char *line,char *in_string,
-                     bool *ml_comment, bool truncated);
+static bool add_line(String &buffer, char *line, ulong line_length,
+                     char *in_string, bool *ml_comment, bool truncated);
 static void remove_cntrl(String &buffer);
 static void print_table_data(MYSQL_RES *result);
 static void print_table_data_html(MYSQL_RES *result);
@@ -1572,6 +1573,11 @@ static struct my_option my_long_options[
     "Default authentication client-side plugin to use.",
    (uchar**) &opt_default_auth, (uchar**) &opt_default_auth, 0,
    GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+  {"binary-mode", OPT_BINARY_MODE,
+   "ASCII '0x00' is allowed in queries and '0x0D0A'('\\r\\n') sequence "
+   "is not translated to '0x0A'('\\n') if 'mysql' is non-interactive and "
+   "--binary-mode is set.",
+   &opt_binary_mode, &opt_binary_mode, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
   { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
 };
 
@@ -1844,13 +1850,33 @@ static int read_and_execute(bool interac
   bool ml_comment= 0;  
   COMMANDS *com;
   bool truncated= 0;
+  ulong line_length= 0;
   status.exit_status=1;
   
   for (;;)
   {
     if (!interactive)
     {
-      line=batch_readline(status.line_buff, &truncated);
+      line=batch_readline(status.line_buff, &truncated, opt_binary_mode);
+      line_length= status.line_buff->read_length;
+      /*
+        ASCII 0x00 is not allowed appearing in queries if it is not in binary
+        mode.
+      */
+      if (!opt_binary_mode && line && strlen(line) != line_length)
+      {
+        status.exit_status= 1;
+        String msg;
+        msg.append("ASCII '0x00' appeared in the query.  It is disallowed unless "
+                   "option --binary-mode is set and 'mysql' is non-interactive.  "
+                   "Please set --binary-mode 1 if the ASCII '0x00' is expected.  "
+                   "Query: '");
+        msg.append(glob_buffer);
+        msg.append(line);
+        msg.append("'.");
+        put_info(msg.c_ptr(), INFO_ERROR);
+        break;
+      }
       /*
         Skip UTF8 Byte Order Marker (BOM) 0xEFBBBF.
         Editors like "notepad" put this marker in
@@ -1912,6 +1938,8 @@ static int read_and_execute(bool interac
       */
       if (opt_outfile && line)
 	fprintf(OUTFILE, "%s\n", line);
+
+      line_length= line ? strlen(line) : 0;
     }
     if (!line)					// End of file
     {
@@ -1936,7 +1964,8 @@ static int read_and_execute(bool interac
 #endif
       continue;
     }
-    if (add_line(glob_buffer,line,&in_string,&ml_comment, truncated))
+    if (add_line(glob_buffer, line, line_length, &in_string, &ml_comment,
+                 truncated))
       break;
   }
   /* if in batch mode, send last query even if it doesn't end with \g or go */
@@ -2019,8 +2048,8 @@ static COMMANDS *find_command(char *name
 }
 
 
-static bool add_line(String &buffer,char *line,char *in_string,
-                     bool *ml_comment, bool truncated)
+static bool add_line(String &buffer, char *line, ulong line_length,
+                     char *in_string, bool *ml_comment, bool truncated)
 {
   uchar inchar;
   char buff[80], *pos, *out;
@@ -2035,10 +2064,11 @@ static bool add_line(String &buffer,char
   if (status.add_to_history && line[0] && not_in_history(line))
     add_history(line);
 #endif
-  char *end_of_line=line+(uint) strlen(line);
+  char *end_of_line= line + line_length;
 
-  for (pos=out=line ; (inchar= (uchar) *pos) ; pos++)
+  for (pos=out=line; pos < end_of_line; pos++)
   {
+    inchar= (uchar) *pos;
     if (!preserve_comments)
     {
       // Skip spaces at the beginning of a statement

=== modified file 'client/readline.cc'
--- a/client/readline.cc	2010-07-08 21:20:08 +0000
+++ b/client/readline.cc	2011-01-26 07:13:45 +0000
@@ -1,4 +1,4 @@
-/* Copyright (C) 2000 MySQL AB
+/* Copyright 2000, 2011, Oracle and/or its affiliates. All rights reserved.
 
    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
@@ -42,7 +42,7 @@ LINE_BUFFER *batch_readline_init(ulong m
 }
 
 
-char *batch_readline(LINE_BUFFER *line_buff, bool *truncated)
+char *batch_readline(LINE_BUFFER *line_buff, bool *truncated, bool binary_mode)
 {
   char *pos;
   ulong out_length;
@@ -51,10 +51,14 @@ char *batch_readline(LINE_BUFFER *line_b
   if (!(pos=intern_read_line(line_buff,&out_length, truncated)))
     return 0;
   if (out_length && pos[out_length-1] == '\n')
-    if (--out_length && pos[out_length-1] == '\r')  /* Remove '\n' */
+  {
+    out_length--;                                   /* Remove '\n' */
+    if (!binary_mode && pos[out_length-1] == '\r')
       out_length--;                                 /* Remove '\r' */
+  }
   line_buff->read_length=out_length;
   pos[out_length]=0;
+  DBUG_DUMP("Query: ", (unsigned char *)pos, out_length);
   return pos;
 }
 
@@ -209,7 +213,7 @@ char *intern_read_line(LINE_BUFFER *buff
   for (;;)
   {
     pos=buffer->end_of_line;
-    while (*pos != '\n' && *pos)
+    while (*pos != '\n' && pos != buffer->end)
       pos++;
     if (pos == buffer->end)
     {
@@ -232,6 +236,7 @@ char *intern_read_line(LINE_BUFFER *buff
       *truncated= 0;
     buffer->end_of_line=pos+1;
     *out_length=(ulong) (pos + 1 - buffer->eof - buffer->start_of_line);
+    DBUG_DUMP("Query: ", (unsigned char *)buffer->start_of_line, *out_length);
     DBUG_RETURN(buffer->start_of_line);
   }
 }

=== added file 'mysql-test/r/mysql_binary_mode.result'
Binary files a/mysql-test/r/mysql_binary_mode.result	1970-01-01 00:00:00 +0000 and
b/mysql-test/r/mysql_binary_mode.result	2011-01-26 07:13:45 +0000 differ

=== added file 'mysql-test/t/mysql_binary_mode.test'
--- a/mysql-test/t/mysql_binary_mode.test	1970-01-01 00:00:00 +0000
+++ b/mysql-test/t/mysql_binary_mode.test	2011-01-26 07:13:45 +0000
@@ -0,0 +1,45 @@
+source include/have_binlog_format_statement.inc;
+
+--echo # Bug#33048 Not able to recover binary/blob data correctly using mysqlbinlog
+--echo # --------------------------------------------------------------------------
+--echo # The test verify that 0x00 and 0x0D0A sequence can be handled correctly by
+--echo # mysql
+--echo
+let $table_name= `SELECT 0x410D0A42`;
+eval CREATE TABLE `$table_name` (c1 CHAR(100));
+
+let $char= `SELECT 0x410042`;
+eval INSERT INTO `$table_name` VALUES("$char");
+
+let $char= `SELECT 0x410D0A42`;
+eval INSERT INTO `$table_name` VALUES("$char");
+
+eval SELECT HEX(c1) FROM `$table_name`;
+
+--echo
+FLUSH LOGS;
+eval DROP TABLE `$table_name`;
+
+--echo
+let $MYSQLD_DATADIR= `SELECT @@datadir`;
+--exec $MYSQL_BINLOG $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/my.sql
+
+--echo # '--exec mysql ...' without --binary-mode option
+--echo # It creates the table with a wrong table name and generates an error.
+--error 1
+--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/my.sql 2>&1
+
+--echo
+--echo # It is not in binary_mode, so table name '0x410D0A42' is translated to
+--echo # '0x410A42' by mysql.
+let $table_name1= `SELECT 0x410A42`;
+eval DROP TABLE `$table_name1`;
+
+--echo
+--echo # In binary_mode, table name '0x410D0A42' and string '0x410042' can be
+--echo # handled correctly.
+--exec $MYSQL --binary-mode test < $MYSQLTEST_VARDIR/tmp/my.sql
+eval SELECT HEX(c1) FROM `$table_name`;
+
+--echo
+eval DROP TABLE `$table_name`;


Attachment: [text/bzr-bundle] bzr/anders.song@greatopensource.com-20110126071345-i34ksuanh1t0v8hk.bundle
Thread
[Resend] bzr commit into mysql-trunk branch (anders.song:3515) Bug#33048Libing Song26 Jan