Commit 2db4392b authored by Sergei Golubchik's avatar Sergei Golubchik

MDEV-4297 mysql --binary-mode

backport mysql --binary-mode (bug#11747577, bug#33048)
parent 16807b58
/* /*
Copyright (c) 2001, 2012, Oracle and/or its affiliates. All rights reserved. Copyright (c) 2001, 2012, Oracle and/or its affiliates.
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
......
...@@ -36,7 +36,7 @@ typedef struct st_line_buffer ...@@ -36,7 +36,7 @@ typedef struct st_line_buffer
extern LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file); extern LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file);
extern LINE_BUFFER *batch_readline_command(LINE_BUFFER *buffer, char * str); extern LINE_BUFFER *batch_readline_command(LINE_BUFFER *buffer, char * str);
extern char *batch_readline(LINE_BUFFER *buffer); extern char *batch_readline(LINE_BUFFER *buffer, bool binary_mode);
extern void batch_readline_end(LINE_BUFFER *buffer); extern void batch_readline_end(LINE_BUFFER *buffer);
#endif /* CLIENT_MY_READLINE_INCLUDED */ #endif /* CLIENT_MY_READLINE_INCLUDED */
/* /*
Copyright (c) 2000, 2012, Oracle and/or its affiliates. Copyright (c) 2000, 2012, Oracle and/or its affiliates.
Copyright (c) 2009, 2012, Monty Program Ab. Copyright (c) 2009, 2013, Monty Program Ab.
This program is free software; you can redistribute it and/or modify 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 it under the terms of the GNU General Public License as published by
...@@ -152,6 +152,7 @@ static uint verbose=0,opt_silent=0,opt_mysql_port=0, opt_local_infile=0; ...@@ -152,6 +152,7 @@ static uint verbose=0,opt_silent=0,opt_mysql_port=0, opt_local_infile=0;
static uint my_end_arg; static uint my_end_arg;
static char * opt_mysql_unix_port=0; static char * opt_mysql_unix_port=0;
static int connect_flag=CLIENT_INTERACTIVE; static int connect_flag=CLIENT_INTERACTIVE;
static my_bool opt_binary_mode= FALSE;
static int interrupted_query= 0; static int interrupted_query= 0;
static char *current_host,*current_db,*current_user=0,*opt_password=0, static char *current_host,*current_db,*current_user=0,*opt_password=0,
*current_prompt=0, *delimiter_str= 0, *current_prompt=0, *delimiter_str= 0,
...@@ -1056,9 +1057,10 @@ static void initialize_readline (char *name); ...@@ -1056,9 +1057,10 @@ static void initialize_readline (char *name);
static void fix_history(String *final_command); static void fix_history(String *final_command);
#endif #endif
static COMMANDS *find_command(char *name,char cmd_name); static COMMANDS *find_command(char *name);
static bool add_line(String &buffer,char *line,char *in_string, static COMMANDS *find_command(char cmd_name);
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 remove_cntrl(String &buffer);
static void print_table_data(MYSQL_RES *result); static void print_table_data(MYSQL_RES *result);
static void print_table_data_html(MYSQL_RES *result); static void print_table_data_html(MYSQL_RES *result);
...@@ -1077,6 +1079,45 @@ static sig_handler window_resize(int sig); ...@@ -1077,6 +1079,45 @@ static sig_handler window_resize(int sig);
#endif #endif
const char DELIMITER_NAME[]= "delimiter";
const uint DELIMITER_NAME_LEN= sizeof(DELIMITER_NAME) - 1;
inline bool is_delimiter_command(char *name, ulong len)
{
/*
Delimiter command has a parameter, so the length of the whole command
is larger than DELIMITER_NAME_LEN. We don't care the parameter, so
only name(first DELIMITER_NAME_LEN bytes) is checked.
*/
return (len >= DELIMITER_NAME_LEN &&
!my_strnncoll(charset_info, (uchar*) name, DELIMITER_NAME_LEN,
(uchar *) DELIMITER_NAME, DELIMITER_NAME_LEN));
}
/**
Get the index of a command in the commands array.
@param cmd_char Short form command.
@return int
The index of the command is returned if it is found, else -1 is returned.
*/
inline int get_command_index(char cmd_char)
{
/*
All client-specific commands are in the first part of commands array
and have a function to implement it.
*/
for (uint i= 0; *commands[i].func; i++)
if (commands[i].cmd_char == cmd_char)
return i;
return -1;
}
static int delimiter_index= -1;
static int charset_index= -1;
static bool real_binary_mode= FALSE;
int main(int argc,char *argv[]) int main(int argc,char *argv[])
{ {
char buff[80]; char buff[80];
...@@ -1085,6 +1126,8 @@ int main(int argc,char *argv[]) ...@@ -1085,6 +1126,8 @@ int main(int argc,char *argv[])
DBUG_ENTER("main"); DBUG_ENTER("main");
DBUG_PROCESS(argv[0]); DBUG_PROCESS(argv[0]);
charset_index= get_command_index('C');
delimiter_index= get_command_index('d');
delimiter_str= delimiter; delimiter_str= delimiter;
default_prompt = my_strdup(getenv("MYSQL_PS1") ? default_prompt = my_strdup(getenv("MYSQL_PS1") ?
getenv("MYSQL_PS1") : getenv("MYSQL_PS1") :
...@@ -1598,6 +1641,13 @@ static struct my_option my_long_options[] = ...@@ -1598,6 +1641,13 @@ static struct my_option my_long_options[] =
"Default authentication client-side plugin to use.", "Default authentication client-side plugin to use.",
&opt_default_auth, &opt_default_auth, 0, &opt_default_auth, &opt_default_auth, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"binary-mode", 0,
"By default, ASCII '\\0' is disallowed and '\\r\\n' is translated to '\\n'. "
"This switch turns off both features, and also turns off parsing of all client"
"commands except \\C and DELIMITER, in non-interactive mode (for input "
"piped to mysql or loaded using the 'source' command). This is necessary "
"when processing output from mysqlbinlog that may contain blobs.",
&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} { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
}; };
...@@ -1878,24 +1928,59 @@ static int read_and_execute(bool interactive) ...@@ -1878,24 +1928,59 @@ static int read_and_execute(bool interactive)
ulong line_number=0; ulong line_number=0;
bool ml_comment= 0; bool ml_comment= 0;
COMMANDS *com; COMMANDS *com;
ulong line_length= 0;
status.exit_status=1; status.exit_status=1;
real_binary_mode= !interactive && opt_binary_mode;
while (!aborted) while (!aborted)
{ {
if (!interactive) if (!interactive)
{ {
line=batch_readline(status.line_buff);
/* /*
Skip UTF8 Byte Order Marker (BOM) 0xEFBBBF. batch_readline can return 0 on EOF or error.
Editors like "notepad" put this marker in In that case, we need to double check that we have a valid
the very beginning of a text file when line before actually setting line_length to read_length.
you save the file using "Unicode UTF-8" format.
*/ */
if (line && !line_number && line= batch_readline(status.line_buff, real_binary_mode);
(uchar) line[0] == 0xEF && if (line)
(uchar) line[1] == 0xBB && {
(uchar) line[2] == 0xBF) line_length= status.line_buff->read_length;
line+= 3;
/*
ASCII 0x00 is not allowed appearing in queries if it is not in binary
mode.
*/
if (!real_binary_mode && strlen(line) != line_length)
{
status.exit_status= 1;
String msg;
msg.append("ASCII '\\0' appeared in the statement, but this is not "
"allowed unless option --binary-mode is enabled and mysql is "
"run in non-interactive mode. Set --binary-mode to 1 if ASCII "
"'\\0' 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
the very beginning of a text file when
you save the file using "Unicode UTF-8" format.
*/
if (!line_number &&
(uchar) line[0] == 0xEF &&
(uchar) line[1] == 0xBB &&
(uchar) line[2] == 0xBF)
{
line+= 3;
// decrease the line length accordingly to the 3 bytes chopped
line_length -=3;
}
}
line_number++; line_number++;
if (!glob_buffer.length()) if (!glob_buffer.length())
status.query_start_line=line_number; status.query_start_line=line_number;
...@@ -1946,6 +2031,8 @@ static int read_and_execute(bool interactive) ...@@ -1946,6 +2031,8 @@ static int read_and_execute(bool interactive)
*/ */
if (opt_outfile && line) if (opt_outfile && line)
fprintf(OUTFILE, "%s\n", line); fprintf(OUTFILE, "%s\n", line);
line_length= line ? strlen(line) : 0;
} }
// End of file or system error // End of file or system error
if (!line) if (!line)
...@@ -1962,7 +2049,7 @@ static int read_and_execute(bool interactive) ...@@ -1962,7 +2049,7 @@ static int read_and_execute(bool interactive)
(We want to allow help, print and clear anywhere at line start (We want to allow help, print and clear anywhere at line start
*/ */
if ((named_cmds || glob_buffer.is_empty()) if ((named_cmds || glob_buffer.is_empty())
&& !ml_comment && !in_string && (com=find_command(line,0))) && !ml_comment && !in_string && (com= find_command(line)))
{ {
if ((*com->func)(&glob_buffer,line) > 0) if ((*com->func)(&glob_buffer,line) > 0)
break; break;
...@@ -1974,7 +2061,7 @@ static int read_and_execute(bool interactive) ...@@ -1974,7 +2061,7 @@ static int read_and_execute(bool interactive)
#endif #endif
continue; continue;
} }
if (add_line(glob_buffer, line, &in_string, &ml_comment, if (add_line(glob_buffer, line, line_length, &in_string, &ml_comment,
status.line_buff ? status.line_buff->truncated : 0)) status.line_buff ? status.line_buff->truncated : 0))
break; break;
} }
...@@ -1996,70 +2083,131 @@ static int read_and_execute(bool interactive) ...@@ -1996,70 +2083,131 @@ static int read_and_execute(bool interactive)
tmpbuf.free(); tmpbuf.free();
#endif #endif
/*
If the function is called by 'source' command, it will return to interactive
mode, so real_binary_mode should be FALSE. Otherwise, it will exit the
program, it is safe to set real_binary_mode to FALSE.
*/
real_binary_mode= FALSE;
return status.exit_status; return status.exit_status;
} }
static COMMANDS *find_command(char *name,char cmd_char) /**
It checks if the input is a short form command. It returns the command's
pointer if a command is found, else return NULL. Note that if binary-mode
is set, then only \C is searched for.
@param cmd_char A character of one byte.
@return
the command's pointer or NULL.
*/
static COMMANDS *find_command(char cmd_char)
{
DBUG_ENTER("find_command");
DBUG_PRINT("enter", ("cmd_char: %d", cmd_char));
int index= -1;
/*
In binary-mode, we disallow all mysql commands except '\C'
and DELIMITER.
*/
if (real_binary_mode)
{
if (cmd_char == 'C')
index= charset_index;
}
else
index= get_command_index(cmd_char);
if (index >= 0)
{
DBUG_PRINT("exit",("found command: %s", commands[index].name));
DBUG_RETURN(&commands[index]);
}
else
DBUG_RETURN((COMMANDS *) 0);
}
/**
It checks if the input is a long form command. It returns the command's
pointer if a command is found, else return NULL. Note that if binary-mode
is set, then only DELIMITER is searched for.
@param name A string.
@return
the command's pointer or NULL.
*/
static COMMANDS *find_command(char *name)
{ {
uint len; uint len;
char *end; char *end;
DBUG_ENTER("find_command"); DBUG_ENTER("find_command");
DBUG_PRINT("enter",("name: '%s' char: %d", name ? name : "NULL", cmd_char));
if (!name) DBUG_ASSERT(name != NULL);
DBUG_PRINT("enter", ("name: '%s'", name));
while (my_isspace(charset_info, *name))
name++;
/*
If there is an \\g in the row or if the row has a delimiter but
this is not a delimiter command, let add_line() take care of
parsing the row and calling find_command().
*/
if ((!real_binary_mode && strstr(name, "\\g")) ||
(strstr(name, delimiter) &&
!is_delimiter_command(name, DELIMITER_NAME_LEN)))
DBUG_RETURN((COMMANDS *) 0);
if ((end=strcont(name, " \t")))
{ {
len=0; len=(uint) (end - name);
end=0; while (my_isspace(charset_info, *end))
end++;
if (!*end)
end= 0; // no arguments to function
}
else
len= (uint) strlen(name);
int index= -1;
if (real_binary_mode)
{
if (is_delimiter_command(name, len))
index= delimiter_index;
} }
else else
{ {
while (my_isspace(charset_info,*name))
name++;
/* /*
If there is an \\g in the row or if the row has a delimiter but All commands are in the first part of commands array and have a function
this is not a delimiter command, let add_line() take care of to implement it.
parsing the row and calling find_command()
*/ */
if (strstr(name, "\\g") || (strstr(name, delimiter) && for (uint i= 0; commands[i].func; i++)
!(strlen(name) >= 9 &&
!my_strnncoll(&my_charset_latin1,
(uchar*) name, 9,
(const uchar*) "delimiter",
9))))
DBUG_RETURN((COMMANDS *) 0);
if ((end=strcont(name," \t")))
{ {
len=(uint) (end - name); if (!my_strnncoll(&my_charset_latin1, (uchar*) name, len,
while (my_isspace(charset_info,*end)) (uchar*) commands[i].name, len) &&
end++; (commands[i].name[len] == '\0') &&
if (!*end) (!end || commands[i].takes_params))
end=0; // no arguments to function {
index= i;
break;
}
} }
else
len=(uint) strlen(name);
} }
for (uint i= 0; commands[i].name; i++) if (index >= 0)
{ {
if (commands[i].func && DBUG_PRINT("exit", ("found command: %s", commands[index].name));
(((name && DBUG_RETURN(&commands[index]);
!my_strnncoll(&my_charset_latin1, (uchar*) name, len,
(uchar*) commands[i].name, len) &&
!commands[i].name[len] &&
(!end || (end && commands[i].takes_params)))) ||
(!name && commands[i].cmd_char == cmd_char)))
{
DBUG_PRINT("exit",("found command: %s", commands[i].name));
DBUG_RETURN(&commands[i]);
}
} }
DBUG_RETURN((COMMANDS *) 0); DBUG_RETURN((COMMANDS *) 0);
} }
static bool add_line(String &buffer,char *line,char *in_string, static bool add_line(String &buffer, char *line, ulong line_length,
bool *ml_comment, bool truncated) char *in_string, bool *ml_comment, bool truncated)
{ {
uchar inchar; uchar inchar;
char buff[80], *pos, *out; char buff[80], *pos, *out;
...@@ -2074,10 +2222,11 @@ static bool add_line(String &buffer,char *line,char *in_string, ...@@ -2074,10 +2222,11 @@ static bool add_line(String &buffer,char *line,char *in_string,
if (status.add_to_history && line[0] && not_in_history(line)) if (status.add_to_history && line[0] && not_in_history(line))
add_history(line); add_history(line);
#endif #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) if (!preserve_comments)
{ {
// Skip spaces at the beginning of a statement // Skip spaces at the beginning of a statement
...@@ -2117,7 +2266,7 @@ static bool add_line(String &buffer,char *line,char *in_string, ...@@ -2117,7 +2266,7 @@ static bool add_line(String &buffer,char *line,char *in_string,
*out++= (char) inchar; *out++= (char) inchar;
continue; continue;
} }
if ((com=find_command(NullS,(char) inchar))) if ((com= find_command((char) inchar)))
{ {
// Flush previously accepted characters // Flush previously accepted characters
if (out != line) if (out != line)
...@@ -2193,7 +2342,7 @@ static bool add_line(String &buffer,char *line,char *in_string, ...@@ -2193,7 +2342,7 @@ static bool add_line(String &buffer,char *line,char *in_string,
pos--; pos--;
if ((com= find_command(buffer.c_ptr(), 0))) if ((com= find_command(buffer.c_ptr())))
{ {
if ((*com->func)(&buffer, buffer.c_ptr()) > 0) if ((*com->func)(&buffer, buffer.c_ptr()) > 0)
...@@ -2312,9 +2461,7 @@ static bool add_line(String &buffer,char *line,char *in_string, ...@@ -2312,9 +2461,7 @@ static bool add_line(String &buffer,char *line,char *in_string,
{ {
uint length=(uint) (out-line); uint length=(uint) (out-line);
if (!truncated && (length < 9 || if (!truncated && (!is_delimiter_command(line, length) ||
my_strnncoll (charset_info, (uchar *)line, 9,
(const uchar *) "delimiter", 9) ||
(*in_string || *ml_comment))) (*in_string || *ml_comment)))
{ {
/* /*
......
...@@ -206,10 +206,8 @@ void print_annotate_event(PRINT_EVENT_INFO *print_event_info) ...@@ -206,10 +206,8 @@ void print_annotate_event(PRINT_EVENT_INFO *print_event_info)
} }
} }
static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info, static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *, const char*);
const char* logname); static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *, const char*);
static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
const char* logname);
static Exit_status dump_log_entries(const char* logname); static Exit_status dump_log_entries(const char* logname);
static Exit_status safe_connect(); static Exit_status safe_connect();
......
...@@ -54,7 +54,7 @@ LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file) ...@@ -54,7 +54,7 @@ LINE_BUFFER *batch_readline_init(ulong max_size,FILE *file)
} }
char *batch_readline(LINE_BUFFER *line_buff) char *batch_readline(LINE_BUFFER *line_buff, bool binary_mode)
{ {
char *pos; char *pos;
ulong out_length; ulong out_length;
...@@ -63,8 +63,17 @@ char *batch_readline(LINE_BUFFER *line_buff) ...@@ -63,8 +63,17 @@ char *batch_readline(LINE_BUFFER *line_buff)
if (!(pos=intern_read_line(line_buff, &out_length))) if (!(pos=intern_read_line(line_buff, &out_length)))
return 0; return 0;
if (out_length && pos[out_length-1] == '\n') if (out_length && pos[out_length-1] == '\n')
if (--out_length && pos[out_length-1] == '\r') /* Remove '\n' */ {
out_length--; /* Remove '\r' */ /*
On Windows platforms we also need to remove '\r', unconditionally. On
Unix-like platforms we only remove it if we are not on binary mode.
*/
/* Remove '\n' */
if (--out_length && IF_WIN(1,!binary_mode) && pos[out_length-1] == '\r')
/* Remove '\r' */
out_length--;
}
line_buff->read_length=out_length; line_buff->read_length=out_length;
pos[out_length]=0; pos[out_length]=0;
return pos; return pos;
...@@ -226,7 +235,7 @@ char *intern_read_line(LINE_BUFFER *buffer, ulong *out_length) ...@@ -226,7 +235,7 @@ char *intern_read_line(LINE_BUFFER *buffer, ulong *out_length)
for (;;) for (;;)
{ {
pos=buffer->end_of_line; pos=buffer->end_of_line;
while (*pos != '\n' && *pos) while (*pos != '\n' && pos != buffer->end)
pos++; pos++;
if (pos == buffer->end) if (pos == buffer->end)
{ {
......
RESET MASTER;
# Bug#33048 Not able to recover binary/blob data correctly using mysqlbinlog
# --------------------------------------------------------------------------
# The test verify that 0x00 and 0x0D0A sequence can be handled correctly by
# mysql
CREATE TABLE `A
B` (c1 CHAR(100));
# It is a faked statement. ASCII 0 is in the original statement, it would
# make the test result to become a binary file which was difficult to get
# the diff result if the original query was logged in the result.
INSERT INTO `A\r\nB` VALUES("A\0B");
INSERT INTO `A
B` VALUES("A
B");
SELECT HEX(c1) FROM `A
B`;
HEX(c1)
410042
410D0A42
FLUSH LOGS;
DROP TABLE `A
B`;
RESET MASTER;
# '--exec mysql ...' without --binary-mode option
# It creates the table with a wrong table name and generates an error.
# (error output was suppressed to make the test case platform agnostic)
# It is not in binary_mode, so table name '0x410D0A42' can be translated to
# '0x410A42' by mysql depending on the OS - Windows or Unix-like.
DROP TABLE `TABLE_NAME_MASKED`;
# In binary_mode, table name '0x410D0A42' and string '0x410042' can be
# handled correctly.
RESET MASTER;
SELECT HEX(c1) FROM `A
B`;
HEX(c1)
410042
410D0A42
DROP TABLE `A
B`;
RESET MASTER;
include/assert.inc [Table and contents created through mysqltest match 0x610D0A62.]
include/assert.inc [Table and contents created while replaying binary log without --binary-mode set match 0x61(0D)0A62.]
include/assert.inc [Table and contents created while replaying binary log with --binary-mode set match 0x610D0A62.]
source include/have_binlog_format_mixed_or_statement.inc;
RESET MASTER;
--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
# zero => 0x00, newline => 0x0D0A, A => 0x41, B => 0x42
# 0x410D0A42 => 'A\r\nB'
let $table_name_right= `SELECT 0x410D0A42`;
# 0x410A42 => 'A\nB'
let $table_name_wrong= `SELECT 0x410A42`;
# 0x410042 => 'A\0B'
let $char0= `SELECT 0x410042`;
eval CREATE TABLE `$table_name_right` (c1 CHAR(100));
--echo # It is a faked statement. ASCII 0 is in the original statement, it would
--echo # make the test result to become a binary file which was difficult to get
--echo # the diff result if the original query was logged in the result.
--echo INSERT INTO `A\r\nB` VALUES("A\0B");
--echo
--disable_query_log
eval INSERT INTO `$table_name_right` VALUES("$char0");
--enable_query_log
let $char0= $table_name_right;
eval INSERT INTO `$table_name_right` VALUES("$char0");
eval SELECT HEX(c1) FROM `$table_name_right`;
--echo
let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1);
FLUSH LOGS;
eval DROP TABLE `$table_name_right`;
--echo
let $MYSQLD_DATADIR= `SELECT @@datadir`;
--exec $MYSQL_BINLOG $MYSQLD_DATADIR/$binlog_file > $MYSQLTEST_VARDIR/tmp/my.sql
RESET MASTER;
--echo # '--exec mysql ...' without --binary-mode option
--echo # It creates the table with a wrong table name and generates an error.
--echo # (error output was suppressed to make the test case platform agnostic)
## disabling result log because the error message has the
## table name in the output which is one byte different ('\r')
## on unixes and windows.
--disable_result_log
--error 1
--exec $MYSQL test < $MYSQLTEST_VARDIR/tmp/my.sql 2>&1
--enable_result_log
--echo
--echo # It is not in binary_mode, so table name '0x410D0A42' can be translated to
--echo # '0x410A42' by mysql depending on the OS - Windows or Unix-like.
--replace_result $table_name_wrong TABLE_NAME_MASKED $table_name_right TABLE_NAME_MASKED
if (`SELECT CONVERT(@@VERSION_COMPILE_OS USING latin1) IN ('Win32', 'Win64', 'Windows')`)
{
eval DROP TABLE `$table_name_right`;
}
if (`SELECT CONVERT(@@VERSION_COMPILE_OS USING latin1) NOT IN ('Win32', 'Win64', 'Windows')`)
{
eval DROP TABLE `$table_name_wrong`;
}
--echo
--echo # In binary_mode, table name '0x410D0A42' and string '0x410042' can be
--echo # handled correctly.
RESET MASTER;
--exec $MYSQL --binary-mode test < $MYSQLTEST_VARDIR/tmp/my.sql
eval SELECT HEX(c1) FROM `$table_name_right`;
--echo
eval DROP TABLE `$table_name_right`;
#
# BUG#12794048 - MAIN.MYSQL_BINARY_MODE FAILS ON WINDOWS RELEASE BUILD
#
RESET MASTER;
#
# This test case tests if the table names and their values
# are handled properly. For that we check
#
# 0x610D0A62 => 'a\r\nb'
let $tbl= `SELECT 0x610D0A62`;
--disable_result_log
--disable_query_log
--let $binlog_file= query_get_value(SHOW MASTER STATUS, File, 1)
#### case #1: mysqltest
#### CREATE table and insert value through regular mysqltest session
--eval CREATE TABLE `$tbl` (c1 CHAR(100))
--eval INSERT INTO `$tbl` VALUES ("$tbl")
--let $table_name=`SELECT table_name FROM information_schema.tables WHERE table_schema='test'`
--let $tbl0= `SELECT HEX(table_name) FROM information_schema.tables WHERE table_schema='test'`
--let $val0= `SELECT HEX(c1) FROM `$table_name` LIMIT 1`
FLUSH LOGS;
--eval DROP TABLE `$table_name`;
#### case #2: mysql --binlog-mode=0
#### Replay through regular mysql client non-interactive mode
--let $MYSQLD_DATADIR= `SELECT @@datadir`
--let $prefix=`SELECT UUID()`
--let $binlog_uuid_filename= $MYSQLTEST_VARDIR/tmp/$prefix-bin.log
--copy_file $MYSQLD_DATADIR/$binlog_file $binlog_uuid_filename
RESET MASTER;
--exec $MYSQL_BINLOG $binlog_uuid_filename | $MYSQL
--let $table_name=`SELECT table_name FROM information_schema.tables WHERE table_schema='test'`
--let $tbl1= `SELECT hex(table_name) FROM information_schema.tables WHERE table_schema='test'`
--let $val1= `SELECT HEX(c1) FROM `$table_name` LIMIT 1`
--eval DROP TABLE `$table_name`;
#### case #3: mysql --binlog-mode=1
#### Replay through regular mysql client non-interactive mode and with binary mode set
RESET MASTER;
--exec $MYSQL_BINLOG $binlog_uuid_filename | $MYSQL --binary-mode
--let $table_name=`SELECT table_name FROM information_schema.tables WHERE table_schema='test'`
--let $tbl2= `SELECT hex(table_name) FROM information_schema.tables WHERE table_schema='test'`
--let $val2= `SELECT HEX(c1) FROM `$table_name` LIMIT 1`
--eval DROP TABLE `$table_name`;
--enable_result_log
--disable_query_log
##### OUTCOME
--let $assert_text= Table and contents created through mysqltest match 0x610D0A62.
--let $assert_cond= "$tbl0" = "610D0A62" AND "$val0" = "610D0A62"
--source include/assert.inc
--let $assert_text= Table and contents created while replaying binary log without --binary-mode set match 0x61(0D)0A62.
if (`SELECT CONVERT(@@VERSION_COMPILE_OS USING latin1) IN ('Win32', 'Win64', 'Windows')`)
{
--let $assert_cond= "$tbl1" = "610D0A62" AND "$val1" = "610D0A62"
}
if (`SELECT CONVERT(@@VERSION_COMPILE_OS USING latin1) NOT IN ('Win32', 'Win64', 'Windows')`)
{
--let $assert_cond= "$tbl1" = "610A62" AND "$val1" = "610A62"
}
--source include/assert.inc
--let $assert_text= Table and contents created while replaying binary log with --binary-mode set match 0x610D0A62.
--let $assert_cond= "$tbl2" = "610D0A62" AND "$val2" = "610D0A62"
--source include/assert.inc
RESET MASTER;
--remove_file $binlog_uuid_filename
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment