List:Commits« Previous MessageNext Message »
From:Chad MILLER Date:February 27 2008 4:38pm
Subject:bk commit into 5.0 tree (cmiller:1.2580) BUG#33048
View as plain text  
Below is the list of changes that have just been committed into a local
5.0 repository of cmiller.  When cmiller does a push these changes
will be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2008-02-27 11:38:48-05:00, cmiller@stripped +3 -0
  Bug#33048: Not able to recover binary/blob data correctly using \
  	mysqlbinlog
  
  mysqlbinlog wrote to stdout query text exactly as sent to the server,
  but some queries that can be inserted via the API are illegal or 
  impossible to send using the command-line "mysql" client (which is
  why we have escape characters for special characters).
  
  Now, make mysqlbinlog escape query characters (only CR for now) that 
  cannot be read via mysql client.

  mysql-test/r/type_blob.result@stripped, 2008-02-27 11:38:46-05:00, cmiller@stripped +22 -0
    Show that literal CR+NLs are preserved across mysqlbinlog|mysql .

  mysql-test/t/type_blob.test@stripped, 2008-02-27 11:38:46-05:00, cmiller@stripped +37 -0
    Show that literal CR+NLs are preserved across mysqlbinlog|mysql .

  sql/log_event.cc@stripped, 2008-02-27 11:38:46-05:00, cmiller@stripped +34 -1
    The mysqbinlog utility describes itself as "Dumps a MySQL binary log
    in a format usable for viewing or for piping to the mysql command 
    line client", but that was untrue if the query contained a literal 
    carriage return and newline, as the client would consume the 
    carriage return.

diff -Nrup a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result
--- a/mysql-test/r/type_blob.result	2007-11-19 12:34:12 -05:00
+++ b/mysql-test/r/type_blob.result	2008-02-27 11:38:46 -05:00
@@ -821,4 +821,26 @@ LENGTH(c)	CHAR_LENGTH(c)
 65535	65535
 65535	65535
 DROP TABLE t;
+DROP DATABASE IF EXISTS dbbug33048;
+CREATE DATABASE dbbug33048;
+use dbbug33048;
+CREATE TABLE binfile (i int auto_increment primary key, bin_data LONGBLOB);
+FLUSH LOGS;
+INSERT INTO binfile (bin_data) values ('
+
+
+
');
+SELECT 'good, have failing data' as descr, i FROM binfile where bin_data = x'0d0a0d0d0a0a0d';
+descr	i
+good, have failing data	1
+SELECT bin_data INTO dumpfile 'bug33048-dump1' FROM binfile;
+FLUSH LOGS;
+DELETE FROM binfile;
+SELECT bin_data INTO dumpfile 'bug33048-dump2' FROM binfile;
+SELECT 'good, have failing data' as descr, i FROM binfile where bin_data = x'0d0a0d0d0a0a0d';
+descr	i
+good, have failing data	1
+DROP TABLE binfile;
+use test;
+DROP DATABASE dbbug33048;
 End of 5.0 tests
diff -Nrup a/mysql-test/t/type_blob.test b/mysql-test/t/type_blob.test
--- a/mysql-test/t/type_blob.test	2007-11-19 12:34:12 -05:00
+++ b/mysql-test/t/type_blob.test	2008-02-27 11:38:46 -05:00
@@ -447,4 +447,41 @@ INSERT INTO t (c) VALUES (REPEAT('3',655
 SELECT LENGTH(c), CHAR_LENGTH(c) FROM t;
 DROP TABLE t;
 
+#
+# Bug#33048: Not able to recover binary/blob data correctly using mysqlbinlog
+#
+--disable_warnings
+DROP DATABASE IF EXISTS dbbug33048;
+--enable_warnings
+CREATE DATABASE dbbug33048;
+
+use dbbug33048;
+CREATE TABLE binfile (i int auto_increment primary key, bin_data LONGBLOB);
+
+FLUSH LOGS;
+let $hexrepr=x'0d0a0d0d0a0a0d';
+let $blob=`select $hexrepr`;
+
+eval INSERT INTO binfile (bin_data) values ('$blob');
+eval SELECT 'good, have failing data' as descr, i FROM binfile where bin_data = $hexrepr;
+
+SELECT bin_data INTO dumpfile 'bug33048-dump1' FROM binfile;
+FLUSH LOGS;
+DELETE FROM binfile;
+
+exec $MYSQL_BINLOG --short-form --local-load=$MYSQLTEST_VARDIR/tmp/ --database=dbbug33048 $MYSQLTEST_VARDIR/log/master-bin.000002 |$MYSQL dbbug33048;
+
+SELECT bin_data INTO dumpfile 'bug33048-dump2' FROM binfile;
+eval SELECT 'good, have failing data' as descr, i FROM binfile where bin_data = $hexrepr;
+
+diff_files $MYSQLTEST_VARDIR/master-data/dbbug33048/bug33048-dump1 $MYSQLTEST_VARDIR/master-data/dbbug33048/bug33048-dump2;
+
+remove_file $MYSQLTEST_VARDIR/master-data/dbbug33048/bug33048-dump1;
+remove_file $MYSQLTEST_VARDIR/master-data/dbbug33048/bug33048-dump2;
+
+DROP TABLE binfile;
+use test;
+DROP DATABASE dbbug33048;
+
+##
 --echo End of 5.0 tests
diff -Nrup a/sql/log_event.cc b/sql/log_event.cc
--- a/sql/log_event.cc	2007-12-21 14:30:22 -05:00
+++ b/sql/log_event.cc	2008-02-27 11:38:46 -05:00
@@ -1858,10 +1858,43 @@ void Query_log_event::print_query_header
 }
 
 
+/**
+  Write the provided event's header, then the (partially-escaped) query and
+  then a delimiter to the provided file handle.
+*/
 void Query_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
 {
+  const char *cursor= query, *cr_location;
+  reg1 uint32 distance_to_end= q_len;
+
   print_query_header(file, print_event_info);
-  my_fwrite(file, (byte*) query, q_len, MYF(MY_NABP | MY_WME));
+
+  /* 
+   Escape only special characters that cause problems.  Currently, this is
+   only known to be carriage returns.
+
+   This is designed to be fast, but simple.  If we ever need to escape other
+   characters, then it is probably best to allocate a string with lenth
+   2*q_len, iterate over each character, copying it or its escaped value to
+   the destination string, then write the destination string once at the end.
+  */
+  while ((cr_location= (char *)memchr(cursor, '\r', distance_to_end)) != NULL)
+  {
+    reg2 uint32 distance_to_cr= cr_location - cursor;
+    /* Write up to the carriage return. */
+    if (distance_to_cr != 0)
+      my_fwrite(file, (byte*) cursor, distance_to_cr, MYF(MY_NABP | MY_WME));
+
+    /* Write the carriage return. */
+    my_fwrite(file, (byte*) "\\r", 2, MYF(MY_NABP | MY_WME));
+
+    /* Advance the cursor so that the rest looks like a new query */
+    distance_to_end= distance_to_end - (cr_location - cursor);
+    cursor= cr_location+1;
+  }
+
+  /* No problematic characters remain.  Write the rest. */
+  my_fwrite(file, (byte*) cursor, distance_to_end, MYF(MY_NABP | MY_WME));
   fprintf(file, "\n%s\n", print_event_info->delimiter);
 }
 #endif /* MYSQL_CLIENT */
Thread
bk commit into 5.0 tree (cmiller:1.2580) BUG#33048Chad MILLER27 Feb