Index: sql/log_event.h =================================================================== --- sql/log_event.h (revision 4174) +++ sql/log_event.h (revision 4186) @@ -673,6 +673,9 @@ uint thread_id; bool thread_id_printed; + /* dump string in hex mode for mysqlbinlog */ + bool dump_hexstring; + st_print_event_info(); ~st_print_event_info() { Index: sql/log_event.cc =================================================================== --- sql/log_event.cc (revision 4174) +++ sql/log_event.cc (revision 4186) @@ -1509,7 +1509,29 @@ my_b_printf(file, "'"); } +/** + Prints a quoted string in its hex mode to io cache. + Control characters are displayed as hex sequence, e.g. \x00 + + @param[in] file IO cache + @param[in] prt Pointer to string + @param[in] length String length +*/ +static void my_b_write_quoted_hex(IO_CACHE *file, const uchar *ptr, uint length) +{ + const uchar *s; + my_b_printf(file, "x'"); + for (s= ptr; length > 0 ; s++, length--) + { + uchar hex[8]={0}; + size_t len= my_snprintf((char*) hex, sizeof(hex), "%02x", *s); + my_b_write(file, hex, len); + } + my_b_printf(file, "'"); +} + + /** Prints a bit string to io cache in format b'1010'. @@ -1559,6 +1581,33 @@ } } +/** + Prints a packed string in it's hex mode to io cache. + The string consists of length packed to 1 or 2 bytes, + followed by string data itself. + + @param[in] file IO cache + @param[in] ptr Pointer to string + @param[in] length String size + + @retval - number of bytes scanned. +*/ +static size_t +my_b_write_quoted_hex_with_length(IO_CACHE *file, const uchar *ptr, uint length) +{ + if (length < 256) + { + length= *ptr; + my_b_write_quoted_hex(file, ptr + 1, length); + return length + 1; + } + else + { + length= uint2korr(ptr); + my_b_write_quoted_hex(file, ptr + 2, length); + return length + 2; + } +} /** Prints a 32-bit number in both signed and unsigned representation @@ -1585,6 +1634,7 @@ @param[in] meta Column meta information @param[out] typestr SQL type string buffer (for verbose output) @param[out] typestr_length Size of typestr + @param[in] hexstring wheather to output CHAR/VARCHAR/TEXT/BLOB in hex mode @retval - number of bytes scanned from ptr. */ @@ -1592,7 +1642,8 @@ static size_t log_event_print_value(IO_CACHE *file, const uchar *ptr, uint type, uint meta, - char *typestr, size_t typestr_length) + char *typestr, size_t typestr_length, + bool hexstring) /* for CHAR/VARCHAR/TEXT/BLOB */ { uint32 length= 0; @@ -1824,22 +1875,34 @@ switch (meta) { case 1: length= *ptr; - my_b_write_quoted(file, ptr + 1, length); + if (hexstring) + my_b_write_quoted_hex(file, ptr + 1, length); + else + my_b_write_quoted(file, ptr + 1, length); my_snprintf(typestr, typestr_length, "TINYBLOB/TINYTEXT"); return length + 1; case 2: length= uint2korr(ptr); - my_b_write_quoted(file, ptr + 2, length); + if (hexstring) + my_b_write_quoted_hex(file, ptr + 2, length); + else + my_b_write_quoted(file, ptr + 2, length); my_snprintf(typestr, typestr_length, "BLOB/TEXT"); return length + 2; case 3: length= uint3korr(ptr); - my_b_write_quoted(file, ptr + 3, length); + if (hexstring) + my_b_write_quoted_hex(file, ptr + 3, length); + else + my_b_write_quoted(file, ptr + 3, length); my_snprintf(typestr, typestr_length, "MEDIUMBLOB/MEDIUMTEXT"); return length + 3; case 4: length= uint4korr(ptr); - my_b_write_quoted(file, ptr + 4, length); + if (hexstring) + my_b_write_quoted_hex(file, ptr + 4, length); + else + my_b_write_quoted(file, ptr + 4, length); my_snprintf(typestr, typestr_length, "LONGBLOB/LONGTEXT"); return length + 4; default: @@ -1851,11 +1914,17 @@ case MYSQL_TYPE_VAR_STRING: length= meta; my_snprintf(typestr, typestr_length, "VARSTRING(%d)", length); - return my_b_write_quoted_with_length(file, ptr, length); + if (hexstring) + return my_b_write_quoted_hex_with_length(file, ptr, length); + else + return my_b_write_quoted_with_length(file, ptr, length); case MYSQL_TYPE_STRING: my_snprintf(typestr, typestr_length, "STRING(%d)", length); - return my_b_write_quoted_with_length(file, ptr, length); + if (hexstring) + return my_b_write_quoted_hex_with_length(file, ptr, length); + else + return my_b_write_quoted_with_length(file, ptr, length); default: { @@ -1918,7 +1987,8 @@ my_b_printf(file, "### @%d=", i + 1); size_t size= log_event_print_value(file, value, td->type(i), td->field_metadata(i), - typestr, sizeof(typestr)); + typestr, sizeof(typestr), + print_event_info->dump_hexstring); if (!size) return 0; Index: client/mysqlbinlog.cc =================================================================== --- client/mysqlbinlog.cc (revision 4174) +++ client/mysqlbinlog.cc (revision 4186) @@ -65,6 +65,7 @@ static bool one_database=0, to_last_remote_log= 0, disable_log_bin= 0; static bool opt_hexdump= 0; +static bool opt_hexstring= 0; const char *base64_output_mode_names[]= {"NEVER", "AUTO", "ALWAYS", "UNSPEC", "DECODE-ROWS", NullS}; TYPELIB base64_output_mode_typelib= @@ -1072,6 +1073,8 @@ {"hexdump", 'H', "Augment output with hexadecimal and ASCII event dump.", &opt_hexdump, &opt_hexdump, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, + {"hexstring", 'x', "Output verbose(-v) string(CHAR/VARCHAR/TEXT/BLOB) in hex mode.", + &opt_hexstring, &opt_hexstring, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"host", 'h', "Get the binlog from server.", &host, &host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, {"local-load", 'l', "Prepare local temporary files for LOAD DATA INFILE in the specified directory.", @@ -1452,6 +1455,7 @@ strmov(print_event_info.delimiter, "/*!*/;"); print_event_info.verbose= short_form ? 0 : verbose; + print_event_info.dump_hexstring= opt_hexstring; rc= (remote_opt ? dump_remote_log_entries(&print_event_info, logname) : dump_local_log_entries(&print_event_info, logname));