summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to 'client')
-rw-r--r--client/client_priv.h2
-rw-r--r--client/completion_hash.h7
-rw-r--r--client/echo.c5
-rw-r--r--client/get_password.c5
-rw-r--r--client/my_readline.h2
-rw-r--r--client/mysql.cc325
-rw-r--r--client/mysql_plugin.c2
-rw-r--r--client/mysql_upgrade.c71
-rw-r--r--client/mysqladmin.cc2
-rw-r--r--client/mysqlbinlog.cc200
-rw-r--r--client/mysqlcheck.c91
-rw-r--r--client/mysqldump.c21
-rw-r--r--client/mysqltest.cc30
-rw-r--r--client/readline.cc17
-rw-r--r--client/sql_string.cc.dontuse4
-rw-r--r--client/sql_string.h.dontuse3
16 files changed, 545 insertions, 242 deletions
diff --git a/client/client_priv.h b/client/client_priv.h
index 8c713d73200..656c8fcf32a 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2001, 2011, 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
it under the terms of the GNU General Public License as published by
diff --git a/client/completion_hash.h b/client/completion_hash.h
index 8e1b2d6e453..70c2cf1b371 100644
--- a/client/completion_hash.h
+++ b/client/completion_hash.h
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000-2002 MySQL AB
+/* Copyright (c) 2000-2002, 2006 MySQL AB
+ Use is subject to license terms
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU Library General Public
@@ -12,8 +13,8 @@
You should have received a copy of the GNU Library General Public
License along with this library; if not, write to the Free
- Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
- MA 02111-1307, USA */
+ Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
+ MA 02110-1301, USA */
#ifndef _HASH_
#define _HASH_
diff --git a/client/echo.c b/client/echo.c
index e3d22edb3ae..2a3cb915d23 100644
--- a/client/echo.c
+++ b/client/echo.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000 MySQL AB
+/* Copyright (c) 2000, 2007 MySQL AB
+ Use is subject to license terms
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
@@ -11,7 +12,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
/*
echo is a replacement for the "echo" command builtin to cmd.exe
diff --git a/client/get_password.c b/client/get_password.c
index 09d307b5553..8a507d94e9b 100644
--- a/client/get_password.c
+++ b/client/get_password.c
@@ -1,4 +1,5 @@
-/* Copyright (C) 2000 MySQL AB
+/* Copyright (c) 2000, 2001, 2003, 2006, 2008 MySQL AB
+ Use is subject to license terms
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
@@ -11,7 +12,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
/*
** Ask for a password from tty
diff --git a/client/my_readline.h b/client/my_readline.h
index 11ace987b44..57537308fed 100644
--- a/client/my_readline.h
+++ b/client/my_readline.h
@@ -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_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);
#endif /* CLIENT_MY_READLINE_INCLUDED */
diff --git a/client/mysql.cc b/client/mysql.cc
index bb57c43674e..90310f85e95 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -1,6 +1,6 @@
/*
- Copyright (c) 2000, 2012, Oracle and/or its affiliates.
- Copyright (c) 2009, 2012, Monty Program Ab.
+ Copyright (c) 2000, 2013, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2013, Monty Program Ab.
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
@@ -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 char * opt_mysql_unix_port=0;
static int connect_flag=CLIENT_INTERACTIVE;
+static my_bool opt_binary_mode= FALSE;
static int interrupted_query= 0;
static char *current_host,*current_db,*current_user=0,*opt_password=0,
*current_prompt=0, *delimiter_str= 0,
@@ -1056,9 +1057,10 @@ static void initialize_readline (char *name);
static void fix_history(String *final_command);
#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 COMMANDS *find_command(char *name);
+static COMMANDS *find_command(char cmd_name);
+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);
@@ -1077,6 +1079,45 @@ static sig_handler window_resize(int sig);
#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[])
{
char buff[80];
@@ -1085,6 +1126,8 @@ int main(int argc,char *argv[])
DBUG_ENTER("main");
DBUG_PROCESS(argv[0]);
+ charset_index= get_command_index('C');
+ delimiter_index= get_command_index('d');
delimiter_str= delimiter;
default_prompt = my_strdup(getenv("MYSQL_PS1") ?
getenv("MYSQL_PS1") :
@@ -1598,6 +1641,13 @@ static struct my_option my_long_options[] =
"Default authentication client-side plugin to use.",
&opt_default_auth, &opt_default_auth, 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}
};
@@ -1635,7 +1685,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
{
switch(optid) {
case OPT_CHARSETS_DIR:
- strmake(mysql_charsets_dir, argument, sizeof(mysql_charsets_dir) - 1);
+ strmake_buf(mysql_charsets_dir, argument);
charsets_dir = mysql_charsets_dir;
break;
case OPT_DELIMITER:
@@ -1648,7 +1698,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
/* Check that delimiter does not contain a backslash */
if (!strstr(argument, "\\"))
{
- strmake(delimiter, argument, sizeof(delimiter) - 1);
+ strmake_buf(delimiter, argument);
}
else
{
@@ -1680,7 +1730,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
if (argument && strlen(argument))
{
default_pager_set= 1;
- strmake(pager, argument, sizeof(pager) - 1);
+ strmake_buf(pager, argument);
strmov(default_pager, pager);
}
else if (default_pager_set)
@@ -1873,29 +1923,64 @@ static int read_and_execute(bool interactive)
String buffer;
#endif
- char *line= 0;
+ char *line= NULL;
char in_string=0;
ulong line_number=0;
bool ml_comment= 0;
COMMANDS *com;
+ ulong line_length= 0;
status.exit_status=1;
+ real_binary_mode= !interactive && opt_binary_mode;
while (!aborted)
{
if (!interactive)
{
- line=batch_readline(status.line_buff);
/*
- 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.
+ batch_readline can return 0 on EOF or error.
+ In that case, we need to double check that we have a valid
+ line before actually setting line_length to read_length.
*/
- if (line && !line_number &&
- (uchar) line[0] == 0xEF &&
- (uchar) line[1] == 0xBB &&
- (uchar) line[2] == 0xBF)
- line+= 3;
+ line= batch_readline(status.line_buff, real_binary_mode);
+ if (line)
+ {
+ line_length= status.line_buff->read_length;
+
+ /*
+ 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++;
if (!glob_buffer.length())
status.query_start_line=line_number;
@@ -1937,6 +2022,13 @@ static int read_and_execute(bool interactive)
#else
if (opt_outfile)
fputs(prompt, OUTFILE);
+ /*
+ free the previous entered line.
+ Note: my_free() cannot be used here as the memory was allocated under
+ the readline/libedit library.
+ */
+ if (line)
+ free(line);
line= readline(prompt);
#endif /* defined(__WIN__) */
@@ -1946,6 +2038,8 @@ static int read_and_execute(bool interactive)
*/
if (opt_outfile && line)
fprintf(OUTFILE, "%s\n", line);
+
+ line_length= line ? strlen(line) : 0;
}
// End of file or system error
if (!line)
@@ -1962,7 +2056,7 @@ static int read_and_execute(bool interactive)
(We want to allow help, print and clear anywhere at line start
*/
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)
break;
@@ -1974,7 +2068,7 @@ static int read_and_execute(bool interactive)
#endif
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))
break;
}
@@ -1994,72 +2088,142 @@ static int read_and_execute(bool interactive)
#if defined(__WIN__)
buffer.free();
tmpbuf.free();
+#else
+ if (interactive)
+ /*
+ free the last entered line.
+ Note: my_free() cannot be used here as the memory was allocated under
+ the readline/libedit library.
+ */
+ free(line);
#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;
}
-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;
char *end;
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=(uint) (end - name);
+ 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)
{
- len=0;
- end=0;
+ if (is_delimiter_command(name, len))
+ index= delimiter_index;
}
else
{
- 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()
+ All commands are in the first part of commands array and have a function
+ to implement it.
*/
- if (strstr(name, "\\g") || (strstr(name, delimiter) &&
- !(strlen(name) >= 9 &&
- !my_strnncoll(&my_charset_latin1,
- (uchar*) name, 9,
- (const uchar*) "delimiter",
- 9))))
- DBUG_RETURN((COMMANDS *) 0);
- if ((end=strcont(name," \t")))
+ for (uint i= 0; commands[i].func; i++)
{
- len=(uint) (end - name);
- while (my_isspace(charset_info,*end))
- end++;
- if (!*end)
- end=0; // no arguments to function
+ if (!my_strnncoll(&my_charset_latin1, (uchar*) name, len,
+ (uchar*) commands[i].name, len) &&
+ (commands[i].name[len] == '\0') &&
+ (!end || commands[i].takes_params))
+ {
+ index= i;
+ break;
+ }
}
- else
- len=(uint) strlen(name);
}
- for (uint i= 0; commands[i].name; i++)
+ if (index >= 0)
{
- if (commands[i].func &&
- (((name &&
- !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_PRINT("exit", ("found command: %s", commands[index].name));
+ DBUG_RETURN(&commands[index]);
}
DBUG_RETURN((COMMANDS *) 0);
}
-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;
@@ -2074,10 +2238,11 @@ static bool add_line(String &buffer,char *line,char *in_string,
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
@@ -2117,7 +2282,7 @@ static bool add_line(String &buffer,char *line,char *in_string,
*out++= (char) inchar;
continue;
}
- if ((com=find_command(NullS,(char) inchar)))
+ if ((com= find_command((char) inchar)))
{
// Flush previously accepted characters
if (out != line)
@@ -2193,7 +2358,7 @@ static bool add_line(String &buffer,char *line,char *in_string,
pos--;
- if ((com= find_command(buffer.c_ptr(), 0)))
+ if ((com= find_command(buffer.c_ptr())))
{
if ((*com->func)(&buffer, buffer.c_ptr()) > 0)
@@ -2312,17 +2477,17 @@ static bool add_line(String &buffer,char *line,char *in_string,
{
uint length=(uint) (out-line);
- if (!truncated &&
- (length < 9 ||
- my_strnncoll (charset_info,
- (uchar *)line, 9, (const uchar *) "delimiter", 9)))
+ if (!truncated && (!is_delimiter_command(line, length) ||
+ (*in_string || *ml_comment)))
{
/*
Don't add a new line in case there's a DELIMITER command to be
added to the glob buffer (e.g. on processing a line like
"<command>;DELIMITER <non-eof>") : similar to how a new line is
not added in the case when the DELIMITER is the first command
- entered with an empty glob buffer.
+ entered with an empty glob buffer. However, if the delimiter is
+ part of a string or a comment, the new line should be added. (e.g.
+ SELECT '\ndelimiter\n';\n)
*/
*out++='\n';
length++;
@@ -2959,7 +3124,7 @@ com_charset(String *buffer __attribute__((unused)), char *line)
{
char buff[256], *param;
CHARSET_INFO * new_cs;
- strmake(buff, line, sizeof(buff) - 1);
+ strmake_buf(buff, line);
param= get_arg(buff, 0);
if (!param || !*param)
{
@@ -3196,7 +3361,7 @@ static void init_tee(const char *file_name)
return;
}
OUTFILE = new_outfile;
- strmake(outfile, file_name, FN_REFLEN-1);
+ strmake_buf(outfile, file_name);
tee_fprintf(stdout, "Logging to file '%s'\n", file_name);
opt_outfile= 1;
return;
@@ -3826,7 +3991,7 @@ com_tee(String *buffer __attribute__((unused)),
/* eliminate the spaces before the parameters */
while (my_isspace(charset_info,*param))
param++;
- end= strmake(file_name, param, sizeof(file_name) - 1);
+ end= strmake_buf(file_name, param);
/* remove end space from command line */
while (end > file_name && (my_isspace(charset_info,end[-1]) ||
my_iscntrl(charset_info,end[-1])))
@@ -3887,7 +4052,7 @@ com_pager(String *buffer __attribute__((unused)),
}
else
{
- end= strmake(pager_name, param, sizeof(pager_name)-1);
+ end= strmake_buf(pager_name, param);
while (end > pager_name && (my_isspace(charset_info,end[-1]) ||
my_iscntrl(charset_info,end[-1])))
end--;
@@ -4100,7 +4265,7 @@ static int com_source(String *buffer __attribute__((unused)),
INFO_ERROR, 0);
while (my_isspace(charset_info,*param))
param++;
- end=strmake(source_name,param,sizeof(source_name)-1);
+ end=strmake_buf(source_name, param);
while (end > source_name && (my_isspace(charset_info,end[-1]) ||
my_iscntrl(charset_info,end[-1])))
end--;
@@ -4153,7 +4318,7 @@ com_delimiter(String *buffer __attribute__((unused)), char *line)
{
char buff[256], *tmp;
- strmake(buff, line, sizeof(buff) - 1);
+ strmake_buf(buff, line);
tmp= get_arg(buff, 0);
if (!tmp || !*tmp)
@@ -4170,7 +4335,7 @@ com_delimiter(String *buffer __attribute__((unused)), char *line)
return 0;
}
}
- strmake(delimiter, tmp, sizeof(delimiter) - 1);
+ strmake_buf(delimiter, tmp);
delimiter_length= (int)strlen(delimiter);
delimiter_str= delimiter;
return 0;
@@ -4184,7 +4349,7 @@ com_use(String *buffer __attribute__((unused)), char *line)
int select_db;
bzero(buff, sizeof(buff));
- strmake(buff, line, sizeof(buff) - 1);
+ strmake_buf(buff, line);
tmp= get_arg(buff, 0);
if (!tmp || !*tmp)
{
@@ -4728,7 +4893,13 @@ put_info(const char *str,INFO_TYPE info_type, uint error, const char *sqlstate)
if (info_type == INFO_ERROR)
{
if (!opt_nobeep)
+ {
+#ifdef _WIN32
+ MessageBeep(MB_ICONWARNING);
+#else
putchar('\a'); /* This should make a bell */
+#endif
+ }
vidattr(A_STANDOUT);
if (error)
{
diff --git a/client/mysql_plugin.c b/client/mysql_plugin.c
index f4e3111b7b7..b6fa350b54a 100644
--- a/client/mysql_plugin.c
+++ b/client/mysql_plugin.c
@@ -12,7 +12,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <m_string.h>
diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c
index 9a3c56507e7..8b3f0fdec79 100644
--- a/client/mysql_upgrade.c
+++ b/client/mysql_upgrade.c
@@ -1,6 +1,6 @@
/*
- Copyright (c) 2006, 2012, Oracle and/or its affiliates.
- Copyright (C) 2010, 2012, Monty Program Ab.
+ Copyright (c) 2006, 2013, Oracle and/or its affiliates.
+ Copyright (c) 2010, 2013, Monty Program Ab.
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
@@ -40,7 +40,7 @@ static char mysql_path[FN_REFLEN];
static char mysqlcheck_path[FN_REFLEN];
static my_bool opt_force, opt_verbose, debug_info_flag, debug_check_flag,
- opt_systables_only;
+ opt_systables_only, opt_version_check;
static my_bool opt_not_used, opt_silent;
static uint my_end_arg= 0;
static char *opt_user= (char*)"root";
@@ -150,6 +150,12 @@ static struct my_option my_long_options[]=
&opt_not_used, &opt_not_used, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
{"version", 'V', "Output version information and exit.", 0, 0, 0,
GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"version-check", 'k', "Run this program only if its \'server version\' "
+ "matches the version of the server to which it's connecting, (enabled by "
+ "default); use --skip-version-check to avoid this check. Note: the \'server "
+ "version\' of the program is the version of the MySQL server with which it "
+ "was built/distributed.", &opt_version_check, &opt_version_check, 0,
+ GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
{"write-binlog", OPT_WRITE_BINLOG,
"All commands including mysqlcheck are binlogged. Enabled by default;"
"use --skip-write-binlog when commands should not be sent to replication slaves.",
@@ -291,6 +297,7 @@ get_one_option(int optid, const struct my_option *opt,
my_progname, optid == 'b' ? "basedir" : "datadir");
/* FALLTHROUGH */
+ case 'k': /* --version-check */
case 'v': /* --verbose */
opt_verbose++;
if (argument == disabled_my_option)
@@ -564,6 +571,8 @@ static int run_query(const char *query, DYNAMIC_STRING *ds_res,
static int extract_variable_from_show(DYNAMIC_STRING* ds, char* value)
{
char *value_start, *value_end;
+ size_t len;
+
/*
The query returns "datadir\t<datadir>\n", skip past
the tab
@@ -576,7 +585,9 @@ static int extract_variable_from_show(DYNAMIC_STRING* ds, char* value)
if ((value_end= strchr(value_start, '\n')) == NULL)
return 1; /* Unexpected result */
- strncpy(value, value_start, MY_MIN(FN_REFLEN, value_end-value_start));
+ len= (size_t) MY_MIN(FN_REFLEN, value_end-value_start);
+ strncpy(value, value_start, len);
+ value[len]= '\0';
return 0;
}
@@ -874,6 +885,55 @@ static const char *load_default_groups[]=
};
+/* Convert the specified version string into the numeric format. */
+static ulong STDCALL calc_server_version(char *some_version)
+{
+ uint major, minor, version;
+ char *point= some_version, *end_point;
+ major= (uint) strtoul(point, &end_point, 10); point=end_point+1;
+ minor= (uint) strtoul(point, &end_point, 10); point=end_point+1;
+ version= (uint) strtoul(point, &end_point, 10);
+ return (ulong) major * 10000L + (ulong)(minor * 100 + version);
+}
+
+/**
+ Check if the server version matches with the server version mysql_upgrade
+ was compiled with.
+
+ @return 0 match successful
+ 1 failed
+*/
+static int check_version_match(void)
+{
+ DYNAMIC_STRING ds_version;
+ char version_str[NAME_CHAR_LEN + 1];
+
+ if (init_dynamic_string(&ds_version, NULL, NAME_CHAR_LEN, NAME_CHAR_LEN))
+ die("Out of memory");
+
+ if (run_query("show variables like 'version'",
+ &ds_version, FALSE) ||
+ extract_variable_from_show(&ds_version, version_str))
+ {
+ dynstr_free(&ds_version);
+ return 1; /* Query failed */
+ }
+
+ dynstr_free(&ds_version);
+
+ if (calc_server_version((char *) version_str) != MYSQL_VERSION_ID)
+ {
+ fprintf(stderr, "Error: Server version (%s) does not match with the "
+ "version of\nthe server (%s) with which this program was built/"
+ "distributed. You can\nuse --skip-version-check to skip this "
+ "check.\n", version_str, MYSQL_SERVER_VERSION);
+ return 1;
+ }
+ else
+ return 0;
+}
+
+
int main(int argc, char **argv)
{
char self_name[FN_REFLEN];
@@ -938,6 +998,9 @@ int main(int argc, char **argv)
die(NULL);
}
+ if (opt_version_check && check_version_match())
+ die("Upgrade failed");
+
/*
Run "mysqlcheck" and "mysql_fix_privilege_tables.sql"
*/
diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc
index a45c3b85596..9a8901435c8 100644
--- a/client/mysqladmin.cc
+++ b/client/mysqladmin.cc
@@ -13,7 +13,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA */
/* maintaince of mysql databases */
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index 32c02d03f37..31a1d583c4f 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -1,6 +1,6 @@
/*
- Copyright (c) 2000, 2012, Oracle and/or its affiliates.
- Copyright (c) 2009, 2012, Monty Program Ab
+ Copyright (c) 2000, 2013, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2013, Monty Program Ab.
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
@@ -37,6 +37,7 @@
/* That one is necessary for defines of OPTION_NO_FOREIGN_KEY_CHECKS etc */
#include "sql_priv.h"
#include "log_event.h"
+#include "compat56.h"
#include "sql_common.h"
#include "my_dir.h"
#include <welcome_copyright_notice.h> // ORACLE_WELCOME_COPYRIGHT_NOTICE
@@ -206,10 +207,8 @@ void print_annotate_event(PRINT_EVENT_INFO *print_event_info)
}
}
-static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info,
- const char* logname);
-static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
- const char* logname);
+static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *, const char*);
+static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *, const char*);
static Exit_status dump_log_entries(const char* logname);
static Exit_status safe_connect();
@@ -818,6 +817,98 @@ write_event_header_and_base64(Log_event *ev, FILE *result_file,
}
+static bool print_base64(PRINT_EVENT_INFO *print_event_info, Log_event *ev)
+{
+ /*
+ These events must be printed in base64 format, if printed.
+ base64 format requires a FD event to be safe, so if no FD
+ event has been printed, we give an error. Except if user
+ passed --short-form, because --short-form disables printing
+ row events.
+ */
+ if (!print_event_info->printed_fd_event && !short_form &&
+ opt_base64_output_mode != BASE64_OUTPUT_DECODE_ROWS)
+ {
+ const char* type_str= ev->get_type_str();
+ if (opt_base64_output_mode == BASE64_OUTPUT_NEVER)
+ error("--base64-output=never specified, but binlog contains a "
+ "%s event which must be printed in base64.",
+ type_str);
+ else
+ error("malformed binlog: it does not contain any "
+ "Format_description_log_event. I now found a %s event, which "
+ "is not safe to process without a "
+ "Format_description_log_event.",
+ type_str);
+ return 1;
+ }
+ ev->print(result_file, print_event_info);
+ return print_event_info->head_cache.error == -1;
+}
+
+
+static bool print_row_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
+ ulong table_id, bool is_stmt_end)
+{
+ Table_map_log_event *ignored_map=
+ print_event_info->m_table_map_ignored.get_table(table_id);
+ bool skip_event= (ignored_map != NULL);
+
+ /*
+ end of statement check:
+ i) destroy/free ignored maps
+ ii) if skip event
+ a) since we are skipping the last event,
+ append END-MARKER(') to body cache (if required)
+
+ b) flush cache now
+ */
+ if (is_stmt_end)
+ {
+ /*
+ Now is safe to clear ignored map (clear_tables will also
+ delete original table map events stored in the map).
+ */
+ if (print_event_info->m_table_map_ignored.count() > 0)
+ print_event_info->m_table_map_ignored.clear_tables();
+
+ /*
+ If there is a kept Annotate event and all corresponding
+ rbr-events were filtered away, the Annotate event was not
+ freed and it is just the time to do it.
+ */
+ free_annotate_event();
+
+ /*
+ One needs to take into account an event that gets
+ filtered but was last event in the statement. If this is
+ the case, previous rows events that were written into
+ IO_CACHEs still need to be copied from cache to
+ result_file (as it would happen in ev->print(...) if
+ event was not skipped).
+ */
+ if (skip_event)
+ {
+ // append END-MARKER(') with delimiter
+ IO_CACHE *const body_cache= &print_event_info->body_cache;
+ if (my_b_tell(body_cache))
+ my_b_printf(body_cache, "'%s\n", print_event_info->delimiter);
+
+ // flush cache
+ if ((copy_event_cache_to_file_and_reinit(&print_event_info->head_cache, result_file) ||
+ copy_event_cache_to_file_and_reinit(&print_event_info->body_cache, result_file)))
+ return 1;
+ }
+ }
+
+ /* skip the event check */
+ if (skip_event)
+ return 0;
+
+ return print_base64(print_event_info, ev);
+}
+
+
/**
Print the given event, and either delete it or delegate the deletion
to someone else.
@@ -1130,86 +1221,29 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
error("Could not rewrite database name");
goto err;
}
+ if (print_base64(print_event_info, ev))
+ goto err;
+ break;
}
case WRITE_ROWS_EVENT:
case DELETE_ROWS_EVENT:
case UPDATE_ROWS_EVENT:
+ {
+ Rows_log_event *e= (Rows_log_event*) ev;
+ if (print_row_event(print_event_info, ev, e->get_table_id(),
+ e->get_flags(Rows_log_event::STMT_END_F)))
+ goto err;
+ break;
+ }
case PRE_GA_WRITE_ROWS_EVENT:
case PRE_GA_DELETE_ROWS_EVENT:
case PRE_GA_UPDATE_ROWS_EVENT:
{
- if (ev_type != TABLE_MAP_EVENT)
- {
- Rows_log_event *e= (Rows_log_event*) ev;
- Table_map_log_event *ignored_map=
- print_event_info->m_table_map_ignored.get_table(e->get_table_id());
- bool skip_event= (ignored_map != NULL);
-
- /*
- end of statement check:
- i) destroy/free ignored maps
- ii) if skip event, flush cache now
- */
- if (e->get_flags(Rows_log_event::STMT_END_F))
- {
- /*
- Now is safe to clear ignored map (clear_tables will also
- delete original table map events stored in the map).
- */
- if (print_event_info->m_table_map_ignored.count() > 0)
- print_event_info->m_table_map_ignored.clear_tables();
-
- /*
- If there is a kept Annotate event and all corresponding
- rbr-events were filtered away, the Annotate event was not
- freed and it is just the time to do it.
- */
- free_annotate_event();
-
- /*
- One needs to take into account an event that gets
- filtered but was last event in the statement. If this is
- the case, previous rows events that were written into
- IO_CACHEs still need to be copied from cache to
- result_file (as it would happen in ev->print(...) if
- event was not skipped).
- */
- if (skip_event)
- {
- if ((copy_event_cache_to_file_and_reinit(&print_event_info->head_cache, result_file) ||
- copy_event_cache_to_file_and_reinit(&print_event_info->body_cache, result_file)))
- goto err;
- }
- }
-
- /* skip the event check */
- if (skip_event)
- goto end;
- }
- /*
- These events must be printed in base64 format, if printed.
- base64 format requires a FD event to be safe, so if no FD
- event has been printed, we give an error. Except if user
- passed --short-form, because --short-form disables printing
- row events.
- */
- if (!print_event_info->printed_fd_event && !short_form &&
- opt_base64_output_mode != BASE64_OUTPUT_DECODE_ROWS)
- {
- const char* type_str= ev->get_type_str();
- if (opt_base64_output_mode == BASE64_OUTPUT_NEVER)
- error("--base64-output=never specified, but binlog contains a "
- "%s event which must be printed in base64.",
- type_str);
- else
- error("malformed binlog: it does not contain any "
- "Format_description_log_event. I now found a %s event, which "
- "is not safe to process without a "
- "Format_description_log_event.",
- type_str);
+ Old_rows_log_event *e= (Old_rows_log_event*) ev;
+ if (print_row_event(print_event_info, ev, e->get_table_id(),
+ e->get_flags(Old_rows_log_event::STMT_END_F)))
goto err;
- }
- /* FALL THROUGH */
+ break;
}
default:
print_skip_replication_statement(print_event_info, ev);
@@ -1516,13 +1550,14 @@ the mysql command line client.\n\n");
static my_time_t convert_str_to_timestamp(const char* str)
{
- int was_cut;
+ MYSQL_TIME_STATUS status;
MYSQL_TIME l_time;
long dummy_my_timezone;
uint dummy_in_dst_time_gap;
+
/* We require a total specification (date AND time) */
- if (str_to_datetime(str, (uint) strlen(str), &l_time, 0, &was_cut) !=
- MYSQL_TIMESTAMP_DATETIME || was_cut)
+ if (str_to_datetime(str, (uint) strlen(str), &l_time, 0, &status) ||
+ l_time.time_type != MYSQL_TIMESTAMP_DATETIME || status.warnings)
{
error("Incorrect date and time argument: %s", str);
exit(1);
@@ -2444,6 +2479,8 @@ 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");
@@ -2494,6 +2531,8 @@ int main(int argc, char** argv)
"/*!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)
@@ -2533,3 +2572,4 @@ void *sql_alloc(size_t size)
#include "sql_string.cc"
#include "sql_list.cc"
#include "rpl_filter.cc"
+#include "compat56.cc"
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c
index f429837c1dd..e614d628630 100644
--- a/client/mysqlcheck.c
+++ b/client/mysqlcheck.c
@@ -18,7 +18,7 @@
/* By Jani Tolonen, 2001-04-20, MySQL Development Team */
-#define CHECK_VERSION "2.7.0"
+#define CHECK_VERSION "2.7.1"
#include "client_priv.h"
#include <m_ctype.h>
@@ -32,6 +32,10 @@
#define EX_USAGE 1
#define EX_MYSQLERR 2
+/* ALTER instead of repair. */
+#define MAX_ALTER_STR_SIZE 128 * 1024
+#define KEY_PARTITIONING_CHANGED_STR "KEY () partitioning changed"
+
static MYSQL mysql_connection, *sock = 0;
static my_bool opt_alldbs = 0, opt_check_only_changed = 0, opt_extended = 0,
opt_compress = 0, opt_databases = 0, opt_fast = 0,
@@ -47,7 +51,7 @@ static char *opt_password = 0, *current_user = 0,
*default_charset= 0, *current_host= 0;
static char *opt_plugin_dir= 0, *opt_default_auth= 0;
static int first_error = 0;
-DYNAMIC_ARRAY tables4repair, tables4rebuild;
+DYNAMIC_ARRAY tables4repair, tables4rebuild, alter_table_cmds;
static char *shared_memory_base_name=0;
static uint opt_protocol=0;
@@ -620,6 +624,17 @@ static int process_all_tables_in_db(char *database)
} /* process_all_tables_in_db */
+static int run_query(const char *query)
+{
+ if (mysql_query(sock, query))
+ {
+ fprintf(stderr, "Failed to %s\n", query);
+ fprintf(stderr, "Error: %s\n", mysql_error(sock));
+ return 1;
+ }
+ return 0;
+}
+
static int fix_table_storage_name(const char *name)
{
@@ -630,12 +645,7 @@ static int fix_table_storage_name(const char *name)
if (strncmp(name, "#mysql50#", 9))
DBUG_RETURN(1);
sprintf(qbuf, "RENAME TABLE `%s` TO `%s`", name, name + 9);
- if (mysql_query(sock, qbuf))
- {
- fprintf(stderr, "Failed to %s\n", qbuf);
- fprintf(stderr, "Error: %s\n", mysql_error(sock));
- rc= 1;
- }
+ rc= run_query(qbuf);
if (verbose)
printf("%-50s %s\n", name, rc ? "FAILED" : "OK");
DBUG_RETURN(rc);
@@ -650,12 +660,7 @@ static int fix_database_storage_name(const char *name)
if (strncmp(name, "#mysql50#", 9))
DBUG_RETURN(1);
sprintf(qbuf, "ALTER DATABASE `%s` UPGRADE DATA DIRECTORY NAME", name);
- if (mysql_query(sock, qbuf))
- {
- fprintf(stderr, "Failed to %s\n", qbuf);
- fprintf(stderr, "Error: %s\n", mysql_error(sock));
- rc= 1;
- }
+ rc= run_query(qbuf);
if (verbose)
printf("%-50s %s\n", name, rc ? "FAILED" : "OK");
DBUG_RETURN(rc);
@@ -726,15 +731,7 @@ static int use_db(char *database)
static int disable_binlog()
{
const char *stmt= "SET SQL_LOG_BIN=0";
- DBUG_ENTER("disable_binlog");
-
- if (mysql_query(sock, stmt))
- {
- fprintf(stderr, "Failed to %s\n", stmt);
- fprintf(stderr, "Error: %s\n", mysql_error(sock));
- DBUG_RETURN(1);
- }
- DBUG_RETURN(0);
+ return run_query(stmt);
}
static int handle_request_for_tables(char *tables, uint length)
@@ -821,6 +818,7 @@ static void print_result()
MYSQL_RES *res;
MYSQL_ROW row;
char prev[(NAME_LEN+9)*2+2];
+ char prev_alter[MAX_ALTER_STR_SIZE];
uint i;
my_bool found_error=0, table_rebuild=0;
DBUG_ENTER("print_result");
@@ -828,6 +826,7 @@ static void print_result()
res = mysql_use_result(sock);
prev[0] = '\0';
+ prev_alter[0]= 0;
for (i = 0; (row = mysql_fetch_row(res)); i++)
{
int changed = strcmp(prev, row[0]);
@@ -844,12 +843,18 @@ static void print_result()
strcmp(row[3],"OK"))
{
if (table_rebuild)
- insert_dynamic(&tables4rebuild, (uchar*) prev);
+ {
+ if (prev_alter[0])
+ insert_dynamic(&alter_table_cmds, (uchar*) prev_alter);
+ else
+ insert_dynamic(&tables4rebuild, (uchar*) prev);
+ }
else
insert_dynamic(&tables4repair, (uchar*) prev);
}
found_error=0;
table_rebuild=0;
+ prev_alter[0]= 0;
if (opt_silent)
continue;
}
@@ -866,11 +871,30 @@ static void print_result()
printf("%-50s %s", row[0], "Needs upgrade");
else
printf("%s\n%-9s: %s", row[0], row[2], row[3]);
- if (strcmp(row[2],"note"))
+ if (opt_auto_repair && strcmp(row[2],"note"))
{
- found_error=1;
- if (opt_auto_repair && strstr(row[3], "ALTER TABLE") != NULL)
+ const char *alter_txt= strstr(row[3], "ALTER TABLE");
+ found_error=1;
+ if (alter_txt)
+ {
table_rebuild=1;
+ if (!strncmp(row[3], KEY_PARTITIONING_CHANGED_STR,
+ strlen(KEY_PARTITIONING_CHANGED_STR)) &&
+ strstr(alter_txt, "PARTITION BY"))
+ {
+ if (strlen(alter_txt) >= MAX_ALTER_STR_SIZE)
+ {
+ printf("Error: Alter command too long (>= %d),"
+ " please do \"%s\" or dump/reload to fix it!\n",
+ MAX_ALTER_STR_SIZE,
+ alter_txt);
+ table_rebuild= 0;
+ prev_alter[0]= 0;
+ }
+ else
+ strcpy(prev_alter, alter_txt);
+ }
+ }
}
}
else
@@ -882,7 +906,12 @@ static void print_result()
if (found_error && opt_auto_repair && what_to_do != DO_REPAIR)
{
if (table_rebuild)
- insert_dynamic(&tables4rebuild, (uchar*) prev);
+ {
+ if (prev_alter[0])
+ insert_dynamic(&alter_table_cmds, (uchar*) prev_alter);
+ else
+ insert_dynamic(&tables4rebuild, (uchar*) prev);
+ }
else
insert_dynamic(&tables4repair, (uchar*) prev);
}
@@ -1001,7 +1030,9 @@ int main(int argc, char **argv)
(my_init_dynamic_array(&tables4repair, sizeof(char)*(NAME_LEN*2+2),16,
64, MYF(0)) ||
my_init_dynamic_array(&tables4rebuild, sizeof(char)*(NAME_LEN*2+2),16,
- 64, MYF(0))))
+ 64, MYF(0)) ||
+ my_init_dynamic_array(&alter_table_cmds, MAX_ALTER_STR_SIZE, 0,
+ 1, MYF(0))))
goto end;
if (opt_alldbs)
@@ -1026,6 +1057,8 @@ int main(int argc, char **argv)
}
for (i = 0; i < tables4rebuild.elements ; i++)
rebuild_table((char*) dynamic_array_ptr(&tables4rebuild, i));
+ for (i = 0; i < alter_table_cmds.elements ; i++)
+ run_query((char*) dynamic_array_ptr(&alter_table_cmds, i));
}
ret= test(first_error);
diff --git a/client/mysqldump.c b/client/mysqldump.c
index 1cf66fe3dd1..ef3b0ce1ca0 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2012, Oracle and/or its affiliates.
+ Copyright (c) 2000, 2013, Oracle and/or its affiliates.
Copyright (c) 2010, 2013, Monty Program Ab.
This program is free software; you can redistribute it and/or modify
@@ -13,7 +13,7 @@
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
*/
/* mysqldump.c - Dump a tables contents and format to an ASCII file
@@ -2300,7 +2300,6 @@ static uint dump_routines_for_db(char *db)
const char *routine_type[]= {"FUNCTION", "PROCEDURE"};
char db_name_buff[NAME_LEN*2+3], name_buff[NAME_LEN*2+3];
char *routine_name;
- char *query_str;
int i;
FILE *sql_file= md_result_file;
MYSQL_RES *routine_res, *routine_list_res;
@@ -2394,17 +2393,6 @@ static uint dump_routines_for_db(char *db)
fprintf(sql_file, "/*!50003 DROP %s IF EXISTS %s */;\n",
routine_type[i], routine_name);
- query_str= cover_definer_clause(row[2], strlen(row[2]),
- C_STRING_WITH_LEN("50020"),
- C_STRING_WITH_LEN("50003"),
- C_STRING_WITH_LEN(" FUNCTION"));
-
- if (!query_str)
- query_str= cover_definer_clause(row[2], strlen(row[2]),
- C_STRING_WITH_LEN("50020"),
- C_STRING_WITH_LEN("50003"),
- C_STRING_WITH_LEN(" PROCEDURE"));
-
if (mysql_num_fields(routine_res) >= 6)
{
if (switch_db_collation(sql_file, db_name_buff, ";",
@@ -2442,9 +2430,9 @@ static uint dump_routines_for_db(char *db)
fprintf(sql_file,
"DELIMITER ;;\n"
- "/*!50003 %s */;;\n"
+ "%s ;;\n"
"DELIMITER ;\n",
- (const char *) (query_str != NULL ? query_str : row[2]));
+ (const char *) row[2]);
restore_sql_mode(sql_file, ";");
@@ -2459,7 +2447,6 @@ static uint dump_routines_for_db(char *db)
}
}
- my_free(query_str);
}
} /* end of routine printing */
mysql_free_result(routine_res);
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index 9e4b9da54af..87d6c80917a 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -1,5 +1,5 @@
-/* Copyright (c) 2000, 2012, Oracle and/or its affiliates.
- Copyright (c) 2009, 2012, Monty Program Ab.
+/* Copyright (c) 2000, 2013, Oracle and/or its affiliates.
+ Copyright (c) 2009, 2013, Monty Program Ab.
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
@@ -63,8 +63,9 @@
#define SIGNAL_FMT "signal %d"
#endif
+#include <my_context.h>
static my_bool non_blocking_api_enabled= 0;
-#if !defined(EMBEDDED_LIBRARY)
+#if !defined(EMBEDDED_LIBRARY) && !defined(MY_CONTEXT_DISABLE)
#define WRAP_NONBLOCK_ENABLED non_blocking_api_enabled
#include "../tests/nonblock-wrappers.h"
#endif
@@ -3590,7 +3591,7 @@ void do_remove_file(struct st_command *command)
' ');
DBUG_PRINT("info", ("removing file: %s", ds_filename.str));
- error= my_delete_allow_opened(ds_filename.str, MYF(disable_warnings ? 0 : MY_WME)) != 0;
+ error= my_delete(ds_filename.str, MYF(disable_warnings ? 0 : MY_WME)) != 0;
handle_command_error(command, error, my_errno);
dynstr_free(&ds_filename);
DBUG_VOID_RETURN;
@@ -3633,7 +3634,6 @@ void do_remove_files_wildcard(struct st_command *command)
fn_format(dirname, ds_directory.str, "", "", MY_UNPACK_FILENAME);
DBUG_PRINT("info", ("listing directory: %s", dirname));
- /* Note that my_dir sorts the list if not given any flags */
if (!(dir_info= my_dir(dirname, MYF(MY_DONT_SORT | MY_WANT_STAT | MY_WME))))
{
error= 1;
@@ -3648,7 +3648,7 @@ void do_remove_files_wildcard(struct st_command *command)
/* Set default wild chars for wild_compare, is changed in embedded mode */
set_wild_chars(1);
- for (i= 0; i < (uint) dir_info->number_off_files; i++)
+ for (i= 0; i < (uint) dir_info->number_of_files; i++)
{
file= dir_info->dir_entry + i;
/* Remove only regular files, i.e. no directories etc. */
@@ -3911,17 +3911,12 @@ static int get_list_files(DYNAMIC_STRING *ds, const DYNAMIC_STRING *ds_dirname,
DBUG_ENTER("get_list_files");
DBUG_PRINT("info", ("listing directory: %s", ds_dirname->str));
- /* Note that my_dir sorts the list if not given any flags */
- if (!(dir_info= my_dir(ds_dirname->str, MYF(0))))
+ if (!(dir_info= my_dir(ds_dirname->str, MYF(MY_WANT_SORT))))
DBUG_RETURN(1);
set_wild_chars(1);
- for (i= 0; i < (uint) dir_info->number_off_files; i++)
+ for (i= 0; i < (uint) dir_info->number_of_files; i++)
{
file= dir_info->dir_entry + i;
- if (file->name[0] == '.' &&
- (file->name[1] == '\0' ||
- (file->name[1] == '.' && file->name[2] == '\0')))
- continue; /* . or .. */
if (ds_wild && ds_wild->length &&
wild_compare(file->name, ds_wild->str, 0))
continue;
@@ -5956,8 +5951,10 @@ void do_connect(struct st_command *command)
if (opt_connect_timeout)
mysql_options(con_slot->mysql, MYSQL_OPT_CONNECT_TIMEOUT,
(void *) &opt_connect_timeout);
-
- mysql_options(con_slot->mysql, MYSQL_OPT_NONBLOCK, 0);
+#ifndef MY_CONTEXT_DISABLE
+ if (mysql_options(con_slot->mysql, MYSQL_OPT_NONBLOCK, 0))
+ die("Failed to initialise non-blocking API");
+#endif
if (opt_compress || con_compress)
mysql_options(con_slot->mysql, MYSQL_OPT_COMPRESS, NullS);
mysql_options(con_slot->mysql, MYSQL_OPT_LOCAL_INFILE, 0);
@@ -6361,8 +6358,7 @@ void do_delimiter(struct st_command* command)
if (!(*p))
die("Can't set empty delimiter");
- strmake(delimiter, p, sizeof(delimiter) - 1);
- delimiter_length= strlen(delimiter);
+ delimiter_length= strmake_buf(delimiter, p) - delimiter;
DBUG_PRINT("exit", ("delimiter: %s", delimiter));
command->last_argument= p + delimiter_length;
diff --git a/client/readline.cc b/client/readline.cc
index 791a044e0e1..b6643b86356 100644
--- a/client/readline.cc
+++ b/client/readline.cc
@@ -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;
ulong out_length;
@@ -63,8 +63,17 @@ char *batch_readline(LINE_BUFFER *line_buff)
if (!(pos=intern_read_line(line_buff, &out_length)))
return 0;
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;
pos[out_length]=0;
return pos;
@@ -226,7 +235,7 @@ char *intern_read_line(LINE_BUFFER *buffer, ulong *out_length)
for (;;)
{
pos=buffer->end_of_line;
- while (*pos != '\n' && *pos)
+ while (*pos != '\n' && pos != buffer->end)
pos++;
if (pos == buffer->end)
{
diff --git a/client/sql_string.cc.dontuse b/client/sql_string.cc.dontuse
index 64219886dd0..9679197b207 100644
--- a/client/sql_string.cc.dontuse
+++ b/client/sql_string.cc.dontuse
@@ -1,5 +1,5 @@
/*
- Copyright (c) 2000, 2011, Oracle and/or its affiliates.
+ Copyright (c) 2000, 2013, Oracle and/or its affiliates.
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
@@ -691,7 +691,7 @@ String *copy_if_not_alloced(String *to,String *from,uint32 from_length)
{
if (from->Alloced_length >= from_length)
return from;
- if (from->alloced || !to || from == to)
+ if ((from->alloced && (from->Alloced_length != 0)) || !to || from == to)
{
(void) from->realloc(from_length);
return from;
diff --git a/client/sql_string.h.dontuse b/client/sql_string.h.dontuse
index 67155ebcee7..94f844dc689 100644
--- a/client/sql_string.h.dontuse
+++ b/client/sql_string.h.dontuse
@@ -1,7 +1,7 @@
#ifndef SQL_STRING_INCLUDED
#define SQL_STRING_INCLUDED
-/* Copyright (c) 2000, 2012, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (c) 2000, 2013, 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
@@ -226,6 +226,7 @@ public:
DBUG_ASSERT(!s.uses_buffer_owned_by(this));
free();
Ptr=s.Ptr ; str_length=s.str_length ; Alloced_length=s.Alloced_length;
+ str_charset=s.str_charset;
alloced=0;
}
return *this;