summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to 'client')
-rw-r--r--client/CMakeLists.txt4
-rw-r--r--client/Makefile.am7
-rw-r--r--client/client_priv.h6
-rw-r--r--client/get_password.c4
-rw-r--r--client/mysql.cc217
-rw-r--r--client/mysql_upgrade.c80
-rw-r--r--client/mysqladmin.cc144
-rw-r--r--client/mysqlbinlog.cc150
-rw-r--r--client/mysqlcheck.c66
-rw-r--r--client/mysqldump.c18
-rw-r--r--client/mysqlimport.c4
-rw-r--r--client/mysqlshow.c2
-rw-r--r--client/mysqlslap.c170
-rw-r--r--client/mysqltest.cc316
-rw-r--r--client/sql_string.h3
15 files changed, 858 insertions, 333 deletions
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt
index e39e8d7178a..52fd378689e 100644
--- a/client/CMakeLists.txt
+++ b/client/CMakeLists.txt
@@ -72,3 +72,7 @@ ENDIF(WIN32)
SET_TARGET_PROPERTIES (mysqlcheck mysqldump mysqlimport mysql_upgrade mysqlshow mysqlslap
PROPERTIES HAS_CXX TRUE)
+ADD_DEFINITIONS(-DHAVE_DLOPEN)
+
+INSTALL(TARGETS mysql mysqltest mysqlcheck mysqldump mysqlimport mysql_upgrade mysqlshow
+ mysqlbinlog mysqladmin mysqlslap echo DESTINATION bin COMPONENT runtime)
diff --git a/client/Makefile.am b/client/Makefile.am
index 393573a061e..96e763772dd 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -99,8 +99,8 @@ mysql_upgrade_SOURCES= mysql_upgrade.c \
# Fix for mit-threads
DEFS = -DMYSQL_CLIENT_NO_THREADS \
- -DDEFAULT_MYSQL_HOME="\"$(prefix)\"" \
- -DMYSQL_DATADIR="\"$(localstatedir)\""
+ -DDEFAULT_MYSQL_HOME='"$(prefix)"' \
+ -DMYSQL_DATADIR='"$(localstatedir)"'
sql_src=log_event.h sql_priv.h rpl_constants.h \
rpl_tblmap.h rpl_tblmap.cc \
@@ -108,7 +108,8 @@ sql_src=log_event.h sql_priv.h rpl_constants.h \
log_event_old.h log_event_old.cc \
rpl_record_old.h rpl_record_old.cc \
rpl_utility.h rpl_utility.cc \
- transaction.h sql_const.h
+ transaction.h sql_const.h \
+ sql_list.h rpl_filter.h sql_list.cc rpl_filter.cc
strings_src=decimal.c dtoa.c
link_sources:
diff --git a/client/client_priv.h b/client/client_priv.h
index e7911fc31f7..c543dd4efa2 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -84,7 +84,11 @@ enum options_client
OPT_DEBUG_INFO, OPT_DEBUG_CHECK, OPT_COLUMN_TYPES, OPT_ERROR_LOG_FILE,
OPT_WRITE_BINLOG, OPT_DUMP_DATE,
OPT_INIT_COMMAND,
- OPT_MAX_CLIENT_OPTION
+ OPT_ABORT_SOURCE_ON_ERROR,
+ OPT_REWRITE_DB,
+ OPT_PLUGIN_DIR,
+ OPT_DEFAULT_PLUGIN,
+ OPT_MAX_CLIENT_OPTION /* should be always the last */
};
/**
diff --git a/client/get_password.c b/client/get_password.c
index ea024f76fb6..c6653183f48 100644
--- a/client/get_password.c
+++ b/client/get_password.c
@@ -113,7 +113,7 @@ static void get_password(char *to,uint length,int fd, my_bool echo)
for (;;)
{
- char tmp;
+ uchar tmp;
if (my_read(fd,&tmp,1,MYF(0)) != 1)
break;
if (tmp == '\b' || (int) tmp == 127)
@@ -138,7 +138,7 @@ static void get_password(char *to,uint length,int fd, my_bool echo)
fputc('*',stderr);
fflush(stderr);
}
- *(pos++) = tmp;
+ *(pos++)= (char) tmp;
}
while (pos != to && isspace(pos[-1]) == ' ')
pos--; /* Allow dummy space at end */
diff --git a/client/mysql.cc b/client/mysql.cc
index b61a751198a..208b5b3288c 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -1,4 +1,6 @@
-/* Copyright 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+/* Copyright (C) 2000-2009 MySQL AB
+ Copyright 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ Copyright 2000-2010 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
@@ -14,7 +16,6 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#define COPYRIGHT_NOTICE "\
-Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.\n\
This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\
and you are welcome to modify and redistribute it under the GPL v2 license\n"
@@ -48,7 +49,7 @@ and you are welcome to modify and redistribute it under the GPL v2 license\n"
#include <locale.h>
#endif
-const char *VER= "14.14";
+const char *VER= "14.16";
/* Don't try to make a nice table if the data is too big */
#define MAX_COLUMN_LENGTH 1024
@@ -86,8 +87,9 @@ extern "C" {
#include <term.h>
#endif
#endif
-#endif
+#endif /* defined(HAVE_CURSES_H) && defined(HAVE_TERM_H) */
+#undef bcmp // Fix problem with new readline
#if defined(__WIN__)
#include <conio.h>
#else
@@ -95,7 +97,6 @@ extern "C" {
#define HAVE_READLINE
#define USE_POPEN
#endif
- //int vidattr(long unsigned int attrs); // Was missing in sun curses
}
#if !defined(HAVE_VIDATTR)
@@ -143,16 +144,18 @@ static my_bool ignore_errors=0,wait_flag=0,quick=0,
opt_secure_auth= 0,
default_pager_set= 0, opt_sigint_ignore= 0,
auto_vertical_output= 0,
- show_warnings= 0, executing_query= 0, interrupted_query= 0,
+ show_warnings= 0, executing_query= 0,
ignore_spaces= 0;
-static my_bool debug_info_flag, debug_check_flag;
+static my_bool debug_info_flag, debug_check_flag, batch_abort_on_error;
static my_bool column_types_flag;
static my_bool preserve_comments= 0;
+static my_bool in_com_source, aborted= 0;
static ulong opt_max_allowed_packet, opt_net_buffer_length;
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 int interrupted_query= 0;
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,
@@ -166,6 +169,7 @@ static int wait_time = 5;
static STATUS status;
static ulong select_limit,max_join_size,opt_connect_timeout=0;
static char mysql_charsets_dir[FN_REFLEN+1];
+static char *opt_plugin_dir= 0, *opt_default_auth;
static const char *xmlmeta[] = {
"&", "&amp;",
"<", "&lt;",
@@ -1022,7 +1026,7 @@ static const char *load_default_groups[]= { "mysql","client",0 };
static int embedded_server_arg_count= 0;
static char *embedded_server_args[MAX_SERVER_ARGS];
static const char *embedded_server_groups[]=
-{ "server", "embedded", "mysql_SERVER", 0 };
+{ "server", "embedded", "mysql_SERVER", "mariadb_SERVER", 0 };
#ifdef HAVE_READLINE
/*
@@ -1078,9 +1082,10 @@ int main(int argc,char *argv[])
delimiter_str= delimiter;
default_prompt = my_strdup(getenv("MYSQL_PS1") ?
getenv("MYSQL_PS1") :
- "mysql> ",MYF(MY_WME));
+ "\\N [\\d]> ",MYF(MY_WME));
current_prompt = my_strdup(default_prompt,MYF(MY_WME));
prompt_counter=0;
+ aborted= 0;
outfile[0]=0; // no (default) outfile
strmov(pager, "stdout"); // the default, if --pager wasn't given
@@ -1169,10 +1174,11 @@ int main(int argc,char *argv[])
window_resize(0);
#endif
- put_info("Welcome to the MySQL monitor. Commands end with ; or \\g.",
+ put_info("Welcome to the MariaDB monitor. Commands end with ; or \\g.",
INFO_INFO);
sprintf((char*) glob_buffer.ptr(),
- "Your MySQL connection id is %lu\nServer version: %s\n",
+ "Your %s connection id is %lu\nServer version: %s\n",
+ mysql_get_server_name(&mysql),
mysql_thread_id(&mysql), server_version_string(&mysql));
put_info((char*) glob_buffer.ptr(),INFO_INFO);
@@ -1285,15 +1291,16 @@ sig_handler mysql_end(int sig)
/*
This function handles sigint calls
If query is in process, kill query
+ If 'source' is executed, abort source command
no query in process, terminate like previous behavior
*/
+
sig_handler handle_sigint(int sig)
{
char kill_buffer[40];
MYSQL *kill_mysql= NULL;
/* terminate if no query being executed, or we already tried interrupting */
- /* terminate if no query being executed, or we already tried interrupting */
if (!executing_query || (interrupted_query == 2))
{
tee_fprintf(stdout, "Ctrl-C -- exit!\n");
@@ -1308,6 +1315,7 @@ sig_handler handle_sigint(int sig)
goto err;
}
+ /* First time try to kill the query, second time the connection */
interrupted_query++;
/* mysqld < 5 does not understand KILL QUERY, skip to KILL CONNECTION */
@@ -1318,11 +1326,15 @@ sig_handler handle_sigint(int sig)
sprintf(kill_buffer, "KILL %s%lu",
(interrupted_query == 1) ? "QUERY " : "",
mysql_thread_id(&mysql));
- tee_fprintf(stdout, "Ctrl-C -- sending \"%s\" to server ...\n", kill_buffer);
+ if (verbose)
+ tee_fprintf(stdout, "Ctrl-C -- sending \"%s\" to server ...\n",
+ kill_buffer);
mysql_real_query(kill_mysql, kill_buffer, (uint) strlen(kill_buffer));
mysql_close(kill_mysql);
- tee_fprintf(stdout, "Ctrl-C -- query aborted.\n");
-
+ tee_fprintf(stdout, "Ctrl-C -- query killed. Continuing normally.\n");
+ interrupted_query= 0;
+ if (in_com_source)
+ aborted= 1; // Abort source command
return;
err:
@@ -1334,7 +1346,6 @@ err:
handler called mysql_end().
*/
mysql_thread_end();
- return;
#else
mysql_end(sig);
#endif
@@ -1357,6 +1368,10 @@ static struct my_option my_long_options[] =
0, 0, 0, 0, 0},
{"help", 'I', "Synonym for -?", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
0, 0, 0, 0, 0},
+ {"abort-source-on-error", OPT_ABORT_SOURCE_ON_ERROR,
+ "Abort 'source filename' operations in case of errors",
+ &batch_abort_on_error, &batch_abort_on_error, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"auto-rehash", OPT_AUTO_REHASH,
"Enable automatic rehashing. One doesn't need to use 'rehash' to get table "
"and field completion, but startup and reconnecting may take a longer time. "
@@ -1413,7 +1428,7 @@ static struct my_option my_long_options[] =
{"vertical", 'E', "Print the output of a query (rows) vertically.",
&vertical, &vertical, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
0},
- {"force", 'f', "Continue even if we get an SQL error.",
+ {"force", 'f', "Continue even if we get an SQL error. Sets abort-source-on-error to 0",
&ignore_errors, &ignore_errors, 0, GET_BOOL, NO_ARG, 0, 0,
0, 0, 0, 0},
{"named-commands", 'G',
@@ -1564,6 +1579,13 @@ static struct my_option my_long_options[] =
{"show-warnings", OPT_SHOW_WARNINGS, "Show warnings after every statement.",
&show_warnings, &show_warnings, 0, GET_BOOL, NO_ARG,
0, 0, 0, 0, 0, 0},
+ {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
+ (uchar**) &opt_plugin_dir, (uchar**) &opt_plugin_dir, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"default_auth", OPT_PLUGIN_DIR,
+ "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},
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -1747,6 +1769,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
#endif
break;
#include <sslopt-case.h>
+ case 'f':
+ batch_abort_on_error= 0;
+ break;
case 'V':
usage(1);
exit(0);
@@ -1830,7 +1855,7 @@ static int read_and_execute(bool interactive)
String buffer;
#endif
- char *line;
+ char *line= 0;
char in_string=0;
ulong line_number=0;
bool ml_comment= 0;
@@ -1838,7 +1863,7 @@ static int read_and_execute(bool interactive)
bool truncated= 0;
status.exit_status=1;
- for (;;)
+ while (!aborted)
{
if (!interactive)
{
@@ -1996,12 +2021,12 @@ static COMMANDS *find_command(char *name,char cmd_char)
for (uint i= 0; commands[i].name; i++)
{
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)))
+ (((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]);
@@ -2159,16 +2184,21 @@ static bool add_line(String &buffer,char *line,char *in_string,
}
buffer.length(0);
}
- else if (!*ml_comment && (!*in_string && (inchar == '#' ||
- (inchar == '-' && pos[1] == '-' &&
- /*
- The third byte is either whitespace or is the
- end of the line -- which would occur only
- because of the user sending newline -- which is
- itself whitespace and should also match.
- */
- (my_isspace(charset_info,pos[2]) ||
- !pos[2])))))
+ else if (!*ml_comment &&
+ (!*in_string &&
+ (inchar == '#' ||
+ (inchar == '-' && pos[1] == '-' &&
+ /*
+ The third byte is either whitespace or is the end of
+ the line -- which would occur only because of the
+ user sending newline -- which is itself whitespace
+ and should also match.
+ We also ignore lines starting with '--', even if there
+ isn't a whitespace after. (This makes it easier to run
+ mysql-test-run cases through the client)
+ */
+ ((my_isspace(charset_info,pos[2]) || !pos[2]) ||
+ (buffer.is_empty() && out == line))))))
{
// Flush previously accepted characters
if (out != line)
@@ -2855,13 +2885,8 @@ com_help(String *buffer __attribute__((unused)),
return com_server_help(buffer,line,help_arg);
}
- put_info("\nFor information about MySQL products and services, visit:\n"
- " http://www.mysql.com/\n"
- "For developer information, including the MySQL Reference Manual, "
- "visit:\n"
- " http://dev.mysql.com/\n"
- "To buy MySQL Enterprise support, training, or other products, visit:\n"
- " https://shop.mysql.com/\n", INFO_INFO);
+ put_info("\nGeneral information about MariaDB can be found at\n"
+ "http://askmonty.org/wiki/index.php/Manual:Contents\n", INFO_INFO);
put_info("List of all MySQL commands:", INFO_INFO);
if (!named_cmds)
put_info("Note that all text commands must be first on line and end with ';'",INFO_INFO);
@@ -3858,8 +3883,9 @@ static int
com_edit(String *buffer,char *line __attribute__((unused)))
{
char filename[FN_REFLEN],buff[160];
- int fd,tmp;
+ int fd,tmp,error;
const char *editor;
+ MY_STAT stat_arg;
if ((fd=create_temp_file(filename,NullS,"sql", O_CREAT | O_WRONLY,
MYF(MY_WME))) < 0)
@@ -3875,10 +3901,14 @@ com_edit(String *buffer,char *line __attribute__((unused)))
!(editor = (char *)getenv("VISUAL")))
editor = "vi";
strxmov(buff,editor," ",filename,NullS);
- if(system(buff) == -1)
+ if ((error= system(buff)))
+ {
+ char errmsg[100];
+ sprintf(errmsg, "Command '%.40s' failed", buff);
+ put_info(errmsg, INFO_ERROR, 0, NullS);
goto err;
+ }
- MY_STAT stat_arg;
if (!my_stat(filename,&stat_arg,MYF(MY_WME)))
goto err;
if ((fd = my_open(filename,O_RDONLY, MYF(MY_WME))) < 0)
@@ -3961,7 +3991,7 @@ static int
com_connect(String *buffer, char *line)
{
char *tmp, buff[256];
- bool save_rehash= opt_rehash;
+ my_bool save_rehash= opt_rehash;
int error;
bzero(buff, sizeof(buff));
@@ -4018,6 +4048,7 @@ static int com_source(String *buffer, char *line)
int error;
STATUS old_status;
FILE *sql_file;
+ my_bool save_ignore_errors;
/* Skip space from file name */
while (my_isspace(charset_info,*line))
@@ -4049,16 +4080,27 @@ static int com_source(String *buffer, char *line)
/* Save old status */
old_status=status;
+ save_ignore_errors= ignore_errors;
bfill((char*) &status,sizeof(status),(char) 0);
status.batch=old_status.batch; // Run in batch mode
status.line_buff=line_buff;
status.file_name=source_name;
glob_buffer.length(0); // Empty command buffer
+ ignore_errors= !batch_abort_on_error;
+ in_com_source= 1;
error= read_and_execute(false);
+ ignore_errors= save_ignore_errors;
status=old_status; // Continue as before
+ in_com_source= aborted= 0;
my_fclose(sql_file,MYF(0));
batch_readline_end(line_buff);
+ /*
+ If we got an error during source operation, don't abort the client
+ if ignore_errors is set
+ */
+ if (error && ignore_errors)
+ error= -1; // Ignore error
return error;
}
@@ -4247,6 +4289,57 @@ char *get_arg(char *line, my_bool get_next_arg)
}
+/**
+ An example of mysql_authentication_dialog_ask callback.
+
+ The C function with the name "mysql_authentication_dialog_ask", if exists,
+ will be used by the "dialog" client authentication plugin when user
+ input is needed. This function should be of mysql_authentication_dialog_ask_t
+ type. If the function does not exists, a built-in implementation will be
+ used.
+
+ @param mysql mysql
+ @param type type of the input
+ 1 - normal string input
+ 2 - password string
+ @param prompt prompt
+ @param buf a buffer to store the use input
+ @param buf_len the length of the buffer
+
+ @retval a pointer to the user input string.
+ It may be equal to 'buf' or to 'mysql->password'.
+ In all other cases it is assumed to be an allocated
+ string, and the "dialog" plugin will free() it.
+*/
+
+extern "C" char *mysql_authentication_dialog_ask(MYSQL *mysql, int type,
+ const char *prompt,
+ char *buf, int buf_len)
+{
+ char *s=buf;
+
+ fputs("[mariadb] ", stdout);
+ fputs(prompt, stdout);
+ fputs(" ", stdout);
+
+ if (type == 2) /* password */
+ {
+ s= get_tty_password("");
+ strnmov(buf, s, buf_len);
+ buf[buf_len-1]= 0;
+ my_free(s, MYF(0));
+ }
+ else
+ {
+ if (!fgets(buf, buf_len-1, stdin))
+ buf[0]= 0;
+ else if (buf[0] && (s= strend(buf))[-1] == '\n')
+ s[-1]= 0;
+ }
+
+ return buf;
+}
+
static int
sql_real_connect(char *host,char *database,char *user,char *password,
uint silent)
@@ -4294,7 +4387,13 @@ sql_real_connect(char *host,char *database,char *user,char *password,
}
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
-
+
+ if (opt_plugin_dir && *opt_plugin_dir)
+ mysql_options(&mysql, MYSQL_PLUGIN_DIR, opt_plugin_dir);
+
+ if (opt_default_auth && *opt_default_auth)
+ mysql_options(&mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
+
if (!mysql_real_connect(&mysql, host, user, password,
database, opt_mysql_port, opt_mysql_unix_port,
connect_flag | CLIENT_MULTI_STATEMENTS))
@@ -4411,6 +4510,7 @@ com_status(String *buffer __attribute__((unused)),
tee_fprintf(stdout, "Using outfile:\t\t'%s'\n", opt_outfile ? outfile : "");
#endif
tee_fprintf(stdout, "Using delimiter:\t%s\n", delimiter);
+ tee_fprintf(stdout, "Server:\t\t\t%s\n", mysql_get_server_name(&mysql));
tee_fprintf(stdout, "Server version:\t\t%s\n", server_version_string(&mysql));
tee_fprintf(stdout, "Protocol version:\t%d\n", mysql_get_proto_info(&mysql));
tee_fprintf(stdout, "Connection:\t\t%s\n", mysql_get_host_info(&mysql));
@@ -4579,12 +4679,19 @@ put_info(const char *str,INFO_TYPE info_type, uint error, const char *sqlstate)
if (error)
{
if (sqlstate)
- (void) tee_fprintf(file, "ERROR %d (%s): ", error, sqlstate);
+ (void) tee_fprintf(file, "ERROR %d (%s)", error, sqlstate);
else
- (void) tee_fprintf(file, "ERROR %d: ", error);
+ (void) tee_fprintf(file, "ERROR %d", error);
}
else
- tee_puts("ERROR: ", file);
+ tee_fputs("ERROR", file);
+ if (status.query_start_line && line_numbers)
+ {
+ (void) fprintf(file," at line %lu",status.query_start_line);
+ if (status.file_name)
+ (void) fprintf(file," in file: '%s'", status.file_name);
+ }
+ tee_fputs(": ", file);
}
else
vidattr(A_BOLD);
@@ -4593,7 +4700,7 @@ put_info(const char *str,INFO_TYPE info_type, uint error, const char *sqlstate)
}
if (unbuffered)
fflush(file);
- return info_type == INFO_ERROR ? -1 : 0;
+ return info_type == INFO_ERROR ? (ignore_errors ? -1 : 1): 0;
}
@@ -4730,7 +4837,7 @@ static void mysql_end_timer(ulong start_time,char *buff)
strmov(strend(buff),")");
}
-static const char* construct_prompt()
+static const char *construct_prompt()
{
processed_prompt.free(); // Erase the old prompt
time_t lclock = time(NULL); // Get the date struct
@@ -4759,6 +4866,12 @@ static const char* construct_prompt()
case 'd':
processed_prompt.append(current_db ? current_db : "(none)");
break;
+ case 'N':
+ if (connected)
+ processed_prompt.append(mysql_get_server_name(&mysql));
+ else
+ processed_prompt.append("unknown");
+ break;
case 'h':
{
const char *prompt;
diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c
index 882350f813b..cd1c9bb27d3 100644
--- a/client/mysql_upgrade.c
+++ b/client/mysql_upgrade.c
@@ -1,4 +1,5 @@
/* Copyright (C) 2000 MySQL AB
+ Copyright (C) 2010 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
@@ -17,7 +18,7 @@
#include <sslopt-vars.h>
#include "../scripts/mysql_fix_privilege_tables_sql.c"
-#define VER "1.1"
+#define VER "1.2"
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
@@ -34,9 +35,10 @@
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,
+static my_bool opt_force, debug_info_flag, debug_check_flag,
opt_systables_only;
-static uint my_end_arg= 0;
+static my_bool opt_not_used; /* For compatiblity */
+static uint my_end_arg= 0, opt_verbose;
static char *opt_user= (char*)"root";
static DYNAMIC_STRING ds_args;
@@ -61,12 +63,14 @@ static struct my_option my_long_options[]=
{
{"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0},
- {"basedir", 'b', "Not used by mysql_upgrade. Only for backward compatibility.",
+ {"basedir", 'b',
+ "Not used by mysql_upgrade. Only for backward compatibility.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"character-sets-dir", OPT_CHARSETS_DIR,
- "Directory for character set files.", 0,
- 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"compress", OPT_COMPRESS, "Use compression in server/client protocol.",
+ "Not used by mysql_upgrade. Only for backward compatibility.",
+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ {"compress", OPT_COMPRESS,
+ "Not used by mysql_upgrade. Only for backward compatibility.",
&not_used, &not_used, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"datadir", 'd',
"Not used by mysql_upgrade. Only for backward compatibility.",
@@ -79,18 +83,17 @@ static struct my_option my_long_options[]=
&default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
#endif
{"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
- &debug_check_flag, &debug_check_flag, 0,
- GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ &debug_check_flag, &debug_check_flag,
+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"debug-info", 'T', "Print some debug info at exit.", &debug_info_flag,
&debug_info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"default-character-set", OPT_DEFAULT_CHARSET,
- "Set the default character set.", 0,
- 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ "Not used by mysql_upgrade. Only for backward compatibility.",
+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"force", 'f', "Force execution of mysqlcheck even if mysql_upgrade "
"has already been executed for the current version of MySQL.",
- &opt_force, &opt_force, 0,
- GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"host",'h', "Connect to host.", 0,
+ &opt_force, &opt_force, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"host", 'h', "Connect to host.", 0,
0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"password", 'p',
"Password to use when connecting to server. If password is not given,"
@@ -115,6 +118,8 @@ static struct my_option my_long_options[]=
"Base name of shared memory.", 0,
0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#endif
+ {"silent", 's', "Print less information", &opt_silent,
+ &opt_silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"socket", 'S', "The socket file to use for connection.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#include <sslopt-longopts.h>
@@ -127,8 +132,7 @@ static struct my_option my_long_options[]=
{"user", 'u', "User for login if not current user.", &opt_user,
&opt_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"verbose", 'v', "Display more output about the process.",
- &opt_verbose, &opt_verbose, 0,
- GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
+ &opt_not_used, &opt_not_used, 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.",
@@ -174,7 +178,7 @@ static void verbose(const char *fmt, ...)
{
va_list args;
- if (!opt_verbose)
+ if (opt_silent)
return;
/* Print the verbose message */
@@ -270,6 +274,18 @@ get_one_option(int optid, const struct my_option *opt,
/* FALLTHROUGH */
case 'v': /* --verbose */
+ opt_verbose++;
+ if (argument == disabled_my_option)
+ {
+ opt_verbose= 0;
+ opt_silent= 1;
+ }
+ add_option= 0;
+ break;
+ case 's':
+ opt_verbose= 0;
+ add_option= 0;
+ break;
case 'f': /* --force */
add_option= FALSE;
break;
@@ -430,7 +446,8 @@ static void find_tool(char *tool_executable_name, const char *tool_name,
len, self_name, FN_LIBCHAR, tool_name);
}
- verbose("Looking for '%s' as: %s", tool_name, tool_executable_name);
+ if (opt_verbose)
+ verbose("Looking for '%s' as: %s", tool_name, tool_executable_name);
/*
Make sure it can be executed
@@ -500,7 +517,7 @@ static int run_query(const char *query, DYNAMIC_STRING *ds_res,
"--database=mysql",
"--batch", /* Turns off pager etc. */
force ? "--force": "--skip-force",
- ds_res ? "--silent": "",
+ ds_res || opt_silent ? "--silent": "",
"<",
query_file_path,
"2>&1",
@@ -582,7 +599,6 @@ static int upgrade_already_done(void)
FILE *in;
char upgrade_info_file[FN_REFLEN]= {0};
char buf[sizeof(MYSQL_SERVER_VERSION)+1];
- char *res;
if (get_upgrade_info_file_name(upgrade_info_file))
return 0; /* Could not get filename => not sure */
@@ -590,19 +606,15 @@ static int upgrade_already_done(void)
if (!(in= my_fopen(upgrade_info_file, O_RDONLY, MYF(0))))
return 0; /* Could not open file => not sure */
- /*
- Read from file, don't care if it fails since it
- will be detected by the strncmp
- */
bzero(buf, sizeof(buf));
- res= fgets(buf, sizeof(buf), in);
+ if (!fgets(buf, sizeof(buf), in))
+ {
+ /* Ignore, will be detected by strncmp() below */
+ }
my_fclose(in, MYF(0));
- if (!res)
- return 0; /* Could not read from file => not sure */
-
- return (strncmp(res, MYSQL_SERVER_VERSION,
+ return (strncmp(buf, MYSQL_SERVER_VERSION,
sizeof(MYSQL_SERVER_VERSION)-1)==0);
}
@@ -658,6 +670,8 @@ static void create_mysql_upgrade_info_file(void)
static void print_conn_args(const char *tool_name)
{
+ if (opt_verbose < 2)
+ return;
if (conn_args.str[0])
verbose("Running '%s' with connection arguments: %s", tool_name,
conn_args.str);
@@ -673,6 +687,7 @@ static void print_conn_args(const char *tool_name)
static int run_mysqlcheck_upgrade(void)
{
+ verbose("Phase 2/3: Checking and upgrading tables");
print_conn_args("mysqlcheck");
return run_tool(mysqlcheck_path,
NULL, /* Send output from mysqlcheck directly to screen */
@@ -681,6 +696,8 @@ static int run_mysqlcheck_upgrade(void)
"--check-upgrade",
"--all-databases",
"--auto-repair",
+ !opt_silent || opt_verbose ? "--verbose": "",
+ opt_silent ? "--silent": "",
opt_write_binlog ? "--write-binlog" : "--skip-write-binlog",
NULL);
}
@@ -688,6 +705,7 @@ static int run_mysqlcheck_upgrade(void)
static int run_mysqlcheck_fixnames(void)
{
+ verbose("Phase 1/3: Fixing table and database names");
print_conn_args("mysqlcheck");
return run_tool(mysqlcheck_path,
NULL, /* Send output from mysqlcheck directly to screen */
@@ -696,6 +714,8 @@ static int run_mysqlcheck_fixnames(void)
"--all-databases",
"--fix-db-names",
"--fix-table-names",
+ opt_verbose ? "--verbose": "",
+ opt_silent ? "--silent": "",
opt_write_binlog ? "--write-binlog" : "--skip-write-binlog",
NULL);
}
@@ -765,7 +785,7 @@ static int run_sql_fix_privilege_tables(void)
if (init_dynamic_string(&ds_result, "", 512, 512))
die("Out of memory");
- verbose("Running 'mysql_fix_privilege_tables'...");
+ verbose("Phase 3/3: Running 'mysql_fix_privilege_tables'...");
run_query(mysql_fix_privilege_tables,
&ds_result, /* Collect result */
TRUE);
diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc
index 69381b749a1..f164a7d039f 100644
--- a/client/mysqladmin.cc
+++ b/client/mysqladmin.cc
@@ -24,7 +24,7 @@
#include <mysql.h>
#include <sql_common.h>
-#define ADMIN_VERSION "8.42"
+#define ADMIN_VERSION "9.0"
#define MAX_MYSQL_VAR 512
#define SHUTDOWN_DEF_TIMEOUT 3600 /* Wait for shutdown */
#define MAX_TRUNC_LENGTH 3
@@ -97,7 +97,10 @@ enum commands {
ADMIN_FLUSH_HOSTS, ADMIN_FLUSH_TABLES, ADMIN_PASSWORD,
ADMIN_PING, ADMIN_EXTENDED_STATUS, ADMIN_FLUSH_STATUS,
ADMIN_FLUSH_PRIVILEGES, ADMIN_START_SLAVE, ADMIN_STOP_SLAVE,
- ADMIN_FLUSH_THREADS, ADMIN_OLD_PASSWORD
+ ADMIN_FLUSH_THREADS, ADMIN_OLD_PASSWORD, ADMIN_FLUSH_SLOW_LOG,
+ ADMIN_FLUSH_TABLE_STATISTICS, ADMIN_FLUSH_INDEX_STATISTICS,
+ ADMIN_FLUSH_USER_STATISTICS, ADMIN_FLUSH_CLIENT_STATISTICS,
+ ADMIN_FLUSH_ALL_STATUS, ADMIN_FLUSH_ALL_STATISTICS
};
static const char *command_names[]= {
"create", "drop", "shutdown",
@@ -107,7 +110,10 @@ static const char *command_names[]= {
"flush-hosts", "flush-tables", "password",
"ping", "extended-status", "flush-status",
"flush-privileges", "start-slave", "stop-slave",
- "flush-threads","old-password",
+ "flush-threads", "old-password", "flush-slow-log",
+ "flush-table-statistics", "flush-index-statistics",
+ "flush-user-statistics", "flush-client-statistics",
+ "flush-all-status", "flush-all-statistics",
NullS
};
@@ -572,11 +578,12 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
If this behaviour is ever changed, Docs should be notified.
*/
- struct rand_struct rand_st;
+ struct my_rnd_struct rand_st;
for (; argc > 0 ; argv++,argc--)
{
- switch (find_type(argv[0],&command_typelib,2)) {
+ int command;
+ switch ((command= find_type(argv[0],&command_typelib,2))) {
case ADMIN_CREATE:
{
char buff[FN_REFLEN+20];
@@ -653,7 +660,11 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
if (mysql_refresh(mysql,
(uint) ~(REFRESH_GRANT | REFRESH_STATUS |
REFRESH_READ_LOCK | REFRESH_SLAVE |
- REFRESH_MASTER)))
+ REFRESH_MASTER | REFRESH_TABLE_STATS |
+ REFRESH_INDEX_STATS |
+ REFRESH_USER_STATS |
+ REFRESH_SLOW_QUERY_LOG |
+ REFRESH_CLIENT_STATS)))
{
my_printf_error(0, "refresh failed; error: '%s'", error_flags,
mysql_error(mysql));
@@ -671,7 +682,8 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
case ADMIN_VER:
new_line=1;
print_version();
- puts("Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.");
+ puts("Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc,\n"
+ "2009 Monty Program Ab");
puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n");
printf("Server version\t\t%s\n", mysql_get_server_info(mysql));
printf("Protocol version\t%d\n", mysql_get_proto_info(mysql));
@@ -847,9 +859,19 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
case ADMIN_FLUSH_LOGS:
{
- if (mysql_refresh(mysql,REFRESH_LOG))
+ if (mysql_query(mysql,"flush logs"))
{
- my_printf_error(0, "refresh failed; error: '%s'", error_flags,
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
+ mysql_error(mysql));
+ return -1;
+ }
+ break;
+ }
+ case ADMIN_FLUSH_SLOW_LOG:
+ {
+ if (mysql_query(mysql,"flush slow query logs"))
+ {
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
@@ -859,7 +881,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
if (mysql_query(mysql,"flush hosts"))
{
- my_printf_error(0, "refresh failed; error: '%s'", error_flags,
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
@@ -869,7 +891,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
if (mysql_query(mysql,"flush tables"))
{
- my_printf_error(0, "refresh failed; error: '%s'", error_flags,
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
@@ -879,7 +901,71 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
if (mysql_query(mysql,"flush status"))
{
- my_printf_error(0, "refresh failed; error: '%s'", error_flags,
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
+ mysql_error(mysql));
+ return -1;
+ }
+ break;
+ }
+ case ADMIN_FLUSH_TABLE_STATISTICS:
+ {
+ if (mysql_query(mysql,"flush table_statistics"))
+ {
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
+ mysql_error(mysql));
+ return -1;
+ }
+ break;
+ }
+ case ADMIN_FLUSH_INDEX_STATISTICS:
+ {
+ if (mysql_query(mysql,"flush index_statistics"))
+ {
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
+ mysql_error(mysql));
+ return -1;
+ }
+ break;
+ }
+ case ADMIN_FLUSH_USER_STATISTICS:
+ {
+ if (mysql_query(mysql,"flush user_statistics"))
+ {
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
+ mysql_error(mysql));
+ return -1;
+ }
+ break;
+ }
+ case ADMIN_FLUSH_CLIENT_STATISTICS:
+ {
+ if (mysql_query(mysql,"flush client_statistics"))
+ {
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
+ mysql_error(mysql));
+ return -1;
+ }
+ break;
+ }
+ case ADMIN_FLUSH_ALL_STATISTICS:
+ {
+ if (mysql_query(mysql,
+ "flush table_statistics,index_statistics,"
+ "user_statistics,client_statistics"))
+ {
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
+ mysql_error(mysql));
+ return -1;
+ }
+ break;
+ }
+ case ADMIN_FLUSH_ALL_STATUS:
+ {
+ if (mysql_query(mysql,
+ "flush status,table_statistics,index_statistics,"
+ "user_statistics,client_statistics"))
+ {
+ my_printf_error(0, "flush failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
@@ -893,7 +979,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
char *typed_password= NULL, *verified= NULL;
/* Do initialization the same way as we do in mysqld */
start_time=time((time_t*) 0);
- randominit(&rand_st,(ulong) start_time,(ulong) start_time/2);
+ my_rnd_init(&rand_st,(ulong) start_time,(ulong) start_time/2);
if (argc < 1)
{
@@ -1070,7 +1156,8 @@ static void print_version(void)
static void usage(void)
{
print_version();
- puts("Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc.");
+ puts("Copyright 2000-2008 MySQL AB, 2008 Sun Microsystems, Inc,\n"
+ "2009 Monty Program Ab");
puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\nand you are welcome to modify and redistribute it under the GPL license\n");
puts("Administration program for the mysqld daemon.");
printf("Usage: %s [OPTIONS] command command....\n", my_progname);
@@ -1078,16 +1165,23 @@ static void usage(void)
my_print_variables(my_long_options);
print_defaults("my",load_default_groups);
puts("\nWhere command is a one or more of: (Commands may be shortened)\n\
- create databasename Create a new database\n\
- debug Instruct server to write debug information to log\n\
- drop databasename Delete a database and all its tables\n\
- extended-status Gives an extended status message from the server\n\
- flush-hosts Flush all cached hosts\n\
- flush-logs Flush all logs\n\
- flush-status Clear status variables\n\
- flush-tables Flush all tables\n\
- flush-threads Flush the thread cache\n\
- flush-privileges Reload grant tables (same as reload)\n\
+ create databasename Create a new database\n\
+ debug Instruct server to write debug information to log\n\
+ drop databasename Delete a database and all its tables\n\
+ extended-status Gives an extended status message from the server\n\
+ flush-all-statistics Flush all statistics tables\n\
+ flush-all-status Flush status and statistics\n\
+ flush-client-statistics Flush client statistics\n\
+ flush-hosts Flush all cached hosts\n\
+ flush-index-statistics Flush index statistics\n\
+ flush-logs Flush all logs\n\
+ flush-privileges Reload grant tables (same as reload)\n\
+ flush-slow-log Flush slow query log\n\
+ flush-status Clear status variables\n\
+ flush-table-statistics Clear table statistics\n\
+ flush-tables Flush all tables\n\
+ flush-threads Flush the thread cache\n\
+ flush-user-statistics Flush user statistics\n\
kill id,id,... Kill mysql threads");
#if MYSQL_VERSION_ID >= 32200
puts("\
@@ -1377,7 +1471,7 @@ static my_bool wait_pidfile(char *pidfile, time_t last_modified,
struct stat *pidfile_status)
{
char buff[FN_REFLEN];
- int error= 1;
+ my_bool error= 1;
uint count= 0;
DBUG_ENTER("wait_pidfile");
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index 277c2d62544..a8f96a1089d 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -35,6 +35,15 @@
#include "log_event.h"
#include "sql_common.h"
+/* Needed for Rpl_filter */
+CHARSET_INFO* system_charset_info= &my_charset_utf8_general_ci;
+
+#include "sql_string.h" // needed for Rpl_filter
+#include "sql_list.h" // needed for Rpl_filter
+#include "rpl_filter.h"
+
+Rpl_filter *binlog_filter;
+
#define BIN_LOG_HEADER_SIZE 4
#define PROBE_HEADER_LEN (EVENT_LEN_OFFSET+4)
@@ -436,7 +445,7 @@ Exit_status Load_log_processor::process_first_event(const char *bname,
ptr= fname + target_dir_name_len;
memcpy(ptr,bname,blen);
ptr+= blen;
- ptr+= sprintf(ptr, "-%x", file_id);
+ ptr+= my_sprintf(ptr, (ptr, "-%x", file_id));
if ((file= create_unique_file(fname,ptr)) < 0)
{
@@ -626,6 +635,42 @@ static bool shall_skip_database(const char *log_dbname)
/**
+ Print "use <db>" statement when current db is to be changed.
+
+ We have to control emiting USE statements according to rewrite-db options.
+ We have to do it here (see process_event() below) and to suppress
+ producing USE statements by corresponding log event print-functions.
+*/
+
+void print_use_stmt(PRINT_EVENT_INFO* pinfo, const char* db, size_t db_len)
+{
+ // pinfo->db is the current db.
+ // If current db is the same as required db, do nothing.
+ if (!db || !memcmp(pinfo->db, db, db_len + 1))
+ return;
+
+ // Current db and required db are different.
+ // Check for rewrite rule for required db. (Note that in a rewrite rule
+ // neither db_from nor db_to part can be empty).
+ size_t len_to= 0;
+ const char *db_to= binlog_filter->get_rewrite_db(db, &len_to);
+
+ // If there is no rewrite rule for db (in this case len_to is left = 0),
+ // printing of the corresponding USE statement is left for log event
+ // print-function.
+ if (!len_to)
+ return;
+
+ // In case of rewrite rule print USE statement for db_to
+ fprintf(result_file, "use %s%s\n", db_to, pinfo->delimiter);
+
+ // Copy the *original* db to pinfo to suppress emiting
+ // of USE stmts by log_event print-functions.
+ memcpy(pinfo->db, db, db_len + 1);
+}
+
+
+/**
Prints the given event in base64 format.
The header is printed to the head cache and the body is printed to
@@ -736,9 +781,11 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
switch (ev_type) {
case QUERY_EVENT:
- if (!((Query_log_event*)ev)->is_trans_keyword() &&
- shall_skip_database(((Query_log_event*)ev)->db))
+ {
+ Query_log_event *qe= (Query_log_event*)ev;
+ if (!qe->is_trans_keyword() && shall_skip_database(qe->db))
goto end;
+ print_use_stmt(print_event_info, qe->db, qe->db_len);
if (opt_base64_output_mode == BASE64_OUTPUT_ALWAYS)
{
if ((retval= write_event_header_and_base64(ev, result_file,
@@ -749,6 +796,7 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
else
ev->print(result_file, print_event_info);
break;
+ }
case CREATE_FILE_EVENT:
{
@@ -876,6 +924,7 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
if (!shall_skip_database(exlq->db))
{
+ print_use_stmt(print_event_info, exlq->db, exlq->db_len);
if (fname)
{
convert_path_to_forward_slashes(fname);
@@ -899,6 +948,13 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
destroy_evt= FALSE;
goto end;
}
+ size_t len_to= 0;
+ const char* db_to= binlog_filter->get_rewrite_db(map->get_db_name(), &len_to);
+ if (len_to && map->rewrite_db(db_to, len_to, glob_description_event))
+ {
+ error("Could not rewrite database name");
+ goto err;
+ }
}
case WRITE_ROWS_EVENT:
case DELETE_ROWS_EVENT:
@@ -983,14 +1039,16 @@ err:
retval= ERROR_STOP;
end:
rec_count++;
+
/*
- Destroy the log_event object. If reading from a remote host,
- set the temp_buf to NULL so that memory isn't freed twice.
+ Destroy the log_event object.
+ MariaDB MWL#36: mainline does this:
+ If reading from a remote host,
+ set the temp_buf to NULL so that memory isn't freed twice.
+ We no longer do that, we use Rpl_filter::event_owns_temp_buf instead.
*/
if (ev)
{
- if (remote_opt)
- ev->temp_buf= 0;
if (destroy_evt) /* destroy it later if not set (ignored table map) */
delete ev;
}
@@ -1147,6 +1205,10 @@ that may lead to an endless loop.",
"Used to reserve file descriptors for use by this program.",
&open_files_limit, &open_files_limit, 0, GET_ULONG,
REQUIRED_ARG, MY_NFILE, 8, OS_FILE_LIMIT, 0, 1, 0},
+ {"rewrite-db", OPT_REWRITE_DB,
+ "Updates to a database with a different name than the original. \
+Example: rewrite-db='from->to'.",
+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -1330,6 +1392,53 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
(find_type_or_exit(argument, &base64_output_mode_typelib, opt->name)-1);
}
break;
+ case OPT_REWRITE_DB: // db_from->db_to
+ {
+ /* See also handling of OPT_REPLICATE_REWRITE_DB in sql/mysqld.cc */
+ char* ptr;
+ char* key= argument; // db-from
+ char* val; // db-to
+
+ // Where key begins
+ while (*key && my_isspace(&my_charset_latin1, *key))
+ key++;
+
+ // Where val begins
+ if (!(ptr= strstr(argument, "->")))
+ {
+ sql_print_error("Bad syntax in rewrite-db: missing '->'!\n");
+ return 1;
+ }
+ val= ptr + 2;
+ while (*val && my_isspace(&my_charset_latin1, *val))
+ val++;
+
+ // Write \0 and skip blanks at the end of key
+ *ptr-- = 0;
+ while (my_isspace(&my_charset_latin1, *ptr) && ptr > argument)
+ *ptr-- = 0;
+
+ if (!*key)
+ {
+ sql_print_error("Bad syntax in rewrite-db: empty db-from!\n");
+ return 1;
+ }
+
+ // Skip blanks at the end of val
+ ptr= val;
+ while (*ptr && !my_isspace(&my_charset_latin1, *ptr))
+ ptr++;
+ *ptr= 0;
+
+ if (!*val)
+ {
+ sql_print_error("Bad syntax in rewrite-db: empty db-to!\n");
+ return 1;
+ }
+
+ binlog_filter->add_db_rewrite(key, val);
+ break;
+ }
case 'v':
if (argument == disabled_my_option)
verbose= 0;
@@ -1374,6 +1483,10 @@ static int parse_args(int *argc, char*** argv)
*/
static Exit_status safe_connect()
{
+ /* Close and old connections to MySQL */
+ if (mysql)
+ mysql_close(mysql);
+
mysql= mysql_init(NULL);
if (!mysql)
@@ -1599,7 +1712,7 @@ static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
If reading from a remote host, ensure the temp_buf for the
Log_event class is pointing to the incoming stream.
*/
- ev->register_temp_buf((char *) net->read_pos + 1);
+ ev->register_temp_buf((char *) net->read_pos + 1, FALSE);
Log_event_type type= ev->get_type_code();
if (glob_description_event->binlog_version >= 3 ||
@@ -1999,6 +2112,8 @@ end:
return retval;
}
+/* Used in sql_alloc(). Inited and freed in main() */
+MEM_ROOT s_mem_root;
int main(int argc, char** argv)
{
@@ -2011,8 +2126,16 @@ int main(int argc, char** argv)
my_init_time(); // for time functions
+ init_alloc_root(&s_mem_root, 16384, 0);
+ if (!(binlog_filter= new Rpl_filter))
+ {
+ error("Failed to create Rpl_filter");
+ exit(1);
+ }
+
if (load_defaults("my", load_default_groups, &argc, &argv))
exit(1);
+
defaults_argv= argv;
parse_args(&argc, (char***)&argv);
@@ -2100,6 +2223,8 @@ int main(int argc, char** argv)
if (result_file != stdout)
my_fclose(result_file, MYF(0));
cleanup();
+ delete binlog_filter;
+ free_root(&s_mem_root, MYF(0));
free_defaults(defaults_argv);
my_free_open_file_info();
load_processor.destroy();
@@ -2111,6 +2236,12 @@ int main(int argc, char** argv)
DBUG_RETURN(retval == ERROR_STOP ? 1 : 0);
}
+
+void *sql_alloc(size_t size)
+{
+ return alloc_root(&s_mem_root, size);
+}
+
/*
We must include this here as it's compiled with different options for
the server
@@ -2122,3 +2253,6 @@ int main(int argc, char** argv)
#include "log_event.cc"
#include "log_event_old.cc"
#include "rpl_utility.cc"
+#include "sql_string.cc"
+#include "sql_list.cc"
+#include "rpl_filter.cc"
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c
index ce733e57db6..aeaead924c9 100644
--- a/client/mysqlcheck.c
+++ b/client/mysqlcheck.c
@@ -1,4 +1,6 @@
-/* Copyright (C) 2000 MySQL AB, 2009 Sun Microsystems, Inc
+/* Copyright (C) 2000 MySQL AB & Jani Tolonen
+ Copyright (C) 2009 Sun Microsystems, Inc
+ Copyright (C) 2010 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
@@ -15,7 +17,7 @@
/* By Jani Tolonen, 2001-04-20, MySQL Development Team */
-#define CHECK_VERSION "2.5.0"
+#define CHECK_VERSION "2.6.0"
#include "client_priv.h"
#include <m_ctype.h>
@@ -67,8 +69,8 @@ static struct my_option my_long_options[] =
&opt_auto_repair, &opt_auto_repair, 0, GET_BOOL, NO_ARG, 0,
0, 0, 0, 0, 0},
{"character-sets-dir", OPT_CHARSETS_DIR,
- "Directory for character set files.", &charsets_dir,
- &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ "Directory for character set files.", (char**) &charsets_dir,
+ (char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"check", 'c', "Check table for errors.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0,
0, 0, 0, 0},
{"check-only-changed", 'C',
@@ -216,24 +218,26 @@ static void usage(void)
{
print_version();
puts("By Jani Tolonen, 2001-04-20, MySQL Development Team.\n");
- puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n");
+ puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,");
puts("and you are welcome to modify and redistribute it under the GPL license.\n");
+ printf("Usage: %s [OPTIONS] database [tables]\n", my_progname);
+ printf("OR %s [OPTIONS] --databases DB1 [DB2 DB3...]\n",
+ my_progname);
+ printf("OR %s [OPTIONS] --all-databases\n\n", my_progname);
puts("This program can be used to CHECK (-c, -m, -C), REPAIR (-r), ANALYZE (-a),");
puts("or OPTIMIZE (-o) tables. Some of the options (like -e or -q) can be");
puts("used at the same time. Not all options are supported by all storage engines.");
- puts("Please consult the MySQL manual for latest information about the");
- puts("above. The options -c, -r, -a, and -o are exclusive to each other, which");
+ puts("The options -c, -r, -a, and -o are exclusive to each other, which");
puts("means that the last option will be used, if several was specified.\n");
- puts("The option -c will be used by default, if none was specified. You");
- puts("can change the default behavior by making a symbolic link, or");
+ puts("The option -c (--check) will be used by default, if none was specified.");
+ puts("You can change the default behavior by making a symbolic link, or");
puts("copying this file somewhere with another name, the alternatives are:");
puts("mysqlrepair: The default option will be -r");
puts("mysqlanalyze: The default option will be -a");
puts("mysqloptimize: The default option will be -o\n");
- printf("Usage: %s [OPTIONS] database [tables]\n", my_progname);
- printf("OR %s [OPTIONS] --databases DB1 [DB2 DB3...]\n",
- my_progname);
- printf("OR %s [OPTIONS] --all-databases\n", my_progname);
+ puts("Please consult the MariaDB/MySQL knowledgebase at");
+ puts("http://kb.askmonty.org/v/mysqlcheck for latest information about");
+ puts("this program.");
print_defaults("my", load_default_groups);
my_print_help(my_long_options);
my_print_variables(my_long_options);
@@ -406,6 +410,8 @@ static int process_all_databases()
MYF(0), mysql_error(sock));
return 1;
}
+ if (verbose)
+ printf("Processing databases\n");
while ((row = mysql_fetch_row(tableres)))
{
if (process_one_db(row[0]))
@@ -419,6 +425,8 @@ static int process_all_databases()
static int process_databases(char **db_names)
{
int result = 0;
+ if (verbose)
+ printf("Processing databases\n");
for ( ; *db_names ; db_names++)
{
if (process_one_db(*db_names))
@@ -511,6 +519,7 @@ static int process_all_tables_in_db(char *database)
MYSQL_RES *res;
MYSQL_ROW row;
uint num_columns;
+ my_bool system_database= 0;
LINT_INIT(res);
if (use_db(database))
@@ -524,6 +533,9 @@ static int process_all_tables_in_db(char *database)
return 1;
}
+ if (!strcmp(database, "mysql") || !strcmp(database, "MYSQL"))
+ system_database= 1;
+
num_columns= mysql_num_fields(res);
if (opt_all_in_1 && what_to_do != DO_UPGRADE)
@@ -566,6 +578,10 @@ static int process_all_tables_in_db(char *database)
/* Skip views if we don't perform renaming. */
if ((what_to_do != DO_UPGRADE) && (num_columns == 2) && (strcmp(row[1], "VIEW") == 0))
continue;
+ if (system_database &&
+ (!strcmp(row[0], "general_log") ||
+ !strcmp(row[0], "slow_log")))
+ continue; /* Skip logging tables */
handle_request_for_tables(row[0], fixed_name_length(row[0]));
}
@@ -614,6 +630,8 @@ static int fix_database_storage_name(const char *name)
static int process_one_db(char *database)
{
+ if (verbose)
+ puts(database);
if (what_to_do == DO_UPGRADE)
{
int rc= 0;
@@ -696,7 +714,8 @@ static int handle_request_for_tables(char *tables, uint length)
if (opt_all_in_1)
{
/* No backticks here as we added them before */
- query_length= sprintf(query, "%s TABLE %s %s", op, tables, options);
+ query_length= my_sprintf(query,
+ (query, "%s TABLE %s %s", op, tables, options));
}
else
{
@@ -723,7 +742,7 @@ static void print_result()
{
MYSQL_RES *res;
MYSQL_ROW row;
- char prev[NAME_LEN*2+2];
+ char prev[(NAME_LEN+9)*2+2];
uint i;
my_bool found_error=0;
@@ -753,7 +772,15 @@ static void print_result()
printf("%-50s %s", row[0], row[3]);
else if (!status && changed)
{
- printf("%s\n%-9s: %s", row[0], row[2], row[3]);
+ /*
+ If the error message includes REPAIR TABLE, we assume it means
+ we have to run upgrade on it. In this case we write a nicer message
+ than "Please do "REPAIR TABLE""...
+ */
+ if (!strcmp(row[2],"error") && strinstr(row[3],"REPAIR TABLE") != 0)
+ printf("%-50s %s", row[0], "Needs upgrade");
+ else
+ printf("%s\n%-9s: %s", row[0], row[2], row[3]);
if (strcmp(row[2],"note"))
found_error=1;
}
@@ -772,7 +799,7 @@ static void print_result()
static int dbConnect(char *host, char *user, char *passwd)
{
DBUG_ENTER("dbConnect");
- if (verbose)
+ if (verbose > 1)
{
fprintf(stderr, "# Connecting to %s...\n", host ? host : "localhost");
}
@@ -804,7 +831,7 @@ static int dbConnect(char *host, char *user, char *passwd)
static void dbDisconnect(char *host)
{
- if (verbose)
+ if (verbose > 1)
fprintf(stderr, "# Disconnecting from %s...\n", host ? host : "localhost");
mysql_close(sock);
} /* dbDisconnect */
@@ -848,7 +875,8 @@ int main(int argc, char **argv)
if (!opt_write_binlog)
{
- if (disable_binlog()) {
+ if (disable_binlog())
+ {
first_error= 1;
goto end;
}
diff --git a/client/mysqldump.c b/client/mysqldump.c
index ac704f152de..626ce1dede7 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -212,8 +212,8 @@ static struct my_option my_long_options[] =
&opt_slave_apply, &opt_slave_apply, 0, GET_BOOL, NO_ARG,
0, 0, 0, 0, 0, 0},
{"character-sets-dir", OPT_CHARSETS_DIR,
- "Directory for character set files.", &charsets_dir,
- &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ "Directory for character set files.", (char**) &charsets_dir,
+ (char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"comments", 'i', "Write additional information.",
&opt_comments, &opt_comments, 0, GET_BOOL, NO_ARG,
1, 0, 0, 0, 0, 0},
@@ -250,8 +250,8 @@ static struct my_option my_long_options[] =
{"debug", '#', "This is a non-debug version. Catch this and exit.",
0,0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0},
#else
- {"debug", '#', "Output debug log.", &default_dbug_option,
- &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
+ {"debug", '#', "Output debug log.", (char**) &default_dbug_option,
+ (char**) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
#endif
{"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
&debug_check_flag, &debug_check_flag, 0,
@@ -974,7 +974,7 @@ static int get_options(int *argc, char ***argv)
static void DB_error(MYSQL *mysql_arg, const char *when)
{
DBUG_ENTER("DB_error");
- maybe_die(EX_MYSQLERR, "Got error: %d: %s %s",
+ maybe_die(EX_MYSQLERR, "Got error: %d: \"%s\" %s",
mysql_errno(mysql_arg), mysql_error(mysql_arg), when);
DBUG_VOID_RETURN;
}
@@ -1399,6 +1399,7 @@ static void free_resources()
if (md_result_file && md_result_file != stdout)
my_fclose(md_result_file, MYF(0));
my_free(opt_password);
+ my_free(current_host);
if (my_hash_inited(&ignore_table))
my_hash_free(&ignore_table);
if (extended_insert)
@@ -4206,7 +4207,7 @@ static char *get_actual_table_name(const char *old_table_name, MEM_ROOT *root)
}
mysql_free_result(table_res);
}
- DBUG_PRINT("exit", ("new_table_name: %s", name));
+ DBUG_PRINT("exit", ("new_table_name: %s", val_or_null(name)));
DBUG_RETURN(name);
}
@@ -4928,6 +4929,7 @@ static my_bool get_view_structure(char *table, char* db)
field= mysql_fetch_field_direct(table_res, 0);
if (strcmp(field->name, "View") != 0)
{
+ mysql_free_result(table_res);
switch_character_set_results(mysql, default_charset);
verbose_msg("-- It's base table, skipped\n");
DBUG_RETURN(0);
@@ -4937,8 +4939,10 @@ static my_bool get_view_structure(char *table, char* db)
if (path)
{
if (!(sql_file= open_sql_file_for_table(table, O_WRONLY)))
+ {
+ mysql_free_result(table_res);
DBUG_RETURN(1);
-
+ }
write_header(sql_file, db);
}
diff --git a/client/mysqlimport.c b/client/mysqlimport.c
index 3d71e437e40..593d43c0c80 100644
--- a/client/mysqlimport.c
+++ b/client/mysqlimport.c
@@ -68,8 +68,8 @@ static char *shared_memory_base_name=0;
static struct my_option my_long_options[] =
{
{"character-sets-dir", OPT_CHARSETS_DIR,
- "Directory for character set files.", &charsets_dir,
- &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ "Directory for character set files.", (char**) &charsets_dir,
+ (char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"default-character-set", OPT_DEFAULT_CHARSET,
"Set the default character set.", &default_charset,
&default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
diff --git a/client/mysqlshow.c b/client/mysqlshow.c
index bb05400e0d8..3cc551d2092 100644
--- a/client/mysqlshow.c
+++ b/client/mysqlshow.c
@@ -161,7 +161,7 @@ int main(int argc, char **argv)
static struct my_option my_long_options[] =
{
{"character-sets-dir", 'c', "Directory for character set files.",
- &charsets_dir, &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0,
+ (char**) &charsets_dir, (char**) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0,
0, 0, 0, 0, 0},
{"default-character-set", OPT_DEFAULT_CHARSET,
"Set the default character set.", &default_charset,
diff --git a/client/mysqlslap.c b/client/mysqlslap.c
index e605e2d522c..6d93bd73efe 100644
--- a/client/mysqlslap.c
+++ b/client/mysqlslap.c
@@ -292,6 +292,25 @@ static int gettimeofday(struct timeval *tp, void *tzp)
}
#endif
+void set_mysql_connect_options(MYSQL *mysql)
+{
+ if (opt_compress)
+ mysql_options(mysql,MYSQL_OPT_COMPRESS,NullS);
+#ifdef HAVE_OPENSSL
+ if (opt_use_ssl)
+ mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
+ opt_ssl_capath, opt_ssl_cipher);
+#endif
+ if (opt_protocol)
+ mysql_options(mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
+#ifdef HAVE_SMEM
+ if (shared_memory_base_name)
+ mysql_options(mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
+#endif
+ mysql_options(mysql, MYSQL_SET_CHARSET_NAME, default_charset);
+}
+
+
int main(int argc, char **argv)
{
MYSQL mysql;
@@ -327,20 +346,7 @@ int main(int argc, char **argv)
exit(1);
}
mysql_init(&mysql);
- if (opt_compress)
- mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS);
-#ifdef HAVE_OPENSSL
- if (opt_use_ssl)
- mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
- opt_ssl_capath, opt_ssl_cipher);
-#endif
- if (opt_protocol)
- mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
-#ifdef HAVE_SMEM
- if (shared_memory_base_name)
- mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
-#endif
- mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
+ set_mysql_connect_options(&mysql);
if (!opt_only_print)
{
@@ -450,7 +456,16 @@ void concurrency_loop(MYSQL *mysql, uint current, option_string *eptr)
/* First we create */
if (create_statements)
+ {
+ /*
+ If we have an --engine option, then we indicate
+ create_schema() to add the engine type to the DDL.
+ */
+ if (eptr)
+ create_statements->type= CREATE_TABLE_TYPE;
+
create_schema(mysql, create_schema_string, create_statements, eptr);
+ }
/*
If we generated GUID we need to build a list of them from creation that
@@ -464,10 +479,10 @@ void concurrency_loop(MYSQL *mysql, uint current, option_string *eptr)
if (commit_rate)
run_query(mysql, "SET AUTOCOMMIT=0", strlen("SET AUTOCOMMIT=0"));
- if (pre_system)
- if ((sysret= system(pre_system)) != 0)
- fprintf(stderr, "Warning: Execution of pre_system option returned %d.\n",
- sysret);
+ if (pre_system && (sysret= system(pre_system)) != 0)
+ fprintf(stderr,
+ "Warning: Execution of pre_system option returned %d.\n",
+ sysret);
/*
Pre statements are always run after all other logic so they can
@@ -481,11 +496,10 @@ void concurrency_loop(MYSQL *mysql, uint current, option_string *eptr)
if (post_statements)
run_statements(mysql, post_statements);
- if (post_system)
- if ((sysret= system(post_system)) != 0)
- fprintf(stderr, "Warning: Execution of post_system option returned %d.\n",
- sysret);
-
+ if (post_system && (sysret= system(post_system)) != 0)
+ fprintf(stderr,
+ "Warning: Execution of post_system option returned %d.\n",
+ sysret);
/* We are finished with this run */
if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
drop_primary_key_list();
@@ -530,7 +544,7 @@ static struct my_option my_long_options[] =
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"auto-generate-sql-load-type", OPT_SLAP_AUTO_GENERATE_SQL_LOAD_TYPE,
"Specify test load type: mixed, update, write, key, or read; default is mixed.",
- &auto_generate_sql_type, &auto_generate_sql_type,
+ (char**) &auto_generate_sql_type, (char**) &auto_generate_sql_type,
0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"auto-generate-sql-secondary-indexes",
OPT_SLAP_AUTO_GENERATE_SECONDARY_INDEXES,
@@ -561,13 +575,13 @@ static struct my_option my_long_options[] =
&opt_compress, &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
0, 0, 0},
{"concurrency", 'c', "Number of clients to simulate for query to run.",
- &concurrency_str, &concurrency_str, 0, GET_STR,
+ (char**) &concurrency_str, (char**) &concurrency_str, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"create", OPT_SLAP_CREATE_STRING, "File or string to use create tables.",
&create_string, &create_string, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
{"create-schema", OPT_CREATE_SLAP_SCHEMA, "Schema to run tests in.",
- &create_schema_string, &create_schema_string, 0, GET_STR,
+ (char**) &create_schema_string, (char**) &create_schema_string, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"csv", OPT_SLAP_CSV,
"Generate CSV output to named file or to stdout if no file is named.",
@@ -577,7 +591,7 @@ static struct my_option my_long_options[] =
0, 0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0},
#else
{"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.",
- &default_dbug_option, &default_dbug_option, 0, GET_STR,
+ (char**) &default_dbug_option, (char**) &default_dbug_option, 0, GET_STR,
OPT_ARG, 0, 0, 0, 0, 0, 0},
#endif
{"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit.",
@@ -587,14 +601,17 @@ static struct my_option my_long_options[] =
&debug_info_flag, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"delimiter", 'F',
"Delimiter to use in SQL statements supplied in file or command line.",
- &delimiter, &delimiter, 0, GET_STR, REQUIRED_ARG,
+ (char**) &delimiter, (char**) &delimiter, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
{"detach", OPT_SLAP_DETACH,
"Detach (close and reopen) connections after X number of requests.",
&detach_rate, &detach_rate, 0, GET_UINT, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
- {"engine", 'e', "Storage engine to use for creating the table.",
- &default_engine, &default_engine, 0,
+ {"engine", 'e',
+ "Comma separated list of storage engines to use for creating the table."
+ " The test is run for each engine. You can also specify an option for an "
+ "engine after a `:', like memory:max_row=2300",
+ &default_engine, &default_engine, 0,
GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"host", 'h', "Connect to host.", &host, &host, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -602,11 +619,11 @@ static struct my_option my_long_options[] =
&iterations, 0, GET_UINT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0},
{"number-char-cols", 'x',
"Number of VARCHAR columns to create in table if specifying --auto-generate-sql.",
- &num_char_cols_opt, &num_char_cols_opt, 0, GET_STR, REQUIRED_ARG,
+ (char**) &num_char_cols_opt, (char**) &num_char_cols_opt, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
{"number-int-cols", 'y',
"Number of INT columns to create in table if specifying --auto-generate-sql.",
- &num_int_cols_opt, &num_int_cols_opt, 0, GET_STR, REQUIRED_ARG,
+ (char**) &num_int_cols_opt, (char**) &num_int_cols_opt, 0, GET_STR, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
{"number-of-queries", OPT_MYSQL_NUMBER_OF_QUERY,
"Limit each client to this number of queries (this is not exact).",
@@ -958,6 +975,7 @@ build_update_string(void)
ptr->type= UPDATE_TYPE_REQUIRES_PREFIX ;
else
ptr->type= UPDATE_TYPE;
+
strmov(ptr->string, update_string.str);
dynstr_free(&update_string);
DBUG_RETURN(ptr);
@@ -973,8 +991,8 @@ build_update_string(void)
static statement *
build_insert_string(void)
{
- char buf[HUGE_STRING_LENGTH];
- unsigned int col_count;
+ char buf[HUGE_STRING_LENGTH];
+ unsigned int col_count;
statement *ptr;
DYNAMIC_STRING insert_string;
DBUG_ENTER("build_insert_string");
@@ -1064,8 +1082,8 @@ build_insert_string(void)
static statement *
build_select_string(my_bool key)
{
- char buf[HUGE_STRING_LENGTH];
- unsigned int col_count;
+ char buf[HUGE_STRING_LENGTH];
+ unsigned int col_count;
statement *ptr;
static DYNAMIC_STRING query_string;
DBUG_ENTER("build_select_string");
@@ -1117,6 +1135,7 @@ build_select_string(my_bool key)
ptr->type= SELECT_TYPE_REQUIRES_PREFIX;
else
ptr->type= SELECT_TYPE;
+
strmov(ptr->string, query_string.str);
dynstr_free(&query_string);
DBUG_RETURN(ptr);
@@ -1175,8 +1194,6 @@ get_options(int *argc,char ***argv)
exit(1);
}
-
-
if (auto_generate_sql && num_of_query && auto_actual_queries)
{
fprintf(stderr,
@@ -1217,6 +1234,7 @@ get_options(int *argc,char ***argv)
num_int_cols= atoi(str->string);
if (str->option)
num_int_cols_index= atoi(str->option);
+
option_cleanup(str);
}
@@ -1229,6 +1247,7 @@ get_options(int *argc,char ***argv)
num_char_cols_index= atoi(str->option);
else
num_char_cols_index= 0;
+
option_cleanup(str);
}
@@ -1463,6 +1482,7 @@ get_options(int *argc,char ***argv)
if (tty_password)
opt_password= get_tty_password(NullS);
+
DBUG_RETURN(0);
}
@@ -1477,6 +1497,7 @@ static int run_query(MYSQL *mysql, const char *query, int len)
if (verbose >= 3)
printf("%.*s;\n", len, query);
+
return mysql_real_query(mysql, query, len);
}
@@ -1592,18 +1613,6 @@ create_schema(MYSQL *mysql, const char *db, statement *stmt,
}
}
- if (engine_stmt)
- {
- len= snprintf(query, HUGE_STRING_LENGTH, "set storage_engine=`%s`",
- engine_stmt->string);
- if (run_query(mysql, query, len))
- {
- fprintf(stderr,"%s: Cannot set default engine: %s\n", my_progname,
- mysql_error(mysql));
- exit(1);
- }
- }
-
count= 0;
after_create= stmt;
@@ -1617,8 +1626,21 @@ limit_not_met:
{
char buffer[HUGE_STRING_LENGTH];
- snprintf(buffer, HUGE_STRING_LENGTH, "%s %s", ptr->string,
- engine_stmt->option);
+ snprintf(buffer, HUGE_STRING_LENGTH, "%s Engine = %s %s",
+ ptr->string, engine_stmt->string, engine_stmt->option);
+ if (run_query(mysql, buffer, strlen(buffer)))
+ {
+ fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
+ my_progname, (uint)ptr->length, ptr->string, mysql_error(mysql));
+ exit(1);
+ }
+ }
+ else if (engine_stmt && engine_stmt->string && ptr->type == CREATE_TABLE_TYPE)
+ {
+ char buffer[HUGE_STRING_LENGTH];
+
+ snprintf(buffer, HUGE_STRING_LENGTH, "%s Engine = %s",
+ ptr->string, engine_stmt->string);
if (run_query(mysql, buffer, strlen(buffer)))
{
fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
@@ -1652,6 +1674,7 @@ drop_schema(MYSQL *mysql, const char *db)
{
char query[HUGE_STRING_LENGTH];
int len;
+
DBUG_ENTER("drop_schema");
len= snprintf(query, HUGE_STRING_LENGTH, "DROP SCHEMA IF EXISTS `%s`", db);
@@ -1788,6 +1811,7 @@ pthread_handler_t run_task(void *p)
my_progname, mysql_error(mysql));
exit(0);
}
+ set_mysql_connect_options(mysql);
if (mysql_thread_init())
{
@@ -1828,7 +1852,6 @@ limit_not_met:
my_progname, mysql_error(mysql));
exit(0);
}
-
if (slap_connect(mysql))
goto end;
}
@@ -1884,10 +1907,17 @@ limit_not_met:
{
if (mysql_field_count(mysql))
{
- result= mysql_store_result(mysql);
- while ((row = mysql_fetch_row(result)))
- counter++;
- mysql_free_result(result);
+ if ((result= mysql_store_result(mysql)))
+ {
+ while ((row = mysql_fetch_row(result)))
+ counter++;
+ mysql_free_result(result);
+ }
+ else
+ {
+ fprintf(stderr,"%s: Error in mysql_store_result(): %d %s\n",
+ my_progname, mysql_errno(mysql), mysql_error(mysql));
+ }
}
} while(mysql_next_result(mysql) == 0);
queries++;
@@ -1933,17 +1963,27 @@ parse_option(const char *origin, option_string **stmt, char delm)
uint count= 0; /* We know that there is always one */
for (tmp= *sptr= (option_string *)my_malloc(sizeof(option_string),
- MYF(MY_ZEROFILL|MY_FAE|MY_WME));
+ MYF(MY_ZEROFILL|MY_FAE|MY_WME));
(retstr= strchr(ptr, delm));
tmp->next= (option_string *)my_malloc(sizeof(option_string),
- MYF(MY_ZEROFILL|MY_FAE|MY_WME)),
+ MYF(MY_ZEROFILL|MY_FAE|MY_WME)),
tmp= tmp->next)
{
- char buffer[HUGE_STRING_LENGTH];
+ /*
+ Initialize buffer, because otherwise an
+ --engine=<storage_engine>:<option>,<eng1>,<eng2>
+ will crash.
+ */
+ char buffer[HUGE_STRING_LENGTH]= "";
char *buffer_ptr;
count++;
strncpy(buffer, ptr, (size_t)(retstr - ptr));
+ /*
+ Handle --engine=memory:max_row=200 cases, or more general speaking
+ --engine=<storage_engine>:<options>, which will be translated to
+ Engine = storage_engine option.
+ */
if ((buffer_ptr= strchr(buffer, ':')))
{
char *option_ptr;
@@ -1964,13 +2004,15 @@ parse_option(const char *origin, option_string **stmt, char delm)
tmp->length= (size_t)(retstr - ptr);
}
+ /* Skip delimiter delm */
ptr+= retstr - ptr + 1;
if (isspace(*ptr))
ptr++;
+
count++;
}
- if (ptr != origin+length)
+ if (ptr != origin + length)
{
char *origin_ptr;
@@ -1979,7 +2021,7 @@ parse_option(const char *origin, option_string **stmt, char delm)
char *option_ptr;
tmp->length= (size_t)(origin_ptr - ptr);
- tmp->string= my_strndup(origin, tmp->length, MYF(MY_FAE));
+ tmp->string= my_strndup(ptr, tmp->length, MYF(MY_FAE));
option_ptr= (char *)ptr + 1 + tmp->length;
@@ -2029,7 +2071,7 @@ parse_delimiter(const char *script, statement **stmt, char delm)
if (ptr != script+length)
{
tmp->string= my_strndup(ptr, (uint)((script + length) - ptr),
- MYF(MY_FAE));
+ MYF(MY_FAE));
tmp->length= (size_t)((script + length) - ptr);
count++;
}
@@ -2087,6 +2129,7 @@ print_conclusions_csv(conclusions *con)
{
char buffer[HUGE_STRING_LENGTH];
const char *ptr= auto_generate_sql_type ? auto_generate_sql_type : "query";
+
snprintf(buffer, HUGE_STRING_LENGTH,
"%s,%s,%ld.%03ld,%ld.%03ld,%ld.%03ld,%d,%llu\n",
con->engine ? con->engine : "", /* Storage engine we ran against */
@@ -2173,6 +2216,7 @@ slap_connect(MYSQL *mysql)
int x, connect_error= 1;
for (x= 0; x < 10; x++)
{
+ set_mysql_connect_options(mysql);
if (mysql_real_connect(mysql, host, user, opt_password,
create_schema_string,
opt_mysql_port,
diff --git a/client/mysqltest.cc b/client/mysqltest.cc
index 611f7f02be4..3eea6b997c8 100644
--- a/client/mysqltest.cc
+++ b/client/mysqltest.cc
@@ -36,6 +36,7 @@
#include "client_priv.h"
#include <mysql_version.h>
#include <mysqld_error.h>
+#include <sql_common.h>
#include <m_ctype.h>
#include <my_dir.h>
#include <hash.h>
@@ -87,7 +88,8 @@ enum {
OPT_PS_PROTOCOL=OPT_MAX_CLIENT_OPTION, OPT_SP_PROTOCOL,
OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL, OPT_MAX_CONNECT_RETRIES,
OPT_MAX_CONNECTIONS, OPT_MARK_PROGRESS, OPT_LOG_DIR,
- OPT_TAIL_LINES, OPT_RESULT_FORMAT_VERSION
+ OPT_TAIL_LINES, OPT_RESULT_FORMAT_VERSION,
+ OPT_MY_CONNECT_TIMEOUT
};
static int record= 0, opt_sleep= -1;
@@ -101,6 +103,7 @@ static int opt_max_connect_retries;
static int opt_result_format_version;
static int opt_max_connections= DEFAULT_MAX_CONN;
static my_bool opt_compress= 0, silent= 0, verbose= 0;
+static int opt_connect_timeout= -1;
static my_bool debug_info_flag= 0, debug_check_flag= 0;
static my_bool tty_password= 0;
static my_bool opt_mark_progress= 0;
@@ -114,6 +117,7 @@ static my_bool display_result_vertically= FALSE, display_result_lower= FALSE,
static my_bool disable_query_log= 0, disable_result_log= 0;
static my_bool disable_connect_log= 1;
static my_bool disable_warnings= 0;
+static my_bool prepare_warnings_enabled= 0;
static my_bool disable_info= 1;
static my_bool abort_on_error= 1;
static my_bool server_initialized= 0;
@@ -134,6 +138,9 @@ static char delimiter[MAX_DELIMITER_LENGTH]= ";";
static uint delimiter_length= 1;
static char TMPDIR[FN_REFLEN];
+static char global_subst_from[200];
+static char global_subst_to[200];
+static char *global_subst= NULL;
/* Block stack */
enum block_cmd {
@@ -200,6 +207,10 @@ static void init_re(void);
static int match_re(my_regex_t *, char *);
static void free_re(void);
+static int replace(DYNAMIC_STRING *ds_str,
+ const char *search_str, ulong search_len,
+ const char *replace_str, ulong replace_len);
+
static uint opt_protocol=0;
DYNAMIC_ARRAY q_lines;
@@ -311,6 +322,7 @@ enum enum_commands {
Q_SEND_SHUTDOWN, Q_SHUTDOWN_SERVER,
Q_RESULT_FORMAT_VERSION,
Q_MOVE_FILE, Q_REMOVE_FILES_WILDCARD, Q_SEND_EVAL,
+ Q_ENABLE_PREPARE_WARNINGS, Q_DISABLE_PREPARE_WARNINGS,
Q_UNKNOWN, /* Unknown command. */
Q_COMMENT, /* Comments, ignored. */
Q_COMMENT_WITH_COMMAND,
@@ -411,6 +423,8 @@ const char *command_names[]=
"move_file",
"remove_files_wildcard",
"send_eval",
+ "enable_prepare_warnings",
+ "disable_prepare_warnings",
0
};
@@ -543,7 +557,7 @@ public:
{
DBUG_ENTER("LogFile::open");
DBUG_PRINT("enter", ("dir: '%s', name: '%s'",
- dir, name));
+ val_or_null(dir), val_or_null(name)));
if (!name)
{
m_file= stdout;
@@ -609,14 +623,14 @@ public:
lines++;
int show_offset= 0;
- char buf[256];
+ char buf[256+1]; /* + zero termination for DBUG_PRINT */
size_t bytes;
bool found_bof= false;
/* Search backward in file until "lines" newline has been found */
while (lines && !found_bof)
{
- show_offset-= sizeof(buf);
+ show_offset-= sizeof(buf)-1;
while(fseek(m_file, show_offset, SEEK_END) != 0 && show_offset < 0)
{
found_bof= true;
@@ -624,7 +638,7 @@ public:
show_offset++;
}
- if ((bytes= fread(buf, 1, sizeof(buf), m_file)) <= 0)
+ if ((bytes= fread(buf, 1, sizeof(buf)-1, m_file)) <= 0)
{
// ferror=0 will happen here if no queries executed yet
if (ferror(m_file))
@@ -634,6 +648,7 @@ public:
DBUG_VOID_RETURN;
}
+ IF_DBUG(buf[bytes]= '\0';)
DBUG_PRINT("info", ("Read %lu bytes from file, buf: %s",
(unsigned long)bytes, buf));
@@ -678,8 +693,10 @@ public:
}
}
- while ((bytes= fread(buf, 1, sizeof(buf), m_file)) > 0)
- fwrite(buf, 1, bytes, stderr);
+ while ((bytes= fread(buf, 1, sizeof(buf)-1, m_file)) > 0)
+ if (bytes != fwrite(buf, 1, bytes, stderr))
+ die("Failed to write to '%s', errno: %d",
+ m_file_name, errno);
if (!lines)
{
@@ -716,6 +733,10 @@ void handle_no_error(struct st_command*);
#define EMB_READ_QUERY_RESULT 2
#define EMB_END_CONNECTION 3
+/* workaround for MySQL BUG#57491 */
+#undef MY_WME
+#define MY_WME 0
+
/* attributes of the query thread */
pthread_attr_t cn_thd_attrib;
@@ -1152,7 +1173,8 @@ void check_command_args(struct st_command *command,
DBUG_VOID_RETURN;
}
-void handle_command_error(struct st_command *command, uint error)
+void handle_command_error(struct st_command *command, uint error,
+ int sys_errno)
{
DBUG_ENTER("handle_command_error");
DBUG_PRINT("enter", ("error: %d", error));
@@ -1168,13 +1190,14 @@ void handle_command_error(struct st_command *command, uint error)
if (i >= 0)
{
- DBUG_PRINT("info", ("command \"%.*s\" failed with expected error: %d",
- command->first_word_len, command->query, error));
+ DBUG_PRINT("info", ("command \"%.*s\" failed with expected error: %u, errno: %d",
+ command->first_word_len, command->query, error,
+ sys_errno));
DBUG_VOID_RETURN;
}
if (command->expected_errors.count > 0)
- die("command \"%.*s\" failed with wrong error: %d",
- command->first_word_len, command->query, error);
+ die("command \"%.*s\" failed with wrong error: %u, errno: %d",
+ command->first_word_len, command->query, error, sys_errno);
}
else if (command->expected_errors.err[0].type == ERR_ERRNO &&
command->expected_errors.err[0].code.errnum != 0)
@@ -1317,15 +1340,6 @@ void die(const char *fmt, ...)
DBUG_ENTER("die");
DBUG_PRINT("enter", ("start_lineno: %d", start_lineno));
- /*
- Protect against dying twice
- first time 'die' is called, try to write log files
- second time, just exit
- */
- if (dying)
- cleanup_and_exit(1);
- dying= 1;
-
/* Print the error message */
fprintf(stderr, "mysqltest: ");
if (cur_file && cur_file != file_stack)
@@ -1344,6 +1358,15 @@ void die(const char *fmt, ...)
fprintf(stderr, "\n");
fflush(stderr);
+ /*
+ Protect against dying twice
+ first time 'die' is called, try to write log files
+ second time, just exit
+ */
+ if (dying)
+ cleanup_and_exit(1);
+ dying= 1;
+
log_file.show_tail(opt_tail_lines);
/*
@@ -1364,6 +1387,7 @@ void abort_not_supported_test(const char *fmt, ...)
DBUG_ENTER("abort_not_supported_test");
/* Print include filestack */
+ fflush(stdout);
fprintf(stderr, "The test '%s' is not supported by this installation\n",
file_stack->file_name);
fprintf(stderr, "Detected in file %s at line %d\n",
@@ -1755,49 +1779,69 @@ enum compare_files_result_enum {
*/
-int compare_files2(File fd, const char* filename2)
+int compare_files2(File fd1, const char* filename2)
{
int error= RESULT_OK;
File fd2;
- size_t len, len2;
- char buff[512], buff2[512];
+ size_t fd1_length, fd2_length;
+ DYNAMIC_STRING fd1_result, fd2_result;
if ((fd2= my_open(filename2, O_RDONLY, MYF(0))) < 0)
{
- my_close(fd, MYF(0));
+ my_close(fd1, MYF(0));
die("Failed to open second file: '%s'", filename2);
}
- while((len= my_read(fd, (uchar*)&buff,
- sizeof(buff), MYF(0))) > 0)
- {
- if ((len2= my_read(fd2, (uchar*)&buff2,
- sizeof(buff2), MYF(0))) < len)
- {
- /* File 2 was smaller */
- error= RESULT_LENGTH_MISMATCH;
- break;
- }
- if (len2 > len)
- {
- /* File 1 was smaller */
- error= RESULT_LENGTH_MISMATCH;
- break;
- }
- if ((memcmp(buff, buff2, len)))
- {
- /* Content of this part differed */
- error= RESULT_CONTENT_MISMATCH;
- break;
- }
+
+ fd1_length= (size_t) my_seek(fd1, 0, SEEK_END, MYF(0));
+ fd2_length= (size_t) my_seek(fd2, 0, SEEK_END, MYF(0));
+
+ if (init_dynamic_string(&fd1_result, 0, fd1_length, 0) ||
+ init_dynamic_string(&fd2_result, 0, fd2_length, 0))
+ die("Out of memory when allocating data for result");
+
+ fd1_result.length= fd1_length;
+ fd2_result.length= fd2_length;
+
+ (void) my_seek(fd1, 0, SEEK_SET, MYF(0));
+ (void) my_seek(fd2, 0, SEEK_SET, MYF(0));
+ if (my_read(fd1, (uchar*) fd1_result.str, fd1_length, MYF(MY_WME | MY_NABP)))
+ die("Error when reading data from result file");
+ if (my_read(fd2, (uchar*) fd2_result.str, fd2_length, MYF(MY_WME | MY_NABP)))
+ die("Error when reading data from result file");
+
+ if (global_subst &&
+ (fd1_length != fd2_length ||
+ memcmp(fd1_result.str, fd2_result.str, fd1_length)))
+ {
+ /**
+ @todo MARIA_HACK
+ This serves for when a test is run with --default-storage-engine=X
+ where X is not MyISAM: tests using SHOW CREATE TABLE will always fail
+ because SHOW CREATE TABLE prints X instead of MyISAM. With
+ --global-subst=X,MyISAM , such trivial differences are eliminated and
+ test may be reported as passing.
+ --global-subst is only a quick way to run a lot of existing tests
+ with Maria and find bugs; it is not good enough for reaching the main
+ trees when Maria is merged into them.
+ --global-subst should be removed.
+ */
+ uint global_subst_from_len= strlen(global_subst_from);
+ uint global_subst_to_len= strlen(global_subst_to);
+ while (replace(&fd1_result,
+ global_subst_from, global_subst_from_len,
+ global_subst_to, global_subst_to_len) == 0)
+ /* do nothing */ ;
+ /* let's compare again to see if it is ok now */
}
- if (!error && my_read(fd2, (uchar*)&buff2,
- sizeof(buff2), MYF(0)) > 0)
- {
- /* File 1 was smaller */
+
+ if (fd1_result.length != fd2_result.length)
error= RESULT_LENGTH_MISMATCH;
- }
+ else if ((memcmp(fd1_result.str, fd2_result.str, fd1_result.length)))
+ error= RESULT_CONTENT_MISMATCH;
my_close(fd2, MYF(0));
+ dynstr_free(&fd1_result);
+ dynstr_free(&fd2_result);
return error;
}
@@ -1865,7 +1909,7 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
{
my_close(fd, MYF(0));
/* Remove the temporary file */
- my_delete(temp_file_path, MYF(0));
+ my_delete(temp_file_path, MYF(MY_WME));
die("Failed to write file '%s'", temp_file_path);
}
@@ -1873,7 +1917,7 @@ int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname)
my_close(fd, MYF(0));
/* Remove the temporary file */
- my_delete(temp_file_path, MYF(0));
+ my_delete(temp_file_path, MYF(MY_WME));
DBUG_RETURN(error);
}
@@ -1917,7 +1961,7 @@ void check_result()
if (access(reject_file, W_OK) == 0)
{
/* Result file directory is writable, save reject file there */
- fn_format(reject_file, result_file_name, NULL,
+ fn_format(reject_file, result_file_name, "",
".reject", MY_REPLACE_EXT);
}
else
@@ -3090,8 +3134,8 @@ void do_remove_file(struct st_command *command)
' ');
DBUG_PRINT("info", ("removing file: %s", ds_filename.str));
- error= my_delete(ds_filename.str, MYF(0)) != 0;
- handle_command_error(command, error);
+ 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;
}
@@ -3109,7 +3153,7 @@ void do_remove_file(struct st_command *command)
void do_remove_files_wildcard(struct st_command *command)
{
- int error= 0;
+ int error= 0, sys_errno= 0;
uint i;
MY_DIR *dir_info;
FILEINFO *file;
@@ -3133,9 +3177,10 @@ void do_remove_files_wildcard(struct st_command *command)
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))))
+ if (!(dir_info= my_dir(dirname, MYF(MY_DONT_SORT | MY_WANT_STAT | MY_WME))))
{
error= 1;
+ sys_errno= my_errno;
goto end;
}
init_dynamic_string(&ds_file_to_remove, dirname, 1024, 1024);
@@ -3161,7 +3206,8 @@ void do_remove_files_wildcard(struct st_command *command)
ds_file_to_remove.str[ds_directory.length + 1]= 0;
dynstr_append(&ds_file_to_remove, file->name);
DBUG_PRINT("info", ("removing file: %s", ds_file_to_remove.str));
- error= my_delete(ds_file_to_remove.str, MYF(0)) != 0;
+ if ((error= (my_delete(ds_file_to_remove.str, MYF(MY_WME)) != 0)))
+ sys_errno= my_errno;
if (error)
break;
}
@@ -3169,7 +3215,7 @@ void do_remove_files_wildcard(struct st_command *command)
my_dirend(dir_info);
end:
- handle_command_error(command, error);
+ handle_command_error(command, error, sys_errno);
dynstr_free(&ds_directory);
dynstr_free(&ds_wild);
dynstr_free(&ds_file_to_remove);
@@ -3207,8 +3253,8 @@ void do_copy_file(struct st_command *command)
DBUG_PRINT("info", ("Copy %s to %s", ds_from_file.str, ds_to_file.str));
error= (my_copy(ds_from_file.str, ds_to_file.str,
- MYF(MY_DONT_OVERWRITE_FILE)) != 0);
- handle_command_error(command, error);
+ MYF(MY_DONT_OVERWRITE_FILE | MY_WME)) != 0);
+ handle_command_error(command, error, my_errno);
dynstr_free(&ds_from_file);
dynstr_free(&ds_to_file);
DBUG_VOID_RETURN;
@@ -3243,8 +3289,8 @@ void do_move_file(struct st_command *command)
DBUG_PRINT("info", ("Move %s to %s", ds_from_file.str, ds_to_file.str));
error= (my_rename(ds_from_file.str, ds_to_file.str,
- MYF(0)) != 0);
- handle_command_error(command, error);
+ MYF(disable_warnings ? 0 : MY_WME)) != 0);
+ handle_command_error(command, error, my_errno);
dynstr_free(&ds_from_file);
dynstr_free(&ds_to_file);
DBUG_VOID_RETURN;
@@ -3288,7 +3334,7 @@ void do_chmod_file(struct st_command *command)
err_code= chmod(ds_file.str, mode);
if (err_code < 0)
err_code= 1;
- handle_command_error(command, err_code);
+ handle_command_error(command, err_code, errno);
dynstr_free(&ds_mode);
dynstr_free(&ds_file);
DBUG_VOID_RETURN;
@@ -3321,7 +3367,7 @@ void do_file_exist(struct st_command *command)
DBUG_PRINT("info", ("Checking for existence of file: %s", ds_filename.str));
error= (access(ds_filename.str, F_OK) != 0);
- handle_command_error(command, error);
+ handle_command_error(command, error, errno);
dynstr_free(&ds_filename);
DBUG_VOID_RETURN;
}
@@ -3351,8 +3397,8 @@ void do_mkdir(struct st_command *command)
' ');
DBUG_PRINT("info", ("creating directory: %s", ds_dirname.str));
- error= my_mkdir(ds_dirname.str, 0777, MYF(0)) != 0;
- handle_command_error(command, error);
+ error= my_mkdir(ds_dirname.str, 0777, MYF(MY_WME)) != 0;
+ handle_command_error(command, error, my_errno);
dynstr_free(&ds_dirname);
DBUG_VOID_RETURN;
}
@@ -3372,7 +3418,7 @@ void do_rmdir(struct st_command *command)
int error;
static DYNAMIC_STRING ds_dirname;
const struct command_arg rmdir_args[] = {
- {"dirname", ARG_STRING, TRUE, &ds_dirname, "Directory to remove"}
+ { "dirname", ARG_STRING, TRUE, &ds_dirname, "Directory to remove" }
};
DBUG_ENTER("do_rmdir");
@@ -3382,7 +3428,7 @@ void do_rmdir(struct st_command *command)
DBUG_PRINT("info", ("removing directory: %s", ds_dirname.str));
error= rmdir(ds_dirname.str) != 0;
- handle_command_error(command, error);
+ handle_command_error(command, error, errno);
dynstr_free(&ds_dirname);
DBUG_VOID_RETURN;
}
@@ -3458,7 +3504,7 @@ static void do_list_files(struct st_command *command)
sizeof(list_files_args)/sizeof(struct command_arg), ' ');
error= get_list_files(&ds_res, &ds_dirname, &ds_wild);
- handle_command_error(command, error);
+ handle_command_error(command, error, my_errno);
dynstr_free(&ds_dirname);
dynstr_free(&ds_wild);
DBUG_VOID_RETURN;
@@ -3500,7 +3546,7 @@ static void do_list_files_write_file_command(struct st_command *command,
init_dynamic_string(&ds_content, "", 1024, 1024);
error= get_list_files(&ds_content, &ds_dirname, &ds_wild);
- handle_command_error(command, error);
+ handle_command_error(command, error, my_errno);
str_to_file2(ds_filename.str, ds_content.str, ds_content.length, append);
dynstr_free(&ds_content);
dynstr_free(&ds_filename);
@@ -3724,7 +3770,7 @@ void do_cat_file(struct st_command *command)
DBUG_PRINT("info", ("Reading from, file: %s", ds_filename.str));
error= cat_file(&ds_res, ds_filename.str);
- handle_command_error(command, error);
+ handle_command_error(command, error, my_errno);
dynstr_free(&ds_filename);
DBUG_VOID_RETURN;
}
@@ -3770,9 +3816,10 @@ void do_diff_files(struct st_command *command)
if ((error= compare_files(ds_filename.str, ds_filename2.str)) &&
match_expected_error(command, error, NULL) < 0)
{
- /* Compare of the two files failed, append them to output
- so the failure can be analyzed, but only if it was not
- expected to fail.
+ /*
+ Compare of the two files failed, append them to output
+ so the failure can be analyzed, but only if it was not
+ expected to fail.
*/
show_diff(&ds_res, ds_filename.str, ds_filename2.str);
log_file.write(&ds_res);
@@ -3782,7 +3829,7 @@ void do_diff_files(struct st_command *command)
dynstr_free(&ds_filename);
dynstr_free(&ds_filename2);
- handle_command_error(command, error);
+ handle_command_error(command, error, -1);
DBUG_VOID_RETURN;
}
@@ -3878,13 +3925,15 @@ void do_change_user(struct st_command *command)
}
if (!ds_user.length)
+ {
dynstr_set(&ds_user, mysql->user);
- if (!ds_passwd.length)
- dynstr_set(&ds_passwd, mysql->passwd);
+ if (!ds_passwd.length)
+ dynstr_set(&ds_passwd, mysql->passwd);
- if (!ds_db.length)
- dynstr_set(&ds_db, mysql->db);
+ if (!ds_db.length)
+ dynstr_set(&ds_db, mysql->db);
+ }
DBUG_PRINT("info",("connection: '%s' user: '%s' password: '%s' database: '%s'",
cur_con->name, ds_user.str, ds_passwd.str, ds_db.str));
@@ -3988,7 +4037,7 @@ void do_perl(struct st_command *command)
/* Remove the temporary file, but keep it if perl failed */
if (!error)
- my_delete(temp_file_path, MYF(0));
+ my_delete(temp_file_path, MYF(MY_WME));
/* Check for error code that indicates perl could not be started */
int exstat= WEXITSTATUS(error);
@@ -4001,7 +4050,7 @@ void do_perl(struct st_command *command)
abort_not_supported_test("perl not found in path");
#endif
else
- handle_command_error(command, exstat);
+ handle_command_error(command, exstat, my_errno);
}
dynstr_free(&ds_delimiter);
DBUG_VOID_RETURN;
@@ -4875,11 +4924,11 @@ char *get_string(char **to_ptr, char **from_ptr,
}
-void set_reconnect(MYSQL* mysql, int val)
+void set_reconnect(MYSQL* mysql, my_bool val)
{
my_bool reconnect= val;
DBUG_ENTER("set_reconnect");
- DBUG_PRINT("info", ("val: %d", val));
+ DBUG_PRINT("info", ("val: %d", (int) val));
#if MYSQL_VERSION_ID < 50000
mysql->reconnect= reconnect;
#else
@@ -4949,7 +4998,7 @@ void select_connection(struct st_command *command)
void do_close_connection(struct st_command *command)
{
- DBUG_ENTER("close_connection");
+ DBUG_ENTER("do_close_connection");
struct st_connection *con;
static DYNAMIC_STRING ds_connection;
@@ -5022,6 +5071,7 @@ void do_close_connection(struct st_command *command)
dynstr_append_mem(ds, ";\n", 2);
}
+ dynstr_free(&ds_connection);
DBUG_VOID_RETURN;
}
@@ -5314,7 +5364,8 @@ void do_connect(struct st_command *command)
con_options= ds_options.str;
while (*con_options)
{
- char* end;
+ size_t length;
+ char *end;
/* Step past any spaces in beginning of option*/
while (*con_options && my_isspace(charset_info, *con_options))
con_options++;
@@ -5322,13 +5373,14 @@ void do_connect(struct st_command *command)
end= con_options;
while (*end && !my_isspace(charset_info, *end))
end++;
- if (!strncmp(con_options, "SSL", 3))
+ length= (size_t) (end - con_options);
+ if (length == 3 && !strncmp(con_options, "SSL", 3))
con_ssl= 1;
- else if (!strncmp(con_options, "COMPRESS", 8))
+ else if (length == 8 && !strncmp(con_options, "COMPRESS", 8))
con_compress= 1;
- else if (!strncmp(con_options, "PIPE", 4))
+ else if (length == 4 && !strncmp(con_options, "PIPE", 4))
con_pipe= 1;
- else if (!strncmp(con_options, "SHM", 3))
+ else if (length == 3 && !strncmp(con_options, "SHM", 3))
con_shm= 1;
else
die("Illegal option to connect: %.*s",
@@ -5368,6 +5420,9 @@ void do_connect(struct st_command *command)
if (opt_charsets_dir)
mysql_options(&con_slot->mysql, MYSQL_SET_CHARSET_DIR,
opt_charsets_dir);
+ if (opt_connect_timeout >= 0)
+ mysql_options(&con_slot->mysql, MYSQL_OPT_CONNECT_TIMEOUT,
+ &opt_connect_timeout);
#if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY)
if (opt_use_ssl || con_ssl)
@@ -5402,14 +5457,13 @@ void do_connect(struct st_command *command)
mysql_options(&con_slot->mysql, MYSQL_SHARED_MEMORY_BASE_NAME, ds_shm.str);
mysql_options(&con_slot->mysql, MYSQL_OPT_PROTOCOL, &protocol);
}
- else if(shared_memory_base_name)
+ else if (shared_memory_base_name)
{
mysql_options(&con_slot->mysql, MYSQL_SHARED_MEMORY_BASE_NAME,
- shared_memory_base_name);
+ shared_memory_base_name);
}
#endif
-
/* Use default db name */
if (ds_database.length == 0)
dynstr_set(&ds_database, opt_db);
@@ -6195,6 +6249,9 @@ static struct my_option my_long_options[] =
GET_INT, REQUIRED_ARG, 0, 0, 10000, 0, 0, 0},
{"test-file", 'x', "Read test from/in this file (default stdin).",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"connect-timeout", OPT_MY_CONNECT_TIMEOUT, "Client connection timeout",
+ (uchar**) &opt_connect_timeout, (uchar**) &opt_connect_timeout, 0,
+ GET_INT, REQUIRED_ARG, -1, -1, 0, 0, 0, 0},
{"timer-file", 'm', "File where the timing in microseconds is stored.",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"tmpdir", 't', "Temporary directory where sockets are put.",
@@ -6406,6 +6463,15 @@ int parse_args(int argc, char **argv)
if (debug_check_flag)
my_end_arg= MY_CHECK_ERROR;
+ if (global_subst != NULL)
+ {
+ char *comma= strstr(global_subst, ",");
+ if (comma == NULL)
+ die("wrong --global-subst, must be X,Y");
+ memcpy(global_subst_from, global_subst, (comma-global_subst));
+ global_subst_from[comma-global_subst]= 0;
+ memcpy(global_subst_to, comma+1, strlen(comma));
+ }
if (!record)
{
@@ -7345,8 +7411,17 @@ void run_query_stmt(MYSQL *mysql, struct st_command *command,
mysql_free_result(res); /* Free normal result set with meta data */
- /* Clear prepare warnings */
- dynstr_set(&ds_prepare_warnings, NULL);
+ /*
+ Normally, if there is a result set, we do not show warnings from the
+ prepare phase. This is because some warnings are generated both during
+ prepare and execute; this would generate different warning output
+ between normal and ps-protocol test runs.
+
+ The --enable_prepare_warnings command can be used to change this so
+ that warnings from both the prepare and execute phase are shown.
+ */
+ if (!disable_warnings && !prepare_warnings_enabled)
+ dynstr_set(&ds_prepare_warnings, NULL);
}
else
{
@@ -7359,7 +7434,6 @@ void run_query_stmt(MYSQL *mysql, struct st_command *command,
Fetch info before fetching warnings, since it will be reset
otherwise.
*/
-
if (!disable_info)
append_info(ds, mysql_stmt_affected_rows(stmt), mysql_info(mysql));
@@ -7394,14 +7468,6 @@ end:
dynstr_free(&ds_execute_warnings);
}
-
- /* Close the statement if - no reconnect, need new prepare */
- if (mysql->reconnect)
- {
- mysql_stmt_close(stmt);
- cur_con->stmt= NULL;
- }
-
/*
We save the return code (mysql_stmt_errno(stmt)) from the last call sent
to the server into the mysqltest builtin variable $mysql_errno. This
@@ -7410,6 +7476,13 @@ end:
var_set_errno(mysql_stmt_errno(stmt));
+ /* Close the statement if reconnect, need new prepare */
+ if (mysql->reconnect)
+ {
+ mysql_stmt_close(stmt);
+ cur_con->stmt= NULL;
+ }
+
DBUG_VOID_RETURN;
}
@@ -7571,7 +7644,6 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags)
}
dynstr_free(&query_str);
-
}
if (sp_protocol_enabled &&
@@ -7856,7 +7928,7 @@ void mark_progress(struct st_command* command __attribute__((unused)),
die("Out of memory");
/* Milliseconds since start */
- end= longlong2str(timer, buf, 10);
+ end= longlong10_to_str(timer, buf, 10);
dynstr_append_mem(&ds_progress, buf, (int)(end-buf));
dynstr_append_mem(&ds_progress, "\t", 1);
@@ -7984,7 +8056,6 @@ static void init_signal_handling(void)
#endif
sigaction(SIGILL, &sa, NULL);
sigaction(SIGFPE, &sa, NULL);
-
DBUG_VOID_RETURN;
}
@@ -7996,6 +8067,7 @@ int main(int argc, char **argv)
my_bool q_send_flag= 0, abort_flag= 0;
uint command_executed= 0, last_command_executed= 0;
char save_file[FN_REFLEN];
+ bool empty_result= FALSE;
MY_INIT(argv[0]);
save_file[0]= 0;
@@ -8171,6 +8243,7 @@ int main(int argc, char **argv)
verbose_msg("Start processing test commands from '%s' ...", cur_file->file_name);
while (!read_command(&command) && !abort_flag)
{
+ my_bool ok_to_do;
int current_line_inc = 1, processed = 0;
if (command->type == Q_UNKNOWN || command->type == Q_COMMENT_WITH_COMMAND)
get_command_type(command);
@@ -8188,7 +8261,7 @@ int main(int argc, char **argv)
abort_on_error);
/* delimiter needs to be executed so we can continue to parse */
- my_bool ok_to_do= cur_block->ok || command->type == Q_DELIMITER;
+ ok_to_do= cur_block->ok || command->type == Q_DELIMITER;
/*
Some commands need to be "done" the first time if they may get
re-iterated over in a true context. This can only happen if there's
@@ -8235,6 +8308,8 @@ int main(int argc, char **argv)
case Q_DISABLE_CONNECT_LOG: disable_connect_log=1; break;
case Q_ENABLE_WARNINGS: disable_warnings=0; break;
case Q_DISABLE_WARNINGS: disable_warnings=1; break;
+ case Q_ENABLE_PREPARE_WARNINGS: prepare_warnings_enabled=1; break;
+ case Q_DISABLE_PREPARE_WARNINGS: prepare_warnings_enabled=0; break;
case Q_ENABLE_INFO: disable_info=0; break;
case Q_DISABLE_INFO: disable_info=1; break;
case Q_ENABLE_METADATA: display_metadata=1; break;
@@ -8427,12 +8502,12 @@ int main(int argc, char **argv)
dynstr_append(&ds_res, "\n");
break;
case Q_PING:
- handle_command_error(command, mysql_ping(&cur_con->mysql));
+ handle_command_error(command, mysql_ping(&cur_con->mysql), -1);
break;
case Q_SEND_SHUTDOWN:
handle_command_error(command,
mysql_shutdown(&cur_con->mysql,
- SHUTDOWN_DEFAULT));
+ SHUTDOWN_DEFAULT), -1);
break;
case Q_SHUTDOWN_SERVER:
do_shutdown_server(command);
@@ -8493,7 +8568,10 @@ int main(int argc, char **argv)
abort_flag= 1;
break;
case Q_SKIP:
- abort_not_supported_test("%s", command->first_argument);
+ /* Eval the query, thus replacing all environment variables */
+ dynstr_set(&ds_res, 0);
+ do_eval(&ds_res, command->first_argument, command->end, FALSE);
+ abort_not_supported_test("%s",ds_res.str);
break;
case Q_RESULT:
@@ -8561,8 +8639,6 @@ int main(int argc, char **argv)
if (parsing_disabled)
die("Test ended with parsing disabled");
- my_bool empty_result= FALSE;
-
/*
The whole test has been executed _sucessfully_.
Time to compare result or save it to record file.
@@ -8643,7 +8719,7 @@ void timer_output(void)
{
char buf[32], *end;
ulonglong timer= timer_now() - timer_start;
- end= longlong2str(timer, buf, 10);
+ end= longlong10_to_str(timer, buf, 10);
str_to_file(timer_file,buf, (int) (end-buf));
/* Timer has been written to the file, don't use it anymore */
timer_file= 0;
@@ -8802,15 +8878,15 @@ void free_replace()
typedef struct st_replace {
- my_bool found;
+ int found;
struct st_replace *next[256];
} REPLACE;
typedef struct st_replace_found {
- my_bool found;
- char *replace_string;
+ int found;
uint to_offset;
int from_offset;
+ char *replace_string;
} REPLACE_STRING;
@@ -8842,7 +8918,7 @@ void replace_strings_append(REPLACE *rep, DYNAMIC_STRING* ds,
}
/* Found a string that needs to be replaced */
- DBUG_PRINT("info", ("found: %d, to_offset: %d, from_offset: %d, string: %s",
+ DBUG_PRINT("info", ("found: %d, to_offset: %u, from_offset: %d, string: %s",
rep_str->found, rep_str->to_offset,
rep_str->from_offset, rep_str->replace_string));
diff --git a/client/sql_string.h b/client/sql_string.h
index bafc287c73e..b51e6b07e01 100644
--- a/client/sql_string.h
+++ b/client/sql_string.h
@@ -18,6 +18,9 @@
/* This file is originally from the mysql distribution. Coded by monty */
+#ifndef CLIENT_SQL_STRING_H
+#define CLIENT_SQL_STRING_H
+
#ifdef USE_PRAGMA_INTERFACE
#pragma interface /* gcc class implementation */
#endif