summaryrefslogtreecommitdiff
path: root/client
diff options
context:
space:
mode:
Diffstat (limited to 'client')
-rw-r--r--client/CMakeLists.txt4
-rw-r--r--client/Makefile.am6
-rw-r--r--client/client_priv.h11
-rw-r--r--client/echo.c44
-rw-r--r--client/mysql.cc7
-rw-r--r--client/mysql_upgrade.c114
-rw-r--r--client/mysqladmin.cc69
-rw-r--r--client/mysqlbinlog.cc49
-rw-r--r--client/mysqlcheck.c13
-rw-r--r--client/mysqldump.c608
-rw-r--r--client/mysqlslap.c1296
-rw-r--r--client/mysqltest.c415
12 files changed, 1917 insertions, 719 deletions
diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt
index a8319f51333..ea9e7547354 100644
--- a/client/CMakeLists.txt
+++ b/client/CMakeLists.txt
@@ -95,4 +95,8 @@ ADD_EXECUTABLE(mysqladmin mysqladmin.cc)
TARGET_LINK_LIBRARIES(mysqladmin mysqlclient mysys dbug yassl taocrypt zlib wsock32)
ADD_EXECUTABLE(mysqlslap mysqlslap.c)
+SET_SOURCE_FILES_PROPERTIES(mysqlslap.c PROPERTIES COMPILE_FLAGS "-DTHREADS")
TARGET_LINK_LIBRARIES(mysqlslap mysqlclient mysys yassl taocrypt zlib wsock32 dbug)
+
+ADD_EXECUTABLE(echo echo.c)
+
diff --git a/client/Makefile.am b/client/Makefile.am
index 747b27e9aa0..e22080e3dd8 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -34,7 +34,7 @@ LDADD= @CLIENT_EXTRA_LDFLAGS@ $(CLIENT_THREAD_LIBS) \
noinst_HEADERS = sql_string.h completion_hash.h my_readline.h \
client_priv.h
-EXTRA_DIST = get_password.c CMakeLists.txt
+EXTRA_DIST = get_password.c CMakeLists.txt echo.c
bin_PROGRAMS = mysql \
mysqladmin \
@@ -76,6 +76,7 @@ mysqlimport_LDADD = $(CXXLDFLAGS) $(CLIENT_THREAD_LIBS) \
mysqlshow_SOURCES= mysqlshow.c
mysqlslap_SOURCES= mysqlslap.c
+mysqlslap_CFLAGS= -DTHREAD -UUNDEF_THREADS_HACK
mysqlslap_LDADD = $(CXXLDFLAGS) $(CLIENT_THREAD_LIBS) \
@CLIENT_EXTRA_LDFLAGS@ \
$(LIBMYSQLCLIENT_LA) \
@@ -94,7 +95,8 @@ DEFS = -DUNDEF_THREADS_HACK \
-DDEFAULT_MYSQL_HOME="\"$(prefix)\"" \
-DDATADIR="\"$(localstatedir)\""
-sql_src=log_event.h mysql_priv.h log_event.cc my_decimal.h my_decimal.cc
+sql_src=log_event.h mysql_priv.h rpl_constants.h \
+ log_event.cc my_decimal.h my_decimal.cc
strings_src=decimal.c
link_sources:
diff --git a/client/client_priv.h b/client/client_priv.h
index 646619f62b1..9a678eb7d2a 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -49,7 +49,6 @@ enum options_client
OPT_TRIGGERS,
OPT_MYSQL_ONLY_PRINT,
OPT_MYSQL_LOCK_DIRECTORY,
- OPT_MYSQL_SLAP_SLAVE,
OPT_USE_THREADS,
OPT_IMPORT_USE_THREADS,
OPT_MYSQL_NUMBER_OF_QUERY,
@@ -58,7 +57,15 @@ enum options_client
OPT_TZ_UTC, OPT_AUTO_CLOSE, OPT_CREATE_SLAP_SCHEMA,
OPT_SLAP_CSV, OPT_SLAP_CREATE_STRING,
OPT_SLAP_AUTO_GENERATE_SQL_LOAD_TYPE, OPT_SLAP_AUTO_GENERATE_WRITE_NUM,
+ OPT_SLAP_AUTO_GENERATE_ADD_AUTO,
+ OPT_SLAP_AUTO_GENERATE_GUID_PRIMARY,
+ OPT_SLAP_AUTO_GENERATE_EXECUTE_QUERIES,
+ OPT_SLAP_AUTO_GENERATE_SECONDARY_INDEXES,
+ OPT_SLAP_AUTO_GENERATE_UNIQUE_WRITE_NUM,
+ OPT_SLAP_AUTO_GENERATE_UNIQUE_QUERY_NUM,
+ OPT_SLAP_PRE_QUERY,
+ OPT_SLAP_POST_QUERY,
OPT_MYSQL_REPLACE_INTO, OPT_BASE64_OUTPUT, OPT_SERVER_ID,
OPT_FIX_TABLE_NAMES, OPT_FIX_DB_NAMES, OPT_SSL_VERIFY_SERVER_CERT,
- OPT_DEBUG_INFO, OPT_COLUMN_TYPES
+ OPT_DEBUG_INFO, OPT_COLUMN_TYPES, OPT_WRITE_BINLOG
};
diff --git a/client/echo.c b/client/echo.c
new file mode 100644
index 00000000000..e3d22edb3ae
--- /dev/null
+++ b/client/echo.c
@@ -0,0 +1,44 @@
+/* Copyright (C) 2000 MySQL 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
+ the Free Software Foundation; version 2 of the License.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+/*
+ echo is a replacement for the "echo" command builtin to cmd.exe
+ on Windows, to get a Unix eqvivalent behaviour when running commands
+ like:
+ $> echo "hello" | mysql
+
+ The windows "echo" would have sent "hello" to mysql while
+ Unix echo will send hello without the enclosing hyphens
+
+ This is a very advanced high tech program so take care when
+ you change it and remember to valgrind it before production
+ use.
+
+*/
+
+#include <stdio.h>
+
+int main(int argc, char **argv)
+{
+ int i;
+ for (i= 1; i < argc; i++)
+ {
+ fprintf(stdout, "%s", argv[i]);
+ if (i < argc - 1)
+ fprintf(stdout, " ");
+ }
+ fprintf(stdout, "\n");
+ return 0;
+}
diff --git a/client/mysql.cc b/client/mysql.cc
index 581f13adabb..981e0ce5f16 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -442,10 +442,6 @@ int main(int argc,char *argv[])
signal(SIGINT, handle_sigint); // Catch SIGINT to clean up
signal(SIGQUIT, mysql_end); // Catch SIGQUIT to clean up
- /*
- Run in interactive mode like the ingres/postgres monitor
- */
-
put_info("Welcome to the MySQL monitor. Commands end with ; or \\g.",
INFO_INFO);
sprintf((char*) glob_buffer.ptr(),
@@ -2521,7 +2517,8 @@ print_table_data_xml(MYSQL_RES *result)
tee_fputs("<?xml version=\"1.0\"?>\n\n<resultset statement=\"", PAGER);
xmlencode_print(glob_buffer.ptr(), (int)strlen(glob_buffer.ptr()));
- tee_fputs("\">", PAGER);
+ tee_fputs("\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">",
+ PAGER);
fields = mysql_fetch_fields(result);
while ((cur = mysql_fetch_row(result)))
diff --git a/client/mysql_upgrade.c b/client/mysql_upgrade.c
index 6d8337abb4d..e6870c23129 100644
--- a/client/mysql_upgrade.c
+++ b/client/mysql_upgrade.c
@@ -54,6 +54,8 @@ static char *default_dbug_option= (char*) "d:t:O,/tmp/mysql_upgrade.trace";
#endif
static my_bool info_flag= 0, tty_password= 0;
+static char **defaults_argv;
+
static struct my_option my_long_options[]=
{
{"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG,
@@ -282,6 +284,10 @@ static int create_defaults_file(const char *path, const char *forced_path)
DYNAMIC_STRING buf;
extra_default_t *d;
+ DBUG_ENTER("create_defaults_file");
+ DBUG_PRINT("enter", ("path: %s, forced_path: %s", path, forced_path));
+
+ /* Delete any previous defaults file generated by mysql_upgrade */
my_delete(path, MYF(0));
defaults_file= my_open(path, O_BINARY | O_CREAT | O_WRONLY | O_EXCL,
@@ -298,6 +304,7 @@ static int create_defaults_file(const char *path, const char *forced_path)
goto error;
}
+ /* Copy forced_path file into the defaults_file being generated */
if (forced_path)
{
forced_file= my_open(forced_path, O_RDONLY, MYF(MY_FAE | MY_WME));
@@ -306,6 +313,7 @@ static int create_defaults_file(const char *path, const char *forced_path)
ret= 1;
goto error;
}
+ DBUG_PRINT("info", ("Copying from %s to %s", forced_path, path));
do
{
cnt= my_read(forced_file, buf.str, buf.max_length, MYF(MY_WME));
@@ -316,10 +324,12 @@ static int create_defaults_file(const char *path, const char *forced_path)
my_close(forced_file, MYF(0));
goto error;
}
+ DBUG_PRINT("info", ("%s", buf.str));
} while (cnt == buf.max_length);
my_close(forced_file, MYF(0));
}
-
+
+ /* Write all extra_default options into the [client] section */
dynstr_set(&buf, "\n[client]");
if (opt_password)
{
@@ -330,6 +340,7 @@ static int create_defaults_file(const char *path, const char *forced_path)
goto error;
}
}
+ DBUG_PRINT("info", ("Writing extra_defaults to file"));
while (extra_defaults)
{
int len;
@@ -338,6 +349,7 @@ static int create_defaults_file(const char *path, const char *forced_path)
len= d->n_len + d->v_len + 1;
if (buf.length + len >= buf.max_length) /* to avoid realloc() */
{
+
if (my_write(defaults_file, buf.str, buf.length, MYF(MY_FNABP | MY_WME)))
{
ret= 1;
@@ -345,15 +357,16 @@ static int create_defaults_file(const char *path, const char *forced_path)
}
dynstr_set(&buf, NULL);
}
- if (dynstr_append_mem(&buf, "\n", 1)
- || dynstr_append_mem(&buf, d->name, d->n_len)
- || (d->v_len && (dynstr_append_mem(&buf, "=", 1)
- || dynstr_append_mem(&buf, d->value, d->v_len))))
+ if (dynstr_append_mem(&buf, "\n", 1) ||
+ dynstr_append_mem(&buf, d->name, d->n_len) ||
+ (d->v_len && (dynstr_append_mem(&buf, "=", 1) ||
+ dynstr_append_mem(&buf, d->value, d->v_len))))
{
ret= 1;
goto error;
}
- my_delete((gptr)d, MYF(0));
+ DBUG_PRINT("info", ("%s", buf.str));
+ my_free((gptr)d, MYF(0));
list_pop(extra_defaults); /* pop off the head */
}
if (my_write(defaults_file, buf.str, buf.length, MYF(MY_FNABP | MY_WME)))
@@ -373,7 +386,7 @@ error:
my_delete(path, MYF(0));
out:
- return ret;
+ DBUG_RETURN(ret);
}
@@ -450,12 +463,8 @@ int main(int argc, char **argv)
char *forced_defaults_file;
char *forced_extra_defaults;
char *local_defaults_group_suffix;
- const char *script_line;
- char *upgrade_defaults_path= 0;
- char *defaults_to_use= NULL;
- int upgrade_defaults_created= 0;
-
- char path[FN_REFLEN];
+
+ char path[FN_REFLEN], upgrade_defaults_path[FN_REFLEN];
DYNAMIC_STRING cmdline;
MY_INIT(argv[0]);
@@ -469,6 +478,7 @@ int main(int argc, char **argv)
&local_defaults_group_suffix);
load_defaults("my", load_default_groups, &argc, &argv);
+ defaults_argv= argv;
/*
Must init_dynamic_string before handle_options because string is freed
@@ -516,25 +526,19 @@ int main(int argc, char **argv)
goto error;
}
- /*
- Create the modified defaults file to be used by mysqlcheck
- and mysql tools
+ /*
+ Create the modified defaults file to be used by mysqlcheck
+ and mysql command line client
*/
- fn_format(path, UPGRADE_DEFAULTS_NAME, datadir, "", MYF(0));
- upgrade_defaults_path= my_strdup(path, MYF(0));
-
- if (extra_defaults)
- {
- ret= create_defaults_file(upgrade_defaults_path, forced_extra_defaults);
- if (ret)
- goto error;
-
- defaults_to_use= upgrade_defaults_path;
- upgrade_defaults_created= 1;
- }
- else
- defaults_to_use= forced_extra_defaults;
+ fn_format(upgrade_defaults_path, UPGRADE_DEFAULTS_NAME, datadir, "", MYF(0));
+ create_defaults_file(upgrade_defaults_path, forced_extra_defaults);
+
+ /*
+ Read the mysql_upgrade_info file to check if mysql_upgrade
+ already has been done
+ Maybe this could be done a little earlier?
+ */
if (!find_file(MYSQL_UPGRADE_INFO_NAME, datadir, MY_SEARCH_SELF,
path, sizeof(path), NULL, NullS)
&& !opt_force)
@@ -553,7 +557,9 @@ int main(int argc, char **argv)
goto fix_priv_tables;
}
}
-
+
+
+ /* Find mysqlcheck */
if (find_file(mysqlcheck_name, basedir, MYF(0), path, sizeof(path),
"bin", EXTRA_CLIENT_PATHS, NullS))
{
@@ -575,13 +581,13 @@ int main(int argc, char **argv)
dynstr_append_os_quoted(&cmdline, path, NullS);
}
- if (defaults_to_use)
- {
- dynstr_append(&cmdline, " ");
- dynstr_append_os_quoted(&cmdline, "--defaults-extra-file=",
- defaults_to_use, NullS);
- }
-
+ /*
+ All settings have been written to the "upgrade_defaults_path"
+ instruct mysqlcheck to only read options from that file
+ */
+ dynstr_append(&cmdline, " ");
+ dynstr_append_os_quoted(&cmdline, "--defaults-file=",
+ upgrade_defaults_path, NullS);
dynstr_append(&cmdline, " ");
dynstr_append_os_quoted(&cmdline, "--check-upgrade", NullS);
dynstr_append(&cmdline, " ");
@@ -594,9 +600,10 @@ int main(int argc, char **argv)
dynstr_append(&cmdline, "\"");
#endif /* __WIN__ */
+ /* Execute mysqlcheck */
if (opt_verbose)
printf("Running %s\n", cmdline.str);
-
+ DBUG_PRINT("info", ("Running: %s", cmdline.str));
ret= system(cmdline.str);
if (ret)
{
@@ -610,6 +617,7 @@ int main(int argc, char **argv)
goto error;
fix_priv_tables:
+ /* Find mysql */
if (find_file(mysql_name, basedir, MYF(0), path, sizeof(path),
"bin", EXTRA_CLIENT_PATHS, NullS))
{
@@ -631,6 +639,7 @@ fix_priv_tables:
dynstr_append_os_quoted(&cmdline, path, NullS);
}
+ /* Find mysql_fix_privililege_tables.sql */
if (find_file(MYSQL_FIX_PRIV_TABLES_NAME, basedir, MYF(0),
path, sizeof(path),
"support_files", "share", "share/mysql", "scripts",
@@ -646,15 +655,14 @@ fix_priv_tables:
" where MySQL is installed");
goto error;
}
- else
- script_line= my_strdup(path, MYF(0));
- if (defaults_to_use)
- {
- dynstr_append(&cmdline, " ");
- dynstr_append_os_quoted(&cmdline, "--defaults-extra-file=",
- defaults_to_use, NullS);
- }
+ /*
+ All settings have been written to the "upgrade_defaults_path",
+ instruct mysql to only read options from that file
+ */
+ dynstr_append(&cmdline, " ");
+ dynstr_append_os_quoted(&cmdline, "--defaults-file=",
+ upgrade_defaults_path, NullS);
dynstr_append(&cmdline, " ");
dynstr_append_os_quoted(&cmdline, "--force", NullS);
dynstr_append(&cmdline, " ");
@@ -666,14 +674,15 @@ fix_priv_tables:
dynstr_append(&cmdline, " ");
dynstr_append_os_quoted(&cmdline, "--database=mysql", NullS);
dynstr_append(&cmdline, " < ");
- dynstr_append_os_quoted(&cmdline, script_line, NullS);
+ dynstr_append_os_quoted(&cmdline, path, NullS);
#ifdef __WIN__
dynstr_append(&cmdline, "\"");
#endif /* __WIN__ */
+ /* Execute "mysql --force < mysql_fix_privilege_tables.sql" */
if (opt_verbose)
printf("Running %s\n", cmdline.str);
-
+ DBUG_PRINT("info", ("Running: %s", cmdline.str));
ret= system(cmdline.str);
if (ret)
fprintf(stderr, "Error executing '%s'\n", cmdline.str);
@@ -681,9 +690,10 @@ fix_priv_tables:
error:
dynstr_free(&cmdline);
- if (upgrade_defaults_created)
- my_delete(upgrade_defaults_path, MYF(0));
-
+ /* Delete the generated defaults file */
+ my_delete(upgrade_defaults_path, MYF(0));
+
+ free_defaults(defaults_argv);
my_end(info_flag ? MY_CHECK_ERROR : 0);
return ret;
}
diff --git a/client/mysqladmin.cc b/client/mysqladmin.cc
index ccfff4d7a03..cb704d716cc 100644
--- a/client/mysqladmin.cc
+++ b/client/mysqladmin.cc
@@ -40,7 +40,7 @@ ulonglong last_values[MAX_MYSQL_VAR];
static int interval=0;
static my_bool option_force=0,interrupted=0,new_line=0,
opt_compress=0, opt_relative=0, opt_verbose=0, opt_vertical=0,
- tty_password= 0, info_flag= 0;
+ tty_password= 0, info_flag= 0, opt_nobeep;
static uint tcp_port = 0, option_wait = 0, option_silent=0, nr_iterations,
opt_count_iterations= 0;
static ulong opt_connect_timeout, opt_shutdown_timeout;
@@ -54,6 +54,7 @@ static char *opt_ndb_connectstring=0;
static char *shared_memory_base_name=0;
#endif
static uint opt_protocol=0;
+static myf error_flags; /* flags to pass to my_printf_error, like ME_BELL */
/*
When using extended-status relatively, ex_val_max_len is the estimated
@@ -154,6 +155,8 @@ static struct my_option my_long_options[] =
NO_ARG, 0, 0, 0, 0, 0, 0},
{"host", 'h', "Connect to host.", (gptr*) &host, (gptr*) &host, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"no-beep", 'b', "Turn off beep on error.", (gptr*) &opt_nobeep,
+ (gptr*) &opt_nobeep, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"password", 'p',
"Password to use when connecting to server. If password is not given it's asked from the tty.",
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
@@ -352,6 +355,8 @@ int main(int argc,char *argv[])
#endif
if (default_charset)
mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
+ error_flags= (myf)(opt_nobeep ? 0 : ME_BELL);
+
if (sql_connect(&mysql, option_wait))
{
unsigned int err= mysql_errno(&mysql);
@@ -450,7 +455,7 @@ static my_bool sql_connect(MYSQL *mysql, uint wait)
if (!host)
host= (char*) LOCAL_HOST;
my_printf_error(0,"connect to server at '%s' failed\nerror: '%s'",
- MYF(ME_BELL), host, mysql_error(mysql));
+ error_flags, host, mysql_error(mysql));
if (mysql_errno(mysql) == CR_CONNECTION_ERROR)
{
fprintf(stderr,
@@ -525,14 +530,14 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
char buff[FN_REFLEN+20];
if (argc < 2)
{
- my_printf_error(0,"Too few arguments to create",MYF(ME_BELL));
+ my_printf_error(0, "Too few arguments to create", error_flags);
return 1;
}
sprintf(buff,"create database `%.*s`",FN_REFLEN,argv[1]);
if (mysql_query(mysql,buff))
{
my_printf_error(0,"CREATE DATABASE failed; error: '%-.200s'",
- MYF(ME_BELL), mysql_error(mysql));
+ error_flags, mysql_error(mysql));
return -1;
}
argc--; argv++;
@@ -542,7 +547,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
if (argc < 2)
{
- my_printf_error(0,"Too few arguments to drop",MYF(ME_BELL));
+ my_printf_error(0, "Too few arguments to drop", error_flags);
return 1;
}
if (drop_db(mysql,argv[1]))
@@ -567,7 +572,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
if (mysql_shutdown(mysql, SHUTDOWN_DEFAULT))
{
- my_printf_error(0,"shutdown failed; error: '%s'",MYF(ME_BELL),
+ my_printf_error(0, "shutdown failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
@@ -588,7 +593,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
case ADMIN_RELOAD:
if (mysql_query(mysql,"flush privileges"))
{
- my_printf_error(0,"reload failed; error: '%s'",MYF(ME_BELL),
+ my_printf_error(0, "reload failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
@@ -599,7 +604,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
REFRESH_READ_LOCK | REFRESH_SLAVE |
REFRESH_MASTER)))
{
- my_printf_error(0,"refresh failed; error: '%s'",MYF(ME_BELL),
+ my_printf_error(0, "refresh failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
@@ -607,7 +612,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
case ADMIN_FLUSH_THREADS:
if (mysql_refresh(mysql,(uint) REFRESH_THREADS))
{
- my_printf_error(0,"refresh failed; error: '%s'",MYF(ME_BELL),
+ my_printf_error(0, "refresh failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
@@ -651,7 +656,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
"show processlist")) ||
!(result = mysql_store_result(mysql)))
{
- my_printf_error(0,"process list failed; error: '%s'",MYF(ME_BELL),
+ my_printf_error(0, "process list failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
@@ -674,7 +679,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
char *pos;
if (argc < 2)
{
- my_printf_error(0,"Too few arguments to 'kill'",MYF(ME_BELL));
+ my_printf_error(0, "Too few arguments to 'kill'", error_flags);
return 1;
}
pos=argv[1];
@@ -682,7 +687,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
if (mysql_kill(mysql,(ulong) atol(pos)))
{
- my_printf_error(0,"kill failed on %ld; error: '%s'",MYF(ME_BELL),
+ my_printf_error(0, "kill failed on %ld; error: '%s'", error_flags,
atol(pos), mysql_error(mysql));
error=1;
}
@@ -698,7 +703,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
case ADMIN_DEBUG:
if (mysql_dump_debug_info(mysql))
{
- my_printf_error(0,"debug failed; error: '%s'",MYF(ME_BELL),
+ my_printf_error(0, "debug failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
@@ -712,7 +717,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
if (mysql_query(mysql,"show /*!40003 GLOBAL */ variables") ||
!(res=mysql_store_result(mysql)))
{
- my_printf_error(0,"unable to show variables; error: '%s'",MYF(ME_BELL),
+ my_printf_error(0, "unable to show variables; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
@@ -734,7 +739,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
if (mysql_query(mysql, "show /*!50002 GLOBAL */ status") ||
!(res = mysql_store_result(mysql)))
{
- my_printf_error(0, "unable to show status; error: '%s'", MYF(ME_BELL),
+ my_printf_error(0, "unable to show status; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
@@ -784,7 +789,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
if (mysql_refresh(mysql,REFRESH_LOG))
{
- my_printf_error(0,"refresh failed; error: '%s'",MYF(ME_BELL),
+ my_printf_error(0, "refresh failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
@@ -794,7 +799,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'",MYF(ME_BELL),
+ my_printf_error(0, "refresh failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
@@ -804,7 +809,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'",MYF(ME_BELL),
+ my_printf_error(0, "refresh failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
@@ -814,7 +819,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
if (mysql_query(mysql,"flush status"))
{
- my_printf_error(0,"refresh failed; error: '%s'",MYF(ME_BELL),
+ my_printf_error(0, "refresh failed; error: '%s'", error_flags,
mysql_error(mysql));
return -1;
}
@@ -831,7 +836,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
if (argc < 2)
{
- my_printf_error(0,"Too few arguments to change password",MYF(ME_BELL));
+ my_printf_error(0, "Too few arguments to change password", error_flags);
return 1;
}
if (argv[1][0])
@@ -854,7 +859,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
if (mysql_query(mysql, "SHOW VARIABLES LIKE 'old_passwords'"))
{
my_printf_error(0, "Could not determine old_passwords setting from server; error: '%s'",
- MYF(ME_BELL),mysql_error(mysql));
+ error_flags, mysql_error(mysql));
return -1;
}
else
@@ -865,7 +870,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
my_printf_error(0,
"Could not get old_passwords setting from "
"server; error: '%s'",
- MYF(ME_BELL),mysql_error(mysql));
+ error_flags, mysql_error(mysql));
return -1;
}
if (!mysql_num_rows(res))
@@ -890,7 +895,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
if (mysql_query(mysql,"set sql_log_off=1"))
{
my_printf_error(0, "Can't turn off logging; error: '%s'",
- MYF(ME_BELL),mysql_error(mysql));
+ error_flags, mysql_error(mysql));
return -1;
}
if (mysql_query(mysql,buff))
@@ -898,7 +903,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
if (mysql_errno(mysql)!=1290)
{
my_printf_error(0,"unable to change password; error: '%s'",
- MYF(ME_BELL),mysql_error(mysql));
+ error_flags, mysql_error(mysql));
return -1;
}
else
@@ -912,7 +917,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
" with grant tables disabled (was started with"
" --skip-grant-tables).\n"
"Use: \"mysqladmin flush-privileges password '*'\""
- " instead", MYF(ME_BELL));
+ " instead", error_flags);
return -1;
}
}
@@ -923,7 +928,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
case ADMIN_START_SLAVE:
if (mysql_query(mysql, "START SLAVE"))
{
- my_printf_error(0, "Error starting slave: %s", MYF(ME_BELL),
+ my_printf_error(0, "Error starting slave: %s", error_flags,
mysql_error(mysql));
return -1;
}
@@ -933,7 +938,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
case ADMIN_STOP_SLAVE:
if (mysql_query(mysql, "STOP SLAVE"))
{
- my_printf_error(0, "Error stopping slave: %s", MYF(ME_BELL),
+ my_printf_error(0, "Error stopping slave: %s", error_flags,
mysql_error(mysql));
return -1;
}
@@ -959,7 +964,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
else
{
my_printf_error(0,"mysqld doesn't answer to ping, error: '%s'",
- MYF(ME_BELL),mysql_error(mysql));
+ error_flags, mysql_error(mysql));
return -1;
}
}
@@ -970,7 +975,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
if (argc < 2)
{
- my_printf_error(0,"Too few arguments to ndb-mgm",MYF(ME_BELL));
+ my_printf_error(0, "Too few arguments to ndb-mgm", error_flags);
return 1;
}
{
@@ -984,7 +989,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
break;
#endif
default:
- my_printf_error(0,"Unknown command: '%-.60s'",MYF(ME_BELL),argv[0]);
+ my_printf_error(0, "Unknown command: '%-.60s'", error_flags, argv[0]);
return 1;
}
}
@@ -1062,7 +1067,7 @@ static int drop_db(MYSQL *mysql, const char *db)
sprintf(name_buff,"drop database `%.*s`",FN_REFLEN,db);
if (mysql_query(mysql,name_buff))
{
- my_printf_error(0,"DROP DATABASE %s failed;\nerror: '%s'",MYF(ME_BELL),
+ my_printf_error(0, "DROP DATABASE %s failed;\nerror: '%s'", error_flags,
db,mysql_error(mysql));
return 1;
}
@@ -1287,7 +1292,7 @@ static my_bool get_pidfile(MYSQL *mysql, char *pidfile)
if (mysql_query(mysql, "SHOW VARIABLES LIKE 'pid_file'"))
{
- my_printf_error(0,"query failed; error: '%s'",MYF(ME_BELL),
+ my_printf_error(0, "query failed; error: '%s'", error_flags,
mysql_error(mysql));
}
result = mysql_store_result(mysql);
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index f2d395bf966..dec750d7313 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -158,11 +158,7 @@ class Load_log_processor
public:
Load_log_processor() {}
- ~Load_log_processor()
- {
- destroy();
- delete_dynamic(&file_names);
- }
+ ~Load_log_processor() {}
int init()
{
@@ -182,20 +178,22 @@ public:
target_dir_name_len= strlen(target_dir_name);
}
void destroy()
+ {
+ File_name_record *ptr= (File_name_record *)file_names.buffer;
+ File_name_record *end= ptr + file_names.elements;
+ for (; ptr < end; ptr++)
{
- File_name_record *ptr= (File_name_record *)file_names.buffer;
- File_name_record *end= ptr + file_names.elements;
- for (; ptr<end; ptr++)
+ if (ptr->fname)
{
- if (ptr->fname)
- {
- my_free(ptr->fname, MYF(MY_WME));
- delete ptr->event;
- bzero((char *)ptr, sizeof(File_name_record));
- }
+ my_free(ptr->fname, MYF(MY_WME));
+ delete ptr->event;
+ bzero((char *)ptr, sizeof(File_name_record));
}
}
+ delete_dynamic(&file_names);
+ }
+
/*
Obtain Create_file event for LOAD DATA statement by its file_id.
@@ -483,22 +481,17 @@ static int
write_event_header_and_base64(Log_event *ev, FILE *result_file,
PRINT_EVENT_INFO *print_event_info)
{
+ IO_CACHE *head= &print_event_info->head_cache;
+ IO_CACHE *body= &print_event_info->body_cache;
DBUG_ENTER("write_event_header_and_base64");
- /* Write header and base64 output to cache */
- IO_CACHE result_cache;
- if (init_io_cache(&result_cache, -1, 0, WRITE_CACHE, 0L, FALSE,
- MYF(MY_WME | MY_NABP)))
- {
- return 1;
- }
- ev->print_header(&result_cache, print_event_info, FALSE);
- ev->print_base64(&result_cache, print_event_info, FALSE);
+ /* Write header and base64 output to cache */
+ ev->print_header(head, print_event_info, FALSE);
+ ev->print_base64(body, print_event_info, FALSE);
/* Read data from cache and write to result file */
- my_b_copy_to_file(&result_cache, result_file);
- end_io_cache(&result_cache);
- DBUG_RETURN(0);
+ DBUG_RETURN(copy_event_cache_to_file_and_reinit(head, result_file) ||
+ copy_event_cache_to_file_and_reinit(body, result_file));
}
@@ -1016,6 +1009,9 @@ static int dump_log_entries(const char* logname)
{
int rc;
PRINT_EVENT_INFO print_event_info;
+
+ if (!print_event_info.init_ok())
+ return 1;
/*
Set safe delimiter, to dump things
like CREATE PROCEDURE safely
@@ -1577,6 +1573,7 @@ int main(int argc, char** argv)
cleanup();
free_defaults(defaults_argv);
my_free_open_file_info();
+ load_processor.destroy();
/* We cannot free DBUG, it is used in global destructors after exit(). */
my_end((info_flag ? MY_CHECK_ERROR : 0) | MY_DONT_FREE_DBUG);
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c
index 1a9d07804b4..2f5d435d0a5 100644
--- a/client/mysqlcheck.c
+++ b/client/mysqlcheck.c
@@ -34,7 +34,8 @@ static my_bool opt_alldbs = 0, opt_check_only_changed = 0, opt_extended = 0,
opt_medium_check = 0, opt_quick = 0, opt_all_in_1 = 0,
opt_silent = 0, opt_auto_repair = 0, ignore_errors = 0,
tty_password= 0, opt_frm= 0, info_flag= 0,
- opt_fix_table_names= 0, opt_fix_db_names= 0, opt_upgrade= 0;
+ opt_fix_table_names= 0, opt_fix_db_names= 0, opt_upgrade= 0,
+ opt_write_binlog= 1;
static uint verbose = 0, opt_mysql_port=0;
static my_string opt_mysql_unix_port = 0;
static char *opt_password = 0, *current_user = 0,
@@ -123,6 +124,10 @@ static struct my_option my_long_options[] =
{"medium-check", 'm',
"Faster than extended-check, but only finds 99.99 percent of all errors. Should be good enough for most cases.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"write-binlog", OPT_WRITE_BINLOG,
+ "Log ANALYZE, OPTIMIZE and REPAIR TABLE commands. Enabled by default; use --skip-write-binlog when commands should not be sent to replication slaves.",
+ (gptr*) &opt_write_binlog, (gptr*) &opt_write_binlog, 0, GET_BOOL, NO_ARG,
+ 1, 0, 0, 0, 0, 0},
{"optimize", 'o', "Optimize table.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0,
0, 0},
{"password", 'p',
@@ -598,16 +603,16 @@ static int handle_request_for_tables(char *tables, uint length)
if (opt_upgrade) end = strmov(end, " FOR UPGRADE");
break;
case DO_REPAIR:
- op = "REPAIR";
+ op= (opt_write_binlog) ? "REPAIR" : "REPAIR NO_WRITE_TO_BINLOG";
if (opt_quick) end = strmov(end, " QUICK");
if (opt_extended) end = strmov(end, " EXTENDED");
if (opt_frm) end = strmov(end, " USE_FRM");
break;
case DO_ANALYZE:
- op = "ANALYZE";
+ op= (opt_write_binlog) ? "ANALYZE" : "ANALYZE NO_WRITE_TO_BINLOG";
break;
case DO_OPTIMIZE:
- op = "OPTIMIZE";
+ op= (opt_write_binlog) ? "OPTIMIZE" : "OPTIMIZE NO_WRITE_TO_BINLOG";
break;
case DO_UPGRADE:
return fix_object_name("TABLE", tables);
diff --git a/client/mysqldump.c b/client/mysqldump.c
index 5f2749eef77..99415a5a593 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -77,13 +77,13 @@
#define IGNORE_DATA 0x01 /* don't dump data for this table */
#define IGNORE_INSERT_DELAYED 0x02 /* table doesn't support INSERT DELAYED */
-static char *add_load_option(char *ptr, const char *object,
- const char *statement);
+static void add_load_option(DYNAMIC_STRING *str, const char *option,
+ const char *option_value);
static ulong find_set(TYPELIB *lib, const char *x, uint length,
char **err_pos, uint *err_len);
static char *alloc_query_str(ulong size);
-static char *field_escape(char *to,const char *from,uint length);
+static void field_escape(DYNAMIC_STRING* in, const char *from);
static my_bool verbose= 0, opt_no_create_info= 0, opt_no_data= 0,
quick= 1, extended_insert= 1,
lock_tables=1,ignore_errors=0,flush_logs=0,flush_privileges=0,
@@ -125,6 +125,19 @@ FILE *md_result_file= 0;
static char *shared_memory_base_name=0;
#endif
static uint opt_protocol= 0;
+
+/*
+Dynamic_string wrapper functions. In this file use these
+wrappers, they will terminate the process if there is
+an allocation failure.
+*/
+static void init_dynamic_string_checked(DYNAMIC_STRING *str, const char *init_str,
+ uint init_alloc, uint alloc_increment);
+static void dynstr_append_checked(DYNAMIC_STRING* dest, const char* src);
+static void dynstr_set_checked(DYNAMIC_STRING *str, const char *init_str);
+static void dynstr_append_mem_checked(DYNAMIC_STRING *str, const char *append,
+ uint length);
+static void dynstr_realloc_checked(DYNAMIC_STRING *str, ulong additional_size);
/*
Constant for detection of default value of default_charset.
If default_charset is equal to mysql_universal_client_charset, then
@@ -436,7 +449,9 @@ static struct my_option my_long_options[] =
static const char *load_default_groups[]= { "mysqldump","client",0 };
-static void safe_exit(int error);
+static void maybe_exit(int error);
+static void die(int error, const char* reason, ...);
+static void maybe_die(int error, const char* reason, ...);
static void write_header(FILE *sql_file, char *db_name);
static void print_value(FILE *file, MYSQL_RES *result, MYSQL_ROW row,
const char *prefix,const char *name,
@@ -495,11 +510,7 @@ static void verbose_msg(const char *fmt, ...)
void check_io(FILE *file)
{
if (ferror(file))
- {
- fprintf(stderr, "%s: Got errno %d on write\n", my_progname, errno);
- ignore_errors= 0; /* We can't ignore this error */
- safe_exit(EX_EOF);
- }
+ die(EX_EOF, "Got errno %d on write", errno);
}
static void print_version(void)
@@ -887,12 +898,74 @@ static int get_options(int *argc, char ***argv)
static void DB_error(MYSQL *mysql_arg, const char *when)
{
DBUG_ENTER("DB_error");
- fprintf(stderr, "%s: Got error: %d: %s %s\n", my_progname,
+ maybe_die(EX_MYSQLERR, "Got error: %d: %s %s",
mysql_errno(mysql_arg), mysql_error(mysql_arg), when);
- fflush(stderr);
- safe_exit(EX_MYSQLERR);
DBUG_VOID_RETURN;
-} /* DB_error */
+}
+
+
+
+/*
+ Prints out an error message and kills the process.
+
+ SYNOPSIS
+ die()
+ error_num - process return value
+ fmt_reason - a format string for use by my_vsnprintf.
+ ... - variable arguments for above fmt_reason string
+
+ DESCRIPTION
+ This call prints out the formatted error message to stderr and then
+ terminates the process.
+*/
+static void die(int error_num, const char* fmt_reason, ...)
+{
+ char buffer[1000];
+ va_list args;
+ va_start(args,fmt_reason);
+ my_vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
+ va_end(args);
+
+ fprintf(stderr, "%s: %s\n", my_progname, buffer);
+ fflush(stderr);
+
+ ignore_errors= 0; /* force the exit */
+ maybe_exit(error_num);
+}
+
+
+/*
+ Prints out an error message and maybe kills the process.
+
+ SYNOPSIS
+ maybe_die()
+ error_num - process return value
+ fmt_reason - a format string for use by my_vsnprintf.
+ ... - variable arguments for above fmt_reason string
+
+ DESCRIPTION
+ This call prints out the formatted error message to stderr and then
+ terminates the process, unless the --force command line option is used.
+
+ This call should be used for non-fatal errors (such as database
+ errors) that the code may still be able to continue to the next unit
+ of work.
+
+*/
+static void maybe_die(int error_num, const char* fmt_reason, ...)
+{
+ char buffer[1000];
+ va_list args;
+ va_start(args,fmt_reason);
+ my_vsnprintf(buffer, sizeof(buffer), fmt_reason, args);
+ va_end(args);
+
+ fprintf(stderr, "%s: %s\n", my_progname, buffer);
+ fflush(stderr);
+
+ maybe_exit(error_num);
+}
+
/*
@@ -917,10 +990,8 @@ static int mysql_query_with_error_report(MYSQL *mysql_con, MYSQL_RES **res,
if (mysql_query(mysql_con, query) ||
(res && !((*res)= mysql_store_result(mysql_con))))
{
- fprintf(stderr, "%s: Couldn't execute '%s': %s (%d)\n",
- my_progname, query,
- mysql_error(mysql_con), mysql_errno(mysql_con));
- safe_exit(EX_MYSQLERR);
+ maybe_die(EX_MYSQLERR, "Couldn't execute '%s': %s (%d)",
+ query, mysql_error(mysql_con), mysql_errno(mysql_con));
return 1;
}
return 0;
@@ -965,7 +1036,7 @@ static void free_resources()
}
-static void safe_exit(int error)
+static void maybe_exit(int error)
{
if (!first_error)
first_error= error;
@@ -1025,10 +1096,7 @@ static int connect_to_db(char *host, char *user,char *passwd)
my_snprintf(buff, sizeof(buff), "/*!40100 SET @@SQL_MODE='%s' */",
compatible_mode_normal_str);
if (mysql_query_with_error_report(mysql, 0, buff))
- {
- safe_exit(EX_MYSQLERR);
DBUG_RETURN(1);
- }
/*
set time_zone to UTC to allow dumping date types between servers with
different time zone settings
@@ -1037,10 +1105,7 @@ static int connect_to_db(char *host, char *user,char *passwd)
{
my_snprintf(buff, sizeof(buff), "/*!40103 SET TIME_ZONE='+00:00' */");
if (mysql_query_with_error_report(mysql, 0, buff))
- {
- safe_exit(EX_MYSQLERR);
DBUG_RETURN(1);
- }
}
DBUG_RETURN(0);
} /* connect_to_db */
@@ -1061,10 +1126,8 @@ static void unescape(FILE *file,char *pos,uint length)
char *tmp;
DBUG_ENTER("unescape");
if (!(tmp=(char*) my_malloc(length*2+1, MYF(MY_WME))))
- {
- ignore_errors=0; /* Fatal error */
- safe_exit(EX_MYSQLERR); /* Force exit */
- }
+ die(EX_MYSQLERR, "Couldn't allocate memory");
+
mysql_real_escape_string(&mysql_connection, tmp, pos, length);
fputc('\'', file);
fputs(tmp, file);
@@ -1423,14 +1486,13 @@ static uint dump_events_for_db(char *db)
mysql_query(mysql, "LOCK TABLES mysql.event READ");
if (mysql_query_with_error_report(mysql, &event_list_res, "show events"))
- {
- safe_exit(EX_MYSQLERR);
DBUG_RETURN(0);
- }
strcpy(delimiter, ";");
if (mysql_num_rows(event_list_res) > 0)
{
+ fprintf(sql_file, "/*!50106 SET @save_time_zone= @@TIME_ZONE */ ;\n");
+
while ((event_list_row= mysql_fetch_row(event_list_res)) != NULL)
{
event_name= quote_name(event_list_row[1], name_buff, 0);
@@ -1447,13 +1509,13 @@ static uint dump_events_for_db(char *db)
if the user has EXECUTE privilege he can see event names, but not the
event body!
*/
- if (strlen(row[2]) != 0)
+ if (strlen(row[3]) != 0)
{
if (opt_drop)
fprintf(sql_file, "/*!50106 DROP EVENT IF EXISTS %s */%s\n",
event_name, delimiter);
- delimit_test= create_delimiter(row[2], delimiter, sizeof(delimiter));
+ delimit_test= create_delimiter(row[3], delimiter, sizeof(delimiter));
if (delimit_test == NULL) {
fprintf(stderr, "%s: Warning: Can't dump event '%s'\n",
event_name, my_progname);
@@ -1461,12 +1523,16 @@ static uint dump_events_for_db(char *db)
}
fprintf(sql_file, "DELIMITER %s\n", delimiter);
- fprintf(sql_file, "/*!50106 %s */ %s\n", row[2], delimiter);
+ fprintf(sql_file, "/*!50106 SET TIME_ZONE= '%s' */ %s\n",
+ row[2], delimiter);
+ fprintf(sql_file, "/*!50106 %s */ %s\n", row[3], delimiter);
}
} /* end of event printing */
+ mysql_free_result(event_res);
+
} /* end of list of events */
fprintf(sql_file, "DELIMITER ;\n");
- mysql_free_result(event_res);
+ fprintf(sql_file, "/*!50106 SET TIME_ZONE= @save_time_zone */ ;\n");
}
mysql_free_result(event_list_res);
@@ -1633,8 +1699,9 @@ static uint dump_routines_for_db(char *db)
my_free(query_str, MYF(MY_ALLOW_ZERO_PTR));
}
} /* end of routine printing */
+ mysql_free_result(routine_res);
+
} /* end of list of routines */
- mysql_free_result(routine_res);
}
mysql_free_result(routine_list_res);
} /* end of for i (0 .. 1) */
@@ -1695,11 +1762,10 @@ static uint get_table_structure(char *table, char *db, char *table_type,
if (!insert_pat_inited)
{
insert_pat_inited= 1;
- if (init_dynamic_string(&insert_pat, "", 1024, 1024))
- safe_exit(EX_MYSQLERR);
+ init_dynamic_string_checked(&insert_pat, "", 1024, 1024);
}
else
- dynstr_set(&insert_pat, "");
+ dynstr_set_checked(&insert_pat, "");
}
insert_option= ((delayed && opt_ignore) ? " DELAYED IGNORE " :
@@ -1731,18 +1797,13 @@ static uint get_table_structure(char *table, char *db, char *table_type,
my_snprintf(buff, sizeof(buff), "show create table %s", result_table);
if (mysql_query_with_error_report(mysql, 0, buff))
- {
- safe_exit(EX_MYSQLERR);
DBUG_RETURN(0);
- }
if (path)
{
if (!(sql_file= open_sql_file_for_table(table)))
- {
- safe_exit(EX_MYSQLERR);
DBUG_RETURN(0);
- }
+
write_header(sql_file, db);
}
if (!opt_xml && opt_comments)
@@ -1806,7 +1867,6 @@ static uint get_table_structure(char *table, char *db, char *table_type,
my_free(scv_buff, MYF(MY_ALLOW_ZERO_PTR));
- safe_exit(EX_MYSQLERR);
DBUG_RETURN(0);
}
else
@@ -1869,7 +1929,6 @@ static uint get_table_structure(char *table, char *db, char *table_type,
{
if (path)
my_fclose(sql_file, MYF(MY_WME));
- safe_exit(EX_MYSQLERR);
DBUG_RETURN(0);
}
@@ -1882,21 +1941,21 @@ static uint get_table_structure(char *table, char *db, char *table_type,
if (write_data)
{
if (opt_replace_into)
- dynstr_append_mem(&insert_pat, "REPLACE ", 8);
+ dynstr_append_checked(&insert_pat, "REPLACE ");
else
- dynstr_append_mem(&insert_pat, "INSERT ", 7);
- dynstr_append(&insert_pat, insert_option);
- dynstr_append_mem(&insert_pat, "INTO ", 5);
- dynstr_append(&insert_pat, opt_quoted_table);
+ dynstr_append_checked(&insert_pat, "INSERT ");
+ dynstr_append_checked(&insert_pat, insert_option);
+ dynstr_append_checked(&insert_pat, "INTO ");
+ dynstr_append_checked(&insert_pat, opt_quoted_table);
if (complete_insert)
{
- dynstr_append_mem(&insert_pat, " (", 2);
+ dynstr_append_checked(&insert_pat, " (");
}
else
{
- dynstr_append_mem(&insert_pat, " VALUES ", 8);
+ dynstr_append_checked(&insert_pat, " VALUES ");
if (!extended_insert)
- dynstr_append_mem(&insert_pat, "(", 1);
+ dynstr_append_checked(&insert_pat, "(");
}
}
@@ -1906,10 +1965,10 @@ static uint get_table_structure(char *table, char *db, char *table_type,
{
if (init)
{
- dynstr_append_mem(&insert_pat, ", ", 2);
+ dynstr_append_checked(&insert_pat, ", ");
}
init=1;
- dynstr_append(&insert_pat,
+ dynstr_append_checked(&insert_pat,
quote_name(row[SHOW_FIELDNAME], name_buff, 0));
}
}
@@ -1924,10 +1983,7 @@ static uint get_table_structure(char *table, char *db, char *table_type,
my_snprintf(query_buff, sizeof(query_buff), "show fields from %s",
result_table);
if (mysql_query_with_error_report(mysql, &result, query_buff))
- {
- safe_exit(EX_MYSQLERR);
DBUG_RETURN(0);
- }
/* Make an sql-file, if path was given iow. option -T was given */
if (!opt_no_create_info)
@@ -1935,10 +1991,7 @@ static uint get_table_structure(char *table, char *db, char *table_type,
if (path)
{
if (!(sql_file= open_sql_file_for_table(table)))
- {
- safe_exit(EX_MYSQLERR);
DBUG_RETURN(0);
- }
write_header(sql_file, db);
}
if (!opt_xml && opt_comments)
@@ -1957,19 +2010,19 @@ static uint get_table_structure(char *table, char *db, char *table_type,
if (write_data)
{
if (opt_replace_into)
- dynstr_append_mem(&insert_pat, "REPLACE ", 8);
+ dynstr_append_checked(&insert_pat, "REPLACE ");
else
- dynstr_append_mem(&insert_pat, "INSERT ", 7);
- dynstr_append(&insert_pat, insert_option);
- dynstr_append_mem(&insert_pat, "INTO ", 5);
- dynstr_append(&insert_pat, result_table);
- if (opt_complete_insert)
- dynstr_append_mem(&insert_pat, " (", 2);
+ dynstr_append_checked(&insert_pat, "INSERT ");
+ dynstr_append_checked(&insert_pat, insert_option);
+ dynstr_append_checked(&insert_pat, "INTO ");
+ dynstr_append_checked(&insert_pat, result_table);
+ if (complete_insert)
+ dynstr_append_checked(&insert_pat, " (");
else
{
- dynstr_append_mem(&insert_pat, " VALUES ", 8);
+ dynstr_append_checked(&insert_pat, " VALUES ");
if (!extended_insert)
- dynstr_append_mem(&insert_pat, "(", 1);
+ dynstr_append_checked(&insert_pat, "(");
}
}
@@ -1984,11 +2037,11 @@ static uint get_table_structure(char *table, char *db, char *table_type,
check_io(sql_file);
}
if (complete_insert)
- dynstr_append_mem(&insert_pat, ", ", 2);
+ dynstr_append_checked(&insert_pat, ", ");
}
init=1;
- if (opt_complete_insert)
- dynstr_append(&insert_pat,
+ if (complete_insert)
+ dynstr_append_checked(&insert_pat,
quote_name(row[SHOW_FIELDNAME], name_buff, 0));
if (!opt_no_create_info)
{
@@ -2038,7 +2091,6 @@ static uint get_table_structure(char *table, char *db, char *table_type,
my_progname, result_table, mysql_error(mysql));
if (path)
my_fclose(sql_file, MYF(MY_WME));
- safe_exit(EX_MYSQLERR);
DBUG_RETURN(0);
}
@@ -2146,11 +2198,11 @@ continue_xml:
check_io(sql_file);
}
}
- if (opt_complete_insert)
+ if (complete_insert)
{
- dynstr_append_mem(&insert_pat, ") VALUES ", 9);
+ dynstr_append_checked(&insert_pat, ") VALUES ");
if (!extended_insert)
- dynstr_append_mem(&insert_pat, "(", 1);
+ dynstr_append_checked(&insert_pat, "(");
}
if (sql_file != md_result_file)
{
@@ -2197,7 +2249,6 @@ static void dump_triggers_for_table(char *table,
{
if (path)
my_fclose(sql_file, MYF(MY_WME));
- safe_exit(EX_MYSQLERR);
DBUG_VOID_RETURN;
}
if (mysql_num_rows(result))
@@ -2256,24 +2307,28 @@ DELIMITER ;;\n");
DBUG_VOID_RETURN;
}
-static char *add_load_option(char *ptr,const char *object,
- const char *statement)
+static void add_load_option(DYNAMIC_STRING *str, const char *option,
+ const char *option_value)
{
- if (object)
+ if (!option_value)
{
- /* Don't escape hex constants */
- if (object[0] == '0' && (object[1] == 'x' || object[1] == 'X'))
- ptr= strxmov(ptr," ",statement," ",object,NullS);
- else
- {
- /* char constant; escape */
- ptr= strxmov(ptr," ",statement," '",NullS);
- ptr= field_escape(ptr,object,(uint) strlen(object));
- *ptr++= '\'';
- }
+ /* Null value means we don't add this option. */
+ return;
}
- return ptr;
-} /* add_load_option */
+
+ dynstr_append_checked(str, option);
+
+ if (strncmp(option_value, "0x", sizeof("0x")-1) == 0)
+ {
+ /* It's a hex constant, don't escape */
+ dynstr_append_checked(str, option_value);
+ }
+ else
+ {
+ /* char constant; escape */
+ field_escape(str, option_value);
+ }
+}
/*
@@ -2283,28 +2338,36 @@ static char *add_load_option(char *ptr,const char *object,
syntax errors from the SQL parser.
*/
-static char *field_escape(char *to,const char *from,uint length)
+static void field_escape(DYNAMIC_STRING* in, const char *from)
{
- const char *end;
- uint end_backslashes=0;
+ uint end_backslashes= 0;
+
+ dynstr_append_checked(in, "'");
- for (end= from+length; from != end; from++)
+ while (*from)
{
- *to++= *from;
+ dynstr_append_mem_checked(in, from, 1);
+
if (*from == '\\')
end_backslashes^=1; /* find odd number of backslashes */
else
{
if (*from == '\'' && !end_backslashes)
- *to++= *from; /* We want a duplicate of "'" for MySQL */
+ {
+ /* We want a duplicate of "'" for MySQL */
+ dynstr_append_checked(in, "\'");
+ }
end_backslashes=0;
}
+ from++;
}
/* Add missing backslashes if user has specified odd number of backs.*/
if (end_backslashes)
- *to++= '\\';
- return to;
-} /* field_escape */
+ dynstr_append_checked(in, "\\");
+
+ dynstr_append_checked(in, "'");
+}
+
static char *alloc_query_str(ulong size)
@@ -2312,10 +2375,8 @@ static char *alloc_query_str(ulong size)
char *query;
if (!(query= (char*) my_malloc(size, MYF(MY_WME))))
- {
- ignore_errors= 0; /* Fatal error */
- safe_exit(EX_MYSQLERR); /* Force exit */
- }
+ die(EX_MYSQLERR, "Couldn't allocate a query string.");
+
return query;
}
@@ -2335,13 +2396,14 @@ static char *alloc_query_str(ulong size)
void
*/
+
static void dump_table(char *table, char *db)
{
char ignore_flag;
- char query_buf[QUERY_LENGTH], *end, buff[256],table_buff[NAME_LEN+3];
+ char buf[200], table_buff[NAME_LEN+3];
+ DYNAMIC_STRING query_string;
char table_type[NAME_LEN];
char *result_table, table_buff2[NAME_LEN*2+3], *opt_quoted_table;
- char *query= query_buf;
int error= 0;
ulong rownr, row_break, total_length, init_length;
uint num_fields;
@@ -2395,44 +2457,69 @@ static void dump_table(char *table, char *db)
opt_quoted_table= quote_name(table, table_buff2, 0);
verbose_msg("-- Sending SELECT query...\n");
+
+ init_dynamic_string_checked(&query_string, "", 1024, 1024);
+
if (path)
{
char filename[FN_REFLEN], tmp_path[FN_REFLEN];
- convert_dirname(tmp_path,path,NullS);
+
+ if (strlen(path) >= FN_REFLEN)
+ {
+ /*
+ This check is made because the some the file functions below
+ have FN_REFLEN sized stack allocated buffers and will cause
+ a crash even if the input destination buffer is large enough
+ to hold the output.
+ */
+ die(EX_USAGE, "Input filename or options too long: %s", path);
+ }
+
+ /*
+ Convert the path to native os format
+ and resolve to the full filepath.
+ */
+ convert_dirname(tmp_path,path,NullS);
my_load_path(tmp_path, tmp_path, NULL);
- fn_format(filename, table, tmp_path, ".txt", 4);
- my_delete(filename, MYF(0)); /* 'INTO OUTFILE' doesn't work, if
- filename wasn't deleted */
+ fn_format(filename, table, tmp_path, ".txt", MYF(MY_UNPACK_FILENAME));
+
+ /* Must delete the file that 'INTO OUTFILE' will write to */
+ my_delete(filename, MYF(0));
+
+ /* convert to a unix path name to stick into the query */
to_unix_path(filename);
- my_snprintf(query, QUERY_LENGTH,
- "SELECT /*!40001 SQL_NO_CACHE */ * INTO OUTFILE '%s'",
- filename);
- end= strend(query);
+
+ /* now build the query string */
+
+ dynstr_append_checked(&query_string, "SELECT /*!40001 SQL_NO_CACHE */ * INTO OUTFILE '");
+ dynstr_append_checked(&query_string, filename);
+ dynstr_append_checked(&query_string, "'");
if (fields_terminated || enclosed || opt_enclosed || escaped)
- end= strmov(end, " FIELDS");
- end= add_load_option(end, fields_terminated, " TERMINATED BY");
- end= add_load_option(end, enclosed, " ENCLOSED BY");
- end= add_load_option(end, opt_enclosed, " OPTIONALLY ENCLOSED BY");
- end= add_load_option(end, escaped, " ESCAPED BY");
- end= add_load_option(end, lines_terminated, " LINES TERMINATED BY");
- *end= '\0';
-
- my_snprintf(buff, sizeof(buff), " FROM %s", result_table);
- end= strmov(end,buff);
- if (where || order_by)
+ dynstr_append_checked(&query_string, " FIELDS");
+
+ add_load_option(&query_string, " TERMINATED BY ", fields_terminated);
+ add_load_option(&query_string, " ENCLOSED BY ", enclosed);
+ add_load_option(&query_string, " OPTIONALLY ENCLOSED BY ", opt_enclosed);
+ add_load_option(&query_string, " ESCAPED BY ", escaped);
+ add_load_option(&query_string, " LINES TERMINATED BY ", lines_terminated);
+
+ dynstr_append_checked(&query_string, " FROM ");
+ dynstr_append_checked(&query_string, result_table);
+
+ if (where)
+ {
+ dynstr_append_checked(&query_string, " WHERE ");
+ dynstr_append_checked(&query_string, where);
+ }
+
+ if (order_by)
{
- query= alloc_query_str((ulong) ((end - query) + 1 +
- (where ? strlen(where) + 7 : 0) +
- (order_by ? strlen(order_by) + 10 : 0)));
- end= strmov(query, query_buf);
-
- if (where)
- end= strxmov(end, " WHERE ", where, NullS);
- if (order_by)
- end= strxmov(end, " ORDER BY ", order_by, NullS);
+ dynstr_append_checked(&query_string, " ORDER BY ");
+ dynstr_append_checked(&query_string, order_by);
}
- if (mysql_real_query(mysql, query, (uint) (end - query)))
+
+ if (mysql_real_query(mysql, query_string.str, query_string.length))
{
DB_error(mysql, "when executing 'SELECT INTO OUTFILE'");
DBUG_VOID_RETURN;
@@ -2446,41 +2533,38 @@ static void dump_table(char *table, char *db)
result_table);
check_io(md_result_file);
}
- my_snprintf(query, QUERY_LENGTH,
- "SELECT /*!40001 SQL_NO_CACHE */ * FROM %s",
- result_table);
- if (where || order_by)
- {
- query= alloc_query_str((ulong) (strlen(query) + 1 +
- (where ? strlen(where) + 7 : 0) +
- (order_by ? strlen(order_by) + 10 : 0)));
- end= strmov(query, query_buf);
+
+ dynstr_append_checked(&query_string, "SELECT /*!40001 SQL_NO_CACHE */ * FROM ");
+ dynstr_append_checked(&query_string, result_table);
- if (where)
+ if (where)
+ {
+ if (!opt_xml && opt_comments)
{
- if (!opt_xml && opt_comments)
- {
- fprintf(md_result_file, "-- WHERE: %s\n", where);
- check_io(md_result_file);
- }
- end= strxmov(end, " WHERE ", where, NullS);
+ fprintf(md_result_file, "-- WHERE: %s\n", where);
+ check_io(md_result_file);
}
- if (order_by)
+
+ dynstr_append_checked(&query_string, " WHERE ");
+ dynstr_append_checked(&query_string, where);
+ }
+ if (order_by)
+ {
+ if (!opt_xml && opt_comments)
{
- if (!opt_xml && opt_comments)
- {
- fprintf(md_result_file, "-- ORDER BY: %s\n", order_by);
- check_io(md_result_file);
- }
- end= strxmov(end, " ORDER BY ", order_by, NullS);
+ fprintf(md_result_file, "-- ORDER BY: %s\n", order_by);
+ check_io(md_result_file);
}
+ dynstr_append_checked(&query_string, " ORDER BY ");
+ dynstr_append_checked(&query_string, order_by);
}
+
if (!opt_xml && !opt_compact)
{
fputs("\n", md_result_file);
check_io(md_result_file);
}
- if (mysql_query_with_error_report(mysql, 0, query))
+ if (mysql_query_with_error_report(mysql, 0, query_string.str))
{
DB_error(mysql, "when retrieving data from server");
goto err;
@@ -2554,14 +2638,9 @@ static void dump_table(char *table, char *db)
ulong length= lengths[i];
if (!(field= mysql_fetch_field(res)))
- {
- my_snprintf(query, QUERY_LENGTH,
- "%s: Not enough fields from table %s! Aborting.\n",
- my_progname, result_table);
- fputs(query,stderr);
- error= EX_CONSCHECK;
- goto err;
- }
+ die(EX_CONSCHECK,
+ "Not enough fields from table %s! Aborting.\n",
+ result_table);
/*
63 is my_charset_bin. If charsetnr is not 63,
@@ -2580,9 +2659,9 @@ static void dump_table(char *table, char *db)
if (extended_insert && !opt_xml)
{
if (i == 0)
- dynstr_set(&extended_row,"(");
+ dynstr_set_checked(&extended_row,"(");
else
- dynstr_append(&extended_row,",");
+ dynstr_append_checked(&extended_row,",");
if (row[i])
{
@@ -2597,15 +2676,10 @@ static void dump_table(char *table, char *db)
- In non-HEX mode we need up to 2 bytes per character,
plus 2 bytes for leading and trailing '\'' characters.
*/
- if (dynstr_realloc(&extended_row,length * 2+2))
- {
- fputs("Aborting dump (out of memory)",stderr);
- error= EX_EOM;
- goto err;
- }
+ dynstr_realloc_checked(&extended_row,length * 2+2);
if (opt_hex_blob && is_blob)
{
- dynstr_append(&extended_row, "0x");
+ dynstr_append_checked(&extended_row, "0x");
extended_row.length+= mysql_hex_string(extended_row.str +
extended_row.length,
row[i], length);
@@ -2613,13 +2687,13 @@ static void dump_table(char *table, char *db)
}
else
{
- dynstr_append(&extended_row,"'");
+ dynstr_append_checked(&extended_row,"'");
extended_row.length +=
mysql_real_escape_string(&mysql_connection,
&extended_row.str[extended_row.length],
row[i],length);
extended_row.str[extended_row.length]='\0';
- dynstr_append(&extended_row,"'");
+ dynstr_append_checked(&extended_row,"'");
}
}
else
@@ -2628,30 +2702,26 @@ static void dump_table(char *table, char *db)
char *ptr= row[i];
if (my_isalpha(charset_info, *ptr) || (*ptr == '-' &&
my_isalpha(charset_info, ptr[1])))
- dynstr_append(&extended_row, "NULL");
+ dynstr_append_checked(&extended_row, "NULL");
else
{
if (field->type == MYSQL_TYPE_DECIMAL)
{
/* add " signs around */
- dynstr_append(&extended_row, "'");
- dynstr_append(&extended_row, ptr);
- dynstr_append(&extended_row, "'");
+ dynstr_append_checked(&extended_row, "'");
+ dynstr_append_checked(&extended_row, ptr);
+ dynstr_append_checked(&extended_row, "'");
}
else
- dynstr_append(&extended_row, ptr);
+ dynstr_append_checked(&extended_row, ptr);
}
}
}
else
- dynstr_append(&extended_row,"''");
- }
- else if (dynstr_append(&extended_row,"NULL"))
- {
- fputs("Aborting dump (out of memory)",stderr);
- error= EX_EOM;
- goto err;
+ dynstr_append_checked(&extended_row,"''");
}
+ else
+ dynstr_append_checked(&extended_row,"NULL");
}
else
{
@@ -2737,7 +2807,7 @@ static void dump_table(char *table, char *db)
if (extended_insert)
{
ulong row_length;
- dynstr_append(&extended_row,")");
+ dynstr_append_checked(&extended_row,")");
row_length= 2 + extended_row.length;
if (total_length + row_length < opt_net_buffer_length)
{
@@ -2773,14 +2843,14 @@ static void dump_table(char *table, char *db)
check_io(md_result_file);
if (mysql_errno(mysql))
{
- my_snprintf(query, QUERY_LENGTH,
+ my_snprintf(buf, sizeof(buf),
"%s: Error %d: %s when dumping table %s at row: %ld\n",
my_progname,
mysql_errno(mysql),
mysql_error(mysql),
result_table,
rownr);
- fputs(query,stderr);
+ fputs(buf,stderr);
error= EX_CONSCHECK;
goto err;
}
@@ -2803,15 +2873,13 @@ static void dump_table(char *table, char *db)
check_io(md_result_file);
}
mysql_free_result(res);
- if (query != query_buf)
- my_free(query, MYF(MY_ALLOW_ZERO_PTR));
+ dynstr_free(&query_string);
}
DBUG_VOID_RETURN;
err:
- if (query != query_buf)
- my_free(query, MYF(MY_ALLOW_ZERO_PTR));
- safe_exit(error);
+ dynstr_free(&query_string);
+ maybe_exit(error);
DBUG_VOID_RETURN;
} /* dump_table */
@@ -2858,25 +2926,25 @@ static int dump_tablespaces_for_tables(char *db, char **table_names, int tables)
mysql_real_escape_string(mysql, name_buff, db, strlen(db));
- init_dynamic_string(&where, " AND TABLESPACE_NAME IN ("
+ init_dynamic_string_checked(&where, " AND TABLESPACE_NAME IN ("
"SELECT DISTINCT TABLESPACE_NAME FROM"
" INFORMATION_SCHEMA.PARTITIONS"
" WHERE"
" TABLE_SCHEMA='", 256, 1024);
- dynstr_append(&where, name_buff);
- dynstr_append(&where, "' AND TABLE_NAME IN (");
+ dynstr_append_checked(&where, name_buff);
+ dynstr_append_checked(&where, "' AND TABLE_NAME IN (");
for (i=0 ; i<tables ; i++)
{
mysql_real_escape_string(mysql, name_buff,
table_names[i], strlen(table_names[i]));
- dynstr_append(&where, "'");
- dynstr_append(&where, name_buff);
- dynstr_append(&where, "',");
+ dynstr_append_checked(&where, "'");
+ dynstr_append_checked(&where, name_buff);
+ dynstr_append_checked(&where, "',");
}
dynstr_trunc(&where, 1);
- dynstr_append(&where,"))");
+ dynstr_append_checked(&where,"))");
DBUG_PRINT("info",("Dump TS for Tables where: %s",where.str));
r= dump_tablespaces(where.str);
@@ -2890,7 +2958,7 @@ static int dump_tablespaces_for_databases(char** databases)
int r;
int i;
- init_dynamic_string(&where, " AND TABLESPACE_NAME IN ("
+ init_dynamic_string_checked(&where, " AND TABLESPACE_NAME IN ("
"SELECT DISTINCT TABLESPACE_NAME FROM"
" INFORMATION_SCHEMA.PARTITIONS"
" WHERE"
@@ -2901,12 +2969,12 @@ static int dump_tablespaces_for_databases(char** databases)
char db_name_buff[NAME_LEN*2+3];
mysql_real_escape_string(mysql, db_name_buff,
databases[i], strlen(databases[i]));
- dynstr_append(&where, "'");
- dynstr_append(&where, db_name_buff);
- dynstr_append(&where, "',");
+ dynstr_append_checked(&where, "'");
+ dynstr_append_checked(&where, db_name_buff);
+ dynstr_append_checked(&where, "',");
}
dynstr_trunc(&where, 1);
- dynstr_append(&where,"))");
+ dynstr_append_checked(&where,"))");
DBUG_PRINT("info",("Dump TS for DBs where: %s",where.str));
r= dump_tablespaces(where.str);
@@ -2928,7 +2996,7 @@ static int dump_tablespaces(char* ts_where)
char *ubs;
char *endsemi;
- init_dynamic_string(&sqlbuf,
+ init_dynamic_string_checked(&sqlbuf,
"SELECT LOGFILE_GROUP_NAME,"
" FILE_NAME,"
" TOTAL_EXTENTS,"
@@ -2941,16 +3009,16 @@ static int dump_tablespaces(char* ts_where)
256, 1024);
if(ts_where)
{
- dynstr_append(&sqlbuf,
+ dynstr_append_checked(&sqlbuf,
" AND LOGFILE_GROUP_NAME IN ("
"SELECT DISTINCT LOGFILE_GROUP_NAME"
" FROM INFORMATION_SCHEMA.FILES"
" WHERE FILE_TYPE = 'DATAFILE'"
);
- dynstr_append(&sqlbuf, ts_where);
- dynstr_append(&sqlbuf, ")");
+ dynstr_append_checked(&sqlbuf, ts_where);
+ dynstr_append_checked(&sqlbuf, ")");
}
- dynstr_append(&sqlbuf,
+ dynstr_append_checked(&sqlbuf,
" GROUP BY LOGFILE_GROUP_NAME, FILE_NAME"
", ENGINE"
" ORDER BY LOGFILE_GROUP_NAME");
@@ -3023,7 +3091,7 @@ static int dump_tablespaces(char* ts_where)
}
}
dynstr_free(&sqlbuf);
- init_dynamic_string(&sqlbuf,
+ init_dynamic_string_checked(&sqlbuf,
"SELECT DISTINCT TABLESPACE_NAME,"
" FILE_NAME,"
" LOGFILE_GROUP_NAME,"
@@ -3035,9 +3103,9 @@ static int dump_tablespaces(char* ts_where)
256, 1024);
if(ts_where)
- dynstr_append(&sqlbuf, ts_where);
+ dynstr_append_checked(&sqlbuf, ts_where);
- dynstr_append(&sqlbuf, " ORDER BY TABLESPACE_NAME, LOGFILE_GROUP_NAME");
+ dynstr_append_checked(&sqlbuf, " ORDER BY TABLESPACE_NAME, LOGFILE_GROUP_NAME");
if (mysql_query_with_error_report(mysql, &tableres, sqlbuf.str))
return 1;
@@ -3248,8 +3316,8 @@ static int init_dumping(char *database, int init_func(char*))
check_io(md_result_file);
}
}
- if (extended_insert && init_dynamic_string(&extended_row, "", 1024, 1024))
- exit(EX_EOM);
+ if (extended_insert)
+ init_dynamic_string_checked(&extended_row, "", 1024, 1024);
return 0;
} /* init_dumping */
@@ -3282,11 +3350,11 @@ static int dump_all_tables_in_db(char *database)
if (lock_tables)
{
DYNAMIC_STRING query;
- init_dynamic_string(&query, "LOCK TABLES ", 256, 1024);
+ init_dynamic_string_checked(&query, "LOCK TABLES ", 256, 1024);
for (numrows= 0 ; (table= getTableName(1)) ; numrows++)
{
- dynstr_append(&query, quote_name(table, table_buff, 1));
- dynstr_append(&query, " READ /*!32311 LOCAL */,");
+ dynstr_append_checked(&query, quote_name(table, table_buff, 1));
+ dynstr_append_checked(&query, " READ /*!32311 LOCAL */,");
}
if (numrows && mysql_real_query(mysql, query.str, query.length-1))
DB_error(mysql, "when using LOCK TABLES");
@@ -3365,11 +3433,11 @@ static my_bool dump_all_views_in_db(char *database)
if (lock_tables)
{
DYNAMIC_STRING query;
- init_dynamic_string(&query, "LOCK TABLES ", 256, 1024);
+ init_dynamic_string_checked(&query, "LOCK TABLES ", 256, 1024);
for (numrows= 0 ; (table= getTableName(1)); numrows++)
{
- dynstr_append(&query, quote_name(table, table_buff, 1));
- dynstr_append(&query, " READ /*!32311 LOCAL */,");
+ dynstr_append_checked(&query, quote_name(table, table_buff, 1));
+ dynstr_append_checked(&query, " READ /*!32311 LOCAL */,");
}
if (numrows && mysql_real_query(mysql, query.str, query.length-1))
DB_error(mysql, "when using LOCK TABLES");
@@ -3421,9 +3489,7 @@ static char *get_actual_table_name(const char *old_table_name, MEM_ROOT *root)
quote_for_like(old_table_name, show_name_buff));
if (mysql_query_with_error_report(mysql, 0, query))
- {
- safe_exit(EX_MYSQLERR);
- }
+ return NullS;
if ((table_res= mysql_store_result(mysql)))
{
@@ -3448,7 +3514,7 @@ static char *get_actual_table_name(const char *old_table_name, MEM_ROOT *root)
static int dump_selected_tables(char *db, char **table_names, int tables)
{
- char table_buff[NAME_LEN*+3];
+ char table_buff[NAME_LEN*2+3];
DYNAMIC_STRING lock_tables_query;
MEM_ROOT root;
char **dump_tables, **pos, **end;
@@ -3459,9 +3525,9 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
init_alloc_root(&root, 8192, 0);
if (!(dump_tables= pos= (char**) alloc_root(&root, tables * sizeof(char *))))
- exit(EX_EOM);
+ die(EX_EOM, "alloc_root failure.");
- init_dynamic_string(&lock_tables_query, "LOCK TABLES ", 256, 1024);
+ init_dynamic_string_checked(&lock_tables_query, "LOCK TABLES ", 256, 1024);
for (; tables > 0 ; tables-- , table_names++)
{
/* the table name passed on commandline may be wrong case */
@@ -3470,16 +3536,14 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
/* Add found table name to lock_tables_query */
if (lock_tables)
{
- dynstr_append(&lock_tables_query, quote_name(*pos, table_buff, 1));
- dynstr_append(&lock_tables_query, " READ /*!32311 LOCAL */,");
+ dynstr_append_checked(&lock_tables_query, quote_name(*pos, table_buff, 1));
+ dynstr_append_checked(&lock_tables_query, " READ /*!32311 LOCAL */,");
}
pos++;
}
else
{
- my_printf_error(0,"Couldn't find table: \"%s\"\n", MYF(0),
- *table_names);
- safe_exit(EX_ILLEGAL_TABLE);
+ maybe_die(EX_ILLEGAL_TABLE, "Couldn't find table: \"%s\"", *table_names);
/* We shall countinue here, if --force was given */
}
}
@@ -3731,7 +3795,7 @@ char check_if_ignore_table(const char *table_name, char *table_type)
{
char result= IGNORE_NONE;
char buff[FN_REFLEN+80], show_name_buff[FN_REFLEN];
- MYSQL_RES *res;
+ MYSQL_RES *res= NULL;
MYSQL_ROW row;
DBUG_ENTER("check_if_ignore_table");
@@ -3900,12 +3964,12 @@ static int replace(DYNAMIC_STRING *ds_str,
const char *start= strstr(ds_str->str, search_str);
if (!start)
return 1;
- init_dynamic_string(&ds_tmp, "",
+ init_dynamic_string_checked(&ds_tmp, "",
ds_str->length + replace_len, 256);
- dynstr_append_mem(&ds_tmp, ds_str->str, start - ds_str->str);
- dynstr_append_mem(&ds_tmp, replace_str, replace_len);
- dynstr_append(&ds_tmp, start + search_len);
- dynstr_set(ds_str, ds_tmp.str);
+ dynstr_append_mem_checked(&ds_tmp, ds_str->str, start - ds_str->str);
+ dynstr_append_mem_checked(&ds_tmp, replace_str, replace_len);
+ dynstr_append_checked(&ds_tmp, start + search_len);
+ dynstr_set_checked(ds_str, ds_tmp.str);
dynstr_free(&ds_tmp);
return 0;
}
@@ -3951,10 +4015,7 @@ static my_bool get_view_structure(char *table, char* db)
my_snprintf(query, sizeof(query), "SHOW CREATE TABLE %s", result_table);
if (mysql_query_with_error_report(mysql, &table_res, query))
- {
- safe_exit(EX_MYSQLERR);
DBUG_RETURN(0);
- }
/* Check if this is a view */
field= mysql_fetch_field_direct(table_res, 0);
@@ -3968,10 +4029,8 @@ static my_bool get_view_structure(char *table, char* db)
if (path)
{
if (!(sql_file= open_sql_file_for_table(table)))
- {
- safe_exit(EX_MYSQLERR);
DBUG_RETURN(1);
- }
+
write_header(sql_file, db);
}
@@ -4017,14 +4076,14 @@ static my_bool get_view_structure(char *table, char* db)
/* Save the result of SHOW CREATE TABLE in ds_view */
row= mysql_fetch_row(table_res);
lengths= mysql_fetch_lengths(table_res);
- init_dynamic_string(&ds_view, row[1], lengths[1] + 1, 1024);
+ init_dynamic_string_checked(&ds_view, row[1], lengths[1] + 1, 1024);
mysql_free_result(table_res);
/* Get the result from "select ... information_schema" */
if (!(table_res= mysql_store_result(mysql)) ||
!(row= mysql_fetch_row(table_res)))
{
- safe_exit(EX_MYSQLERR);
+ DB_error(mysql, "when trying to save the result of SHOW CREATE TABLE in ds_view.");
DBUG_RETURN(1);
}
@@ -4096,6 +4155,45 @@ static my_bool get_view_structure(char *table, char* db)
DBUG_RETURN(0);
}
+/*
+ The following functions are wrappers for the dynamic string functions
+ and if they fail, the wrappers will terminate the current process.
+*/
+
+#define DYNAMIC_STR_ERROR_MSG "Couldn't perform DYNAMIC_STRING operation"
+
+static void init_dynamic_string_checked(DYNAMIC_STRING *str, const char *init_str,
+ uint init_alloc, uint alloc_increment)
+{
+ if (init_dynamic_string(str, init_str, init_alloc, alloc_increment))
+ die(EX_MYSQLERR, DYNAMIC_STR_ERROR_MSG);
+}
+
+static void dynstr_append_checked(DYNAMIC_STRING* dest, const char* src)
+{
+ if (dynstr_append(dest, src))
+ die(EX_MYSQLERR, DYNAMIC_STR_ERROR_MSG);
+}
+
+static void dynstr_set_checked(DYNAMIC_STRING *str, const char *init_str)
+{
+ if (dynstr_set(str, init_str))
+ die(EX_MYSQLERR, DYNAMIC_STR_ERROR_MSG);
+}
+
+static void dynstr_append_mem_checked(DYNAMIC_STRING *str, const char *append,
+ uint length)
+{
+ if (dynstr_append_mem(str, append, length))
+ die(EX_MYSQLERR, DYNAMIC_STR_ERROR_MSG);
+}
+
+static void dynstr_realloc_checked(DYNAMIC_STRING *str, ulong additional_size)
+{
+ if (dynstr_realloc(str, additional_size))
+ die(EX_MYSQLERR, DYNAMIC_STR_ERROR_MSG);
+}
+
int main(int argc, char **argv)
{
diff --git a/client/mysqlslap.c b/client/mysqlslap.c
index ad2c8685ba1..ef11f4bab5b 100644
--- a/client/mysqlslap.c
+++ b/client/mysqlslap.c
@@ -62,7 +62,6 @@ TODO:
Add language for better tests
String length for files and those put on the command line are not
setup to handle binary data.
- Report results of each thread into the lock file we use.
More stats
Break up tests and run them on multiple hosts at once.
Allow output to be fed into a database directly.
@@ -71,16 +70,18 @@ TODO:
#define SHOW_VERSION "0.9"
-#define HUGE_STRING_LENGTH 8096
+#define HUGE_STRING_LENGTH 8196
#define RAND_STRING_SIZE 126
+/* Types */
+#define SELECT_TYPE 0
+#define UPDATE_TYPE 1
+#define INSERT_TYPE 2
+#define UPDATE_TYPE_REQUIRES_PREFIX 3
+#define CREATE_TABLE_TYPE 4
+#define SELECT_TYPE_REQUIRES_PREFIX 5
+
#include "client_priv.h"
-#ifdef HAVE_LIBPTHREAD
-#include <my_pthread.h>
-#endif
-#include <my_sys.h>
-#include <m_string.h>
-#include <mysql.h>
#include <mysqld_error.h>
#include <my_dir.h>
#include <signal.h>
@@ -92,9 +93,6 @@ TODO:
#endif
#include <ctype.h>
-#define MYSLAPLOCK "/myslaplock.lck"
-#define MYSLAPLOCK_DIR "/tmp"
-
#ifdef __WIN__
#define srandom srand
#define random rand
@@ -105,10 +103,23 @@ TODO:
static char *shared_memory_base_name=0;
#endif
+/* Global Thread counter */
+uint thread_counter;
+pthread_mutex_t counter_mutex;
+pthread_cond_t count_threshhold;
+uint master_wakeup;
+pthread_mutex_t sleeper_mutex;
+pthread_cond_t sleep_threshhold;
+
static char **defaults_argv;
+char **primary_keys;
+unsigned long long primary_keys_number_of;
+
static char *host= NULL, *opt_password= NULL, *user= NULL,
*user_supplied_query= NULL,
+ *user_supplied_pre_statements= NULL,
+ *user_supplied_post_statements= NULL,
*default_engine= NULL,
*opt_mysql_unix_port= NULL;
@@ -116,26 +127,35 @@ const char *delimiter= "\n";
const char *create_schema_string= "mysqlslap";
-const char *lock_directory;
-char lock_file_str[FN_REFLEN];
-
static my_bool opt_preserve;
static my_bool opt_only_print= FALSE;
-static my_bool opt_slave;
-
static my_bool opt_compress= FALSE, tty_password= FALSE,
opt_silent= FALSE,
+ auto_generate_sql_autoincrement= FALSE,
+ auto_generate_sql_guid_primary= FALSE,
auto_generate_sql= FALSE;
const char *auto_generate_sql_type= "mixed";
static unsigned long connect_flags= CLIENT_MULTI_RESULTS;
-static int verbose, num_int_cols, num_char_cols, delimiter_length;
-static int iterations;
+static int verbose, delimiter_length;
+const char *num_int_cols_opt;
+const char *num_char_cols_opt;
+/* Yes, we do set defaults here */
+static unsigned int num_int_cols= 1;
+static unsigned int num_char_cols= 1;
+static unsigned int num_int_cols_index= 0;
+static unsigned int num_char_cols_index= 0;
+
+static unsigned int iterations;
static char *default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME;
static ulonglong actual_queries= 0;
+static ulonglong auto_actual_queries;
+static ulonglong auto_generate_sql_unique_write_number;
+static ulonglong auto_generate_sql_unique_query_number;
+static unsigned int auto_generate_sql_secondary_indexes;
static ulonglong num_of_query;
static ulonglong auto_generate_sql_number;
const char *concurrency_str= NULL;
@@ -150,7 +170,6 @@ static uint opt_protocol= 0;
static int get_options(int *argc,char ***argv);
static uint opt_mysql_port= 0;
-static uint opt_use_threads;
static const char *load_default_groups[]= { "mysqlslap","client",0 };
@@ -159,9 +178,22 @@ typedef struct statement statement;
struct statement {
char *string;
size_t length;
+ unsigned char type;
+ char *option;
+ size_t option_length;
statement *next;
};
+typedef struct option_string option_string;
+
+struct option_string {
+ char *string;
+ size_t length;
+ char *option;
+ size_t option_length;
+ option_string *next;
+};
+
typedef struct stats stats;
struct stats {
@@ -175,7 +207,6 @@ typedef struct thread_context thread_context;
struct thread_context {
statement *stmt;
ulonglong limit;
- bool thread;
};
typedef struct conclusions conclusions;
@@ -192,27 +223,36 @@ struct conclusions {
unsigned long long min_rows;
};
+static option_string *engine_options= NULL;
+static statement *pre_statements= NULL;
+static statement *post_statements= NULL;
static statement *create_statements= NULL,
- *engine_statements= NULL,
*query_statements= NULL;
/* Prototypes */
void print_conclusions(conclusions *con);
void print_conclusions_csv(conclusions *con);
-void generate_stats(conclusions *con, statement *eng, stats *sptr);
+void generate_stats(conclusions *con, option_string *eng, stats *sptr);
uint parse_comma(const char *string, uint **range);
uint parse_delimiter(const char *script, statement **stmt, char delm);
+uint parse_option(const char *origin, option_string **stmt, char delm);
static int drop_schema(MYSQL *mysql, const char *db);
uint get_random_string(char *buf);
static statement *build_table_string(void);
static statement *build_insert_string(void);
-static statement *build_query_string(void);
+static statement *build_update_string(void);
+static statement * build_select_string(my_bool key);
+static int generate_primary_key_list(MYSQL *mysql, option_string *engine_stmt);
+static int drop_primary_key_list(void);
static int create_schema(MYSQL *mysql, const char *db, statement *stmt,
- statement *engine_stmt);
+ option_string *engine_stmt);
static int run_scheduler(stats *sptr, statement *stmts, uint concur,
ulonglong limit);
-int run_task(thread_context *con);
+pthread_handler_t run_task(void *p);
void statement_cleanup(statement *stmt);
+void option_cleanup(option_string *stmt);
+void concurrency_loop(MYSQL *mysql, uint current, option_string *eptr);
+static int run_statements(MYSQL *mysql, statement *stmt);
static const char ALPHANUMERICS[]=
"0123456789ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstuvwxyz";
@@ -246,13 +286,7 @@ static int gettimeofday(struct timeval *tp, void *tzp)
int main(int argc, char **argv)
{
MYSQL mysql;
- int x;
- unsigned long long client_limit;
- statement *eptr;
-
-#ifdef __WIN__
- opt_use_threads= 1;
-#endif
+ option_string *eptr;
MY_INIT(argv[0]);
@@ -309,78 +343,63 @@ int main(int argc, char **argv)
}
}
+ VOID(pthread_mutex_init(&counter_mutex, NULL));
+ VOID(pthread_cond_init(&count_threshhold, NULL));
+ VOID(pthread_mutex_init(&sleeper_mutex, NULL));
+ VOID(pthread_cond_init(&sleep_threshhold, NULL));
+
/* Main iterations loop */
- eptr= engine_statements;
+ eptr= engine_options;
do
{
/* For the final stage we run whatever queries we were asked to run */
uint *current;
- conclusions conclusion;
-
- for (current= concurrency; current && *current; current++)
- {
- stats *head_sptr;
- stats *sptr;
-
- head_sptr= (stats *)my_malloc(sizeof(stats) * iterations, MYF(MY_ZEROFILL));
-
- bzero(&conclusion, sizeof(conclusions));
- if (num_of_query)
- client_limit= num_of_query / *current;
- else
- client_limit= actual_queries;
-
- for (x= 0, sptr= head_sptr; x < iterations; x++, sptr++)
- {
- /*
- We might not want to load any data, such as when we are calling
- a stored_procedure that doesn't use data, or we know we already have
- data in the table.
- */
- if (!opt_preserve)
- drop_schema(&mysql, create_schema_string);
- /* First we create */
- if (create_statements)
- create_schema(&mysql, create_schema_string, create_statements, eptr);
+ if (verbose >= 2)
+ printf("Starting Concurrency Test\n");
- run_scheduler(sptr, query_statements, *current, client_limit);
+ if (*concurrency)
+ {
+ for (current= concurrency; current && *current; current++)
+ concurrency_loop(&mysql, *current, eptr);
+ }
+ else
+ {
+ uint infinite= 1;
+ do {
+ concurrency_loop(&mysql, infinite, eptr);
}
-
- generate_stats(&conclusion, eptr, head_sptr);
-
- if (!opt_silent)
- print_conclusions(&conclusion);
- if (opt_csv_str)
- print_conclusions_csv(&conclusion);
-
- my_free((byte *)head_sptr, MYF(0));
+ while (infinite++);
}
if (!opt_preserve)
drop_schema(&mysql, create_schema_string);
+
} while (eptr ? (eptr= eptr->next) : 0);
+ VOID(pthread_mutex_destroy(&counter_mutex));
+ VOID(pthread_cond_destroy(&count_threshhold));
+ VOID(pthread_mutex_destroy(&sleeper_mutex));
+ VOID(pthread_cond_destroy(&sleep_threshhold));
+
if (!opt_only_print)
mysql_close(&mysql); /* Close & free connection */
-
- /* Remove lock file */
- my_delete(lock_file_str, MYF(0));
-
/* now free all the strings we created */
if (opt_password)
- my_free(opt_password, MYF(0));
+ my_free((gptr)opt_password, MYF(0));
- my_free((byte *)concurrency, MYF(0));
+ my_free((gptr)concurrency, MYF(0));
statement_cleanup(create_statements);
- statement_cleanup(engine_statements);
statement_cleanup(query_statements);
+ statement_cleanup(pre_statements);
+ statement_cleanup(post_statements);
+ option_cleanup(engine_options);
#ifdef HAVE_SMEM
if (shared_memory_base_name)
- my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
+ my_free((gptr)shared_memory_base_name, MYF(MY_ALLOW_ZERO_PTR));
#endif
free_defaults(defaults_argv);
my_end(0);
@@ -388,6 +407,76 @@ int main(int argc, char **argv)
return 0;
}
+void concurrency_loop(MYSQL *mysql, uint current, option_string *eptr)
+{
+ unsigned int x;
+ stats *head_sptr;
+ stats *sptr;
+ conclusions conclusion;
+ unsigned long long client_limit;
+
+ head_sptr= (stats *)my_malloc(sizeof(stats) * iterations,
+ MYF(MY_ZEROFILL|MY_FAE|MY_WME));
+
+ bzero(&conclusion, sizeof(conclusions));
+
+ if (auto_actual_queries)
+ client_limit= auto_actual_queries;
+ else if (num_of_query)
+ client_limit= num_of_query / current;
+ else
+ client_limit= actual_queries;
+
+ for (x= 0, sptr= head_sptr; x < iterations; x++, sptr++)
+ {
+ /*
+ We might not want to load any data, such as when we are calling
+ a stored_procedure that doesn't use data, or we know we already have
+ data in the table.
+ */
+ if (!opt_preserve)
+ drop_schema(mysql, create_schema_string);
+
+ /* First we create */
+ if (create_statements)
+ create_schema(mysql, create_schema_string, create_statements, eptr);
+
+ /*
+ If we generated GUID we need to build a list of them from creation that
+ we can later use.
+ */
+ if (verbose >= 2)
+ printf("Generating primary key list\n");
+ if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
+ generate_primary_key_list(mysql, eptr);
+
+ if (pre_statements)
+ run_statements(mysql, pre_statements);
+
+ run_scheduler(sptr, query_statements, current, client_limit);
+
+ if (post_statements)
+ run_statements(mysql, post_statements);
+
+ /* We are finished with this run */
+ if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
+ drop_primary_key_list();
+ }
+
+ if (verbose >= 2)
+ printf("Generating stats\n");
+
+ generate_stats(&conclusion, eptr, head_sptr);
+
+ if (!opt_silent)
+ print_conclusions(&conclusion);
+ if (opt_csv_str)
+ print_conclusions_csv(&conclusion);
+
+ my_free((gptr)head_sptr, MYF(0));
+
+}
+
static struct my_option my_long_options[] =
{
@@ -397,10 +486,42 @@ static struct my_option my_long_options[] =
"Generate SQL where not supplied by file or command line.",
(gptr*) &auto_generate_sql, (gptr*) &auto_generate_sql,
0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"auto-generate-sql-add-autoincrement", OPT_SLAP_AUTO_GENERATE_ADD_AUTO,
+ "Add autoincrement to auto-generated tables.",
+ (gptr*) &auto_generate_sql_autoincrement,
+ (gptr*) &auto_generate_sql_autoincrement,
+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"auto-generate-sql-execute-number", OPT_SLAP_AUTO_GENERATE_EXECUTE_QUERIES,
+ "Set this number to generate a set number of queries to run.\n",
+ (gptr*) &auto_actual_queries, (gptr*) &auto_actual_queries,
+ 0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"auto-generate-sql-guid-primary", OPT_SLAP_AUTO_GENERATE_GUID_PRIMARY,
+ "Add GUID based primary keys to auto-generated tables.",
+ (gptr*) &auto_generate_sql_guid_primary,
+ (gptr*) &auto_generate_sql_guid_primary,
+ 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"auto-generate-sql-load-type", OPT_SLAP_AUTO_GENERATE_SQL_LOAD_TYPE,
- "Load types are mixed, write, or read. Default is mixed\n",
+ "Load types are mixed, update, write, key, or read. Default is mixed\n",
(gptr*) &auto_generate_sql_type, (gptr*) &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,
+ "Number of secondary indexes to add auto-generated tables.",
+ (gptr*) &auto_generate_sql_secondary_indexes,
+ (gptr*) &auto_generate_sql_secondary_indexes, 0,
+ GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"auto-generate-sql-unique-query-number",
+ OPT_SLAP_AUTO_GENERATE_UNIQUE_QUERY_NUM,
+ "Number of unique queries auto tests",
+ (gptr*) &auto_generate_sql_unique_query_number,
+ (gptr*) &auto_generate_sql_unique_query_number,
+ 0, GET_ULL, REQUIRED_ARG, 10, 0, 0, 0, 0, 0},
+ {"auto-generate-sql-unique-write-number",
+ OPT_SLAP_AUTO_GENERATE_UNIQUE_WRITE_NUM,
+ "Number of unique queries for auto-generate-sql-write-number",
+ (gptr*) &auto_generate_sql_unique_write_number,
+ (gptr*) &auto_generate_sql_unique_write_number,
+ 0, GET_ULL, REQUIRED_ARG, 10, 0, 0, 0, 0, 0},
{"auto-generate-sql-write-number", OPT_SLAP_AUTO_GENERATE_WRITE_NUM,
"Number of rows to insert to used in read and write loads (default is 100).\n",
(gptr*) &auto_generate_sql_number, (gptr*) &auto_generate_sql_number,
@@ -435,17 +556,14 @@ static struct my_option my_long_options[] =
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"iterations", 'i', "Number of times too run the tests.", (gptr*) &iterations,
(gptr*) &iterations, 0, GET_UINT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0},
- {"lock-directory", OPT_MYSQL_LOCK_DIRECTORY, "Directory to use to keep locks.",
- (gptr*) &lock_directory, (gptr*) &lock_directory, 0, GET_STR,
- REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"number-char-cols", 'x',
"Number of VARCHAR columns to create table with if specifying --auto-generate-sql ",
- (gptr*) &num_char_cols, (gptr*) &num_char_cols, 0, GET_UINT, REQUIRED_ARG,
- 1, 0, 0, 0, 0, 0},
+ (gptr*) &num_char_cols_opt, (gptr*) &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 table with if specifying --auto-generate-sql.",
- (gptr*) &num_int_cols, (gptr*) &num_int_cols, 0, GET_UINT, REQUIRED_ARG,
- 1, 0, 0, 0, 0, 0},
+ (gptr*) &num_int_cols_opt, (gptr*) &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).",
(gptr*) &num_of_query, (gptr*) &num_of_query, 0,
@@ -465,6 +583,16 @@ static struct my_option my_long_options[] =
{"port", 'P', "Port number to use for connection.", (gptr*) &opt_mysql_port,
(gptr*) &opt_mysql_port, 0, GET_UINT, REQUIRED_ARG, MYSQL_PORT, 0, 0, 0, 0,
0},
+ {"post-query", OPT_SLAP_POST_QUERY,
+ "Query to run or file containing query to run after executing.",
+ (gptr*) &user_supplied_post_statements,
+ (gptr*) &user_supplied_post_statements,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"pre-query", OPT_SLAP_PRE_QUERY,
+ "Query to run or file containing query to run before executing.",
+ (gptr*) &user_supplied_pre_statements,
+ (gptr*) &user_supplied_pre_statements,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"preserve-schema", OPT_MYSQL_PRESERVE_SCHEMA,
"Preserve the schema from the mysqlslap run, this happens unless "
"--auto-generate-sql or --create are used.",
@@ -485,17 +613,10 @@ static struct my_option my_long_options[] =
{"silent", 's', "Run program in silent mode - no output.",
(gptr*) &opt_silent, (gptr*) &opt_silent, 0, GET_BOOL, NO_ARG,
0, 0, 0, 0, 0, 0},
- {"slave", OPT_MYSQL_SLAP_SLAVE, "Follow master locks for other slap clients",
- (gptr*) &opt_slave, (gptr*) &opt_slave, 0, GET_BOOL, NO_ARG,
- 0, 0, 0, 0, 0, 0},
{"socket", 'S', "Socket file to use for connection.",
(gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#include <sslopt-longopts.h>
- {"use-threads", OPT_USE_THREADS,
- "Use pthread calls instead of fork() calls (default on Windows)",
- (gptr*) &opt_use_threads, (gptr*) &opt_use_threads, 0,
- GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#ifndef DONT_ALLOW_USER_CHANGE
{"user", 'u', "User for login if not current user.", (gptr*) &user,
(gptr*) &user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
@@ -552,7 +673,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
if (argument)
{
char *start= argument;
- my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
+ my_free((gptr)opt_password, MYF(MY_ALLOW_ZERO_PTR));
opt_password= my_strdup(argument,MYF(MY_FAE));
while (*argument) *argument++= 'x'; /* Destroy argument */
if (*start)
@@ -614,43 +735,196 @@ get_random_string(char *buf)
static statement *
build_table_string(void)
{
- char buf[512];
- int col_count;
+ char buf[HUGE_STRING_LENGTH];
+ unsigned int col_count;
statement *ptr;
DYNAMIC_STRING table_string;
DBUG_ENTER("build_table_string");
- DBUG_PRINT("info", ("num int cols %d num char cols %d",
+ DBUG_PRINT("info", ("num int cols %u num char cols %u",
num_int_cols, num_char_cols));
init_dynamic_string(&table_string, "", 1024, 1024);
dynstr_append(&table_string, "CREATE TABLE `t1` (");
- for (col_count= 1; col_count <= num_int_cols; col_count++)
+
+ if (auto_generate_sql_autoincrement)
{
- sprintf(buf, "intcol%d INT(32)", col_count);
- dynstr_append(&table_string, buf);
+ dynstr_append(&table_string, "id serial");
- if (col_count < num_int_cols || num_char_cols > 0)
+ if (num_int_cols || num_char_cols)
dynstr_append(&table_string, ",");
}
- for (col_count= 1; col_count <= num_char_cols; col_count++)
+
+ if (auto_generate_sql_guid_primary)
{
- sprintf(buf, "charcol%d VARCHAR(128)", col_count);
- dynstr_append(&table_string, buf);
+ dynstr_append(&table_string, "id varchar(32) primary key");
- if (col_count < num_char_cols)
+ if (num_int_cols || num_char_cols || auto_generate_sql_guid_primary)
+ dynstr_append(&table_string, ",");
+ }
+
+ if (auto_generate_sql_secondary_indexes)
+ {
+ unsigned int count;
+
+ for (count= 0; count < auto_generate_sql_secondary_indexes; count++)
+ {
+ if (count) /* Except for the first pass we add a comma */
+ dynstr_append(&table_string, ",");
+
+ if (snprintf(buf, HUGE_STRING_LENGTH, "id%d varchar(32) unique key", count)
+ > HUGE_STRING_LENGTH)
+ {
+ fprintf(stderr, "Memory Allocation error in create table\n");
+ exit(1);
+ }
+ dynstr_append(&table_string, buf);
+ }
+
+ if (num_int_cols || num_char_cols)
dynstr_append(&table_string, ",");
}
+
+ if (num_int_cols)
+ for (col_count= 1; col_count <= num_int_cols; col_count++)
+ {
+ if (num_int_cols_index)
+ {
+ if (snprintf(buf, HUGE_STRING_LENGTH, "intcol%d INT(32), INDEX(intcol%d)",
+ col_count, col_count) > HUGE_STRING_LENGTH)
+ {
+ fprintf(stderr, "Memory Allocation error in create table\n");
+ exit(1);
+ }
+ }
+ else
+ {
+ if (snprintf(buf, HUGE_STRING_LENGTH, "intcol%d INT(32) ", col_count)
+ > HUGE_STRING_LENGTH)
+ {
+ fprintf(stderr, "Memory Allocation error in create table\n");
+ exit(1);
+ }
+ }
+ dynstr_append(&table_string, buf);
+
+ if (col_count < num_int_cols || num_char_cols > 0)
+ dynstr_append(&table_string, ",");
+ }
+
+ if (num_char_cols)
+ for (col_count= 1; col_count <= num_char_cols; col_count++)
+ {
+ if (num_char_cols_index)
+ {
+ if (snprintf(buf, HUGE_STRING_LENGTH,
+ "charcol%d VARCHAR(128), INDEX(charcol%d) ",
+ col_count, col_count) > HUGE_STRING_LENGTH)
+ {
+ fprintf(stderr, "Memory Allocation error in creating table\n");
+ exit(1);
+ }
+ }
+ else
+ {
+ if (snprintf(buf, HUGE_STRING_LENGTH, "charcol%d VARCHAR(128)",
+ col_count) > HUGE_STRING_LENGTH)
+ {
+ fprintf(stderr, "Memory Allocation error in creating table\n");
+ exit(1);
+ }
+ }
+ dynstr_append(&table_string, buf);
+
+ if (col_count < num_char_cols)
+ dynstr_append(&table_string, ",");
+ }
+
dynstr_append(&table_string, ")");
- ptr= (statement *)my_malloc(sizeof(statement), MYF(MY_ZEROFILL));
- ptr->string = (char *)my_malloc(table_string.length+1, MYF(MY_WME));
+ ptr= (statement *)my_malloc(sizeof(statement),
+ MYF(MY_ZEROFILL|MY_FAE|MY_WME));
+ ptr->string = (char *)my_malloc(table_string.length+1,
+ MYF(MY_ZEROFILL|MY_FAE|MY_WME));
ptr->length= table_string.length+1;
+ ptr->type= CREATE_TABLE_TYPE;
strmov(ptr->string, table_string.str);
dynstr_free(&table_string);
DBUG_RETURN(ptr);
}
+/*
+ build_update_string()
+
+ This function builds insert statements when the user opts to not supply
+ an insert file or string containing insert data
+*/
+static statement *
+build_update_string(void)
+{
+ char buf[HUGE_STRING_LENGTH];
+ unsigned int col_count;
+ statement *ptr;
+ DYNAMIC_STRING update_string;
+ DBUG_ENTER("build_update_string");
+
+ init_dynamic_string(&update_string, "", 1024, 1024);
+
+ dynstr_append(&update_string, "UPDATE t1 SET ");
+
+ if (num_int_cols)
+ for (col_count= 1; col_count <= num_int_cols; col_count++)
+ {
+ if (snprintf(buf, HUGE_STRING_LENGTH, "intcol%d = %ld", col_count,
+ random()) > HUGE_STRING_LENGTH)
+ {
+ fprintf(stderr, "Memory Allocation error in creating update\n");
+ exit(1);
+ }
+ dynstr_append(&update_string, buf);
+
+ if (col_count < num_int_cols || num_char_cols > 0)
+ dynstr_append_mem(&update_string, ",", 1);
+ }
+
+ if (num_char_cols)
+ for (col_count= 1; col_count <= num_char_cols; col_count++)
+ {
+ char rand_buffer[RAND_STRING_SIZE];
+ int buf_len= get_random_string(rand_buffer);
+
+ if (snprintf(buf, HUGE_STRING_LENGTH, "charcol%d = '%.*s'", col_count,
+ buf_len, rand_buffer)
+ > HUGE_STRING_LENGTH)
+ {
+ fprintf(stderr, "Memory Allocation error in creating update\n");
+ exit(1);
+ }
+ dynstr_append(&update_string, buf);
+
+ if (col_count < num_char_cols)
+ dynstr_append_mem(&update_string, ",", 1);
+ }
+
+ if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
+ dynstr_append(&update_string, " WHERE id = ");
+
+
+ ptr= (statement *)my_malloc(sizeof(statement),
+ MYF(MY_ZEROFILL|MY_FAE|MY_WME));
+
+ ptr->string= (char *)my_malloc(update_string.length + 1,
+ MYF(MY_ZEROFILL|MY_FAE|MY_WME));
+ ptr->length= update_string.length+1;
+ if (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary)
+ ptr->type= UPDATE_TYPE_REQUIRES_PREFIX ;
+ else
+ ptr->type= UPDATE_TYPE;
+ strmov(ptr->string, update_string.str);
+ dynstr_free(&update_string);
+ DBUG_RETURN(ptr);
+}
+
/*
build_insert_string()
@@ -661,38 +935,82 @@ build_table_string(void)
static statement *
build_insert_string(void)
{
- char buf[RAND_STRING_SIZE];
- int col_count;
+ char buf[HUGE_STRING_LENGTH];
+ unsigned int col_count;
statement *ptr;
DYNAMIC_STRING insert_string;
DBUG_ENTER("build_insert_string");
init_dynamic_string(&insert_string, "", 1024, 1024);
- dynstr_append_mem(&insert_string, "INSERT INTO t1 VALUES (", 23);
- for (col_count= 1; col_count <= num_int_cols; col_count++)
+ dynstr_append(&insert_string, "INSERT INTO t1 VALUES (");
+
+ if (auto_generate_sql_autoincrement)
{
- sprintf(buf, "%ld", random());
- dynstr_append(&insert_string, buf);
+ dynstr_append(&insert_string, "NULL");
- if (col_count < num_int_cols || num_char_cols > 0)
- dynstr_append_mem(&insert_string, ",", 1);
+ if (num_int_cols || num_char_cols)
+ dynstr_append(&insert_string, ",");
}
- for (col_count= 1; col_count <= num_char_cols; col_count++)
+
+ if (auto_generate_sql_guid_primary)
{
- int buf_len= get_random_string(buf);
- dynstr_append_mem(&insert_string, "'", 1);
- dynstr_append_mem(&insert_string, buf, buf_len);
- dynstr_append_mem(&insert_string, "'", 1);
+ dynstr_append(&insert_string, "uuid()");
- if (col_count < num_char_cols)
- dynstr_append_mem(&insert_string, ",", 1);
+ if (num_int_cols || num_char_cols)
+ dynstr_append(&insert_string, ",");
+ }
+
+ if (auto_generate_sql_secondary_indexes)
+ {
+ unsigned int count;
+
+ for (count= 0; count < auto_generate_sql_secondary_indexes; count++)
+ {
+ if (count) /* Except for the first pass we add a comma */
+ dynstr_append(&insert_string, ",");
+
+ dynstr_append(&insert_string, "uuid()");
+ }
+
+ if (num_int_cols || num_char_cols)
+ dynstr_append(&insert_string, ",");
}
+
+ if (num_int_cols)
+ for (col_count= 1; col_count <= num_int_cols; col_count++)
+ {
+ if (snprintf(buf, HUGE_STRING_LENGTH, "%ld", random()) > HUGE_STRING_LENGTH)
+ {
+ fprintf(stderr, "Memory Allocation error in creating insert\n");
+ exit(1);
+ }
+ dynstr_append(&insert_string, buf);
+
+ if (col_count < num_int_cols || num_char_cols > 0)
+ dynstr_append_mem(&insert_string, ",", 1);
+ }
+
+ if (num_char_cols)
+ for (col_count= 1; col_count <= num_char_cols; col_count++)
+ {
+ int buf_len= get_random_string(buf);
+ dynstr_append_mem(&insert_string, "'", 1);
+ dynstr_append_mem(&insert_string, buf, buf_len);
+ dynstr_append_mem(&insert_string, "'", 1);
+
+ if (col_count < num_char_cols)
+ dynstr_append_mem(&insert_string, ",", 1);
+ }
+
dynstr_append_mem(&insert_string, ")", 1);
- ptr= (statement *)my_malloc(sizeof(statement), MYF(MY_ZEROFILL));
- ptr->string= (char *)my_malloc(insert_string.length+1, MYF(MY_WME));
+ ptr= (statement *)my_malloc(sizeof(statement),
+ MYF(MY_ZEROFILL|MY_FAE|MY_WME));
+ ptr->string= (char *)my_malloc(insert_string.length + 1,
+ MYF(MY_ZEROFILL|MY_FAE|MY_WME));
ptr->length= insert_string.length+1;
+ ptr->type= INSERT_TYPE;
strmov(ptr->string, insert_string.str);
dynstr_free(&insert_string);
DBUG_RETURN(ptr);
@@ -700,26 +1018,31 @@ build_insert_string(void)
/*
- build_query_string()
+ build_select_string()
This function builds a query if the user opts to not supply a query
statement or file containing a query statement
*/
static statement *
-build_query_string(void)
+build_select_string(my_bool key)
{
- char buf[512];
- int col_count;
+ char buf[HUGE_STRING_LENGTH];
+ unsigned int col_count;
statement *ptr;
static DYNAMIC_STRING query_string;
- DBUG_ENTER("build_query_string");
+ DBUG_ENTER("build_select_string");
init_dynamic_string(&query_string, "", 1024, 1024);
dynstr_append_mem(&query_string, "SELECT ", 7);
for (col_count= 1; col_count <= num_int_cols; col_count++)
{
- sprintf(buf, "intcol%d", col_count);
+ if (snprintf(buf, HUGE_STRING_LENGTH, "intcol%d", col_count)
+ > HUGE_STRING_LENGTH)
+ {
+ fprintf(stderr, "Memory Allocation error in creating select\n");
+ exit(1);
+ }
dynstr_append(&query_string, buf);
if (col_count < num_int_cols || num_char_cols > 0)
@@ -728,17 +1051,34 @@ build_query_string(void)
}
for (col_count= 1; col_count <= num_char_cols; col_count++)
{
- sprintf(buf, "charcol%d", col_count);
+ if (snprintf(buf, HUGE_STRING_LENGTH, "charcol%d", col_count)
+ > HUGE_STRING_LENGTH)
+ {
+ fprintf(stderr, "Memory Allocation error in creating select\n");
+ exit(1);
+ }
dynstr_append(&query_string, buf);
if (col_count < num_char_cols)
dynstr_append_mem(&query_string, ",", 1);
}
- dynstr_append_mem(&query_string, " FROM t1", 8);
- ptr= (statement *)my_malloc(sizeof(statement), MYF(MY_ZEROFILL));
- ptr->string= (char *)my_malloc(query_string.length+1, MYF(MY_WME));
+ dynstr_append(&query_string, " FROM t1");
+
+ if ((key) &&
+ (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary))
+ dynstr_append(&query_string, " WHERE id = ");
+
+ ptr= (statement *)my_malloc(sizeof(statement),
+ MYF(MY_ZEROFILL|MY_FAE|MY_WME));
+ ptr->string= (char *)my_malloc(query_string.length + 1,
+ MYF(MY_ZEROFILL|MY_FAE|MY_WME));
ptr->length= query_string.length+1;
+ if ((key) &&
+ (auto_generate_sql_autoincrement || auto_generate_sql_guid_primary))
+ ptr->type= SELECT_TYPE_REQUIRES_PREFIX;
+ else
+ ptr->type= SELECT_TYPE;
strmov(ptr->string, query_string.str);
dynstr_free(&query_string);
DBUG_RETURN(ptr);
@@ -773,12 +1113,40 @@ get_options(int *argc,char ***argv)
exit(1);
}
- parse_comma(concurrency_str ? concurrency_str : "1", &concurrency);
+ if (auto_generate_sql && auto_generate_sql_guid_primary &&
+ auto_generate_sql_autoincrement)
+ {
+ fprintf(stderr,
+ "%s: Either auto-generate-sql-guid-primary or auto-generate-sql-add-autoincrement can be used!\n",
+ my_progname);
+ exit(1);
+ }
- if (lock_directory)
- snprintf(lock_file_str, FN_REFLEN, "%s/%s", lock_directory, MYSLAPLOCK);
- else
- snprintf(lock_file_str, FN_REFLEN, "%s/%s", MYSLAPLOCK_DIR, MYSLAPLOCK);
+ /*
+ We are testing to make sure that if someone specified a key search
+ that we actually added a key!
+ */
+ if (auto_generate_sql && auto_generate_sql_type[0] == 'k')
+ if ( auto_generate_sql_autoincrement == FALSE &&
+ auto_generate_sql_guid_primary == FALSE)
+ {
+ fprintf(stderr,
+ "%s: Can't perform key test without a primary key!\n",
+ my_progname);
+ exit(1);
+ }
+
+
+
+ if (auto_generate_sql && num_of_query && auto_actual_queries)
+ {
+ fprintf(stderr,
+ "%s: Either auto-generate-sql-execute-number or number-of-queries can be used!\n",
+ my_progname);
+ exit(1);
+ }
+
+ parse_comma(concurrency_str ? concurrency_str : "1", &concurrency);
if (opt_csv_str)
{
@@ -803,23 +1171,76 @@ get_options(int *argc,char ***argv)
if (opt_only_print)
opt_silent= TRUE;
+ if (num_int_cols_opt)
+ {
+ option_string *str;
+ parse_option(num_int_cols_opt, &str, ',');
+ num_int_cols= atoi(str->string);
+ if (str->option)
+ num_int_cols_index= atoi(str->option);
+ option_cleanup(str);
+ }
+
+ if (num_char_cols_opt)
+ {
+ option_string *str;
+ parse_option(num_char_cols_opt, &str, ',');
+ num_char_cols= atoi(str->string);
+ if (str->option)
+ num_char_cols_index= atoi(str->option);
+ else
+ num_char_cols_index= 0;
+ option_cleanup(str);
+ }
+
+
if (auto_generate_sql)
{
unsigned long long x= 0;
statement *ptr_statement;
+ if (verbose >= 2)
+ printf("Building Create Statements for Auto\n");
+
create_statements= build_table_string();
+ /*
+ Pre-populate table
+ */
+ for (ptr_statement= create_statements, x= 0;
+ x < auto_generate_sql_unique_write_number;
+ x++, ptr_statement= ptr_statement->next)
+ {
+ ptr_statement->next= build_insert_string();
+ }
+
+ if (verbose >= 2)
+ printf("Building Query Statements for Auto\n");
if (auto_generate_sql_type[0] == 'r')
{
- for (ptr_statement= create_statements, x= 0;
- x < auto_generate_sql_number;
+ if (verbose >= 2)
+ printf("Generating SELECT Statements for Auto\n");
+
+ query_statements= build_select_string(FALSE);
+ for (ptr_statement= query_statements, x= 0;
+ x < auto_generate_sql_unique_query_number;
x++, ptr_statement= ptr_statement->next)
{
- ptr_statement->next= build_insert_string();
+ ptr_statement->next= build_select_string(FALSE);
}
+ }
+ else if (auto_generate_sql_type[0] == 'k')
+ {
+ if (verbose >= 2)
+ printf("Generating SELECT for keys Statements for Auto\n");
- query_statements= build_query_string();
+ query_statements= build_select_string(TRUE);
+ for (ptr_statement= query_statements, x= 0;
+ x < auto_generate_sql_unique_query_number;
+ x++, ptr_statement= ptr_statement->next)
+ {
+ ptr_statement->next= build_select_string(TRUE);
+ }
}
else if (auto_generate_sql_type[0] == 'w')
{
@@ -828,14 +1249,26 @@ get_options(int *argc,char ***argv)
Archive (since strings which were identical one after another
would be too easily optimized).
*/
+ if (verbose >= 2)
+ printf("Generating INSERT Statements for Auto\n");
query_statements= build_insert_string();
for (ptr_statement= query_statements, x= 0;
- x < auto_generate_sql_number;
+ x < auto_generate_sql_unique_query_number;
x++, ptr_statement= ptr_statement->next)
{
ptr_statement->next= build_insert_string();
}
}
+ else if (auto_generate_sql_type[0] == 'u')
+ {
+ query_statements= build_update_string();
+ for (ptr_statement= query_statements, x= 0;
+ x < auto_generate_sql_unique_query_number;
+ x++, ptr_statement= ptr_statement->next)
+ {
+ ptr_statement->next= build_update_string();
+ }
+ }
else /* Mixed mode is default */
{
int coin= 0;
@@ -846,7 +1279,7 @@ get_options(int *argc,char ***argv)
at the moment it results in "every other".
*/
for (ptr_statement= query_statements, x= 0;
- x < 4;
+ x < auto_generate_sql_unique_query_number;
x++, ptr_statement= ptr_statement->next)
{
if (coin)
@@ -856,7 +1289,7 @@ get_options(int *argc,char ***argv)
}
else
{
- ptr_statement->next= build_query_string();
+ ptr_statement->next= build_select_string(TRUE);
coin= 1;
}
}
@@ -878,12 +1311,13 @@ get_options(int *argc,char ***argv)
fprintf(stderr,"%s: Could not open create file\n", my_progname);
exit(1);
}
- tmp_string= (char *)my_malloc(sbuf.st_size+1, MYF(MY_WME));
+ tmp_string= (char *)my_malloc(sbuf.st_size + 1,
+ MYF(MY_ZEROFILL|MY_FAE|MY_WME));
my_read(data_file, tmp_string, sbuf.st_size, MYF(0));
tmp_string[sbuf.st_size]= '\0';
my_close(data_file,MYF(0));
parse_delimiter(tmp_string, &create_statements, delimiter[0]);
- my_free(tmp_string, MYF(0));
+ my_free((gptr)tmp_string, MYF(0));
}
else if (create_string)
{
@@ -904,14 +1338,15 @@ get_options(int *argc,char ***argv)
fprintf(stderr,"%s: Could not open query supplied file\n", my_progname);
exit(1);
}
- tmp_string= (char *)my_malloc(sbuf.st_size+1, MYF(MY_WME));
+ tmp_string= (char *)my_malloc(sbuf.st_size + 1,
+ MYF(MY_ZEROFILL|MY_FAE|MY_WME));
my_read(data_file, tmp_string, sbuf.st_size, MYF(0));
tmp_string[sbuf.st_size]= '\0';
my_close(data_file,MYF(0));
if (user_supplied_query)
actual_queries= parse_delimiter(tmp_string, &query_statements,
delimiter[0]);
- my_free(tmp_string, MYF(0));
+ my_free((gptr)tmp_string, MYF(0));
}
else if (user_supplied_query)
{
@@ -920,8 +1355,71 @@ get_options(int *argc,char ***argv)
}
}
+ if (user_supplied_pre_statements && my_stat(user_supplied_pre_statements, &sbuf, MYF(0)))
+ {
+ File data_file;
+ if (!MY_S_ISREG(sbuf.st_mode))
+ {
+ fprintf(stderr,"%s: User query supplied file was not a regular file\n",
+ my_progname);
+ exit(1);
+ }
+ if ((data_file= my_open(user_supplied_pre_statements, O_RDWR, MYF(0))) == -1)
+ {
+ fprintf(stderr,"%s: Could not open query supplied file\n", my_progname);
+ exit(1);
+ }
+ tmp_string= (char *)my_malloc(sbuf.st_size + 1,
+ MYF(MY_ZEROFILL|MY_FAE|MY_WME));
+ my_read(data_file, tmp_string, sbuf.st_size, MYF(0));
+ tmp_string[sbuf.st_size]= '\0';
+ my_close(data_file,MYF(0));
+ if (user_supplied_pre_statements)
+ actual_queries= parse_delimiter(tmp_string, &pre_statements,
+ delimiter[0]);
+ my_free((gptr)tmp_string, MYF(0));
+ }
+ else if (user_supplied_pre_statements)
+ {
+ actual_queries= parse_delimiter(user_supplied_pre_statements, &pre_statements,
+ delimiter[0]);
+ }
+
+ if (user_supplied_post_statements && my_stat(user_supplied_post_statements, &sbuf, MYF(0)))
+ {
+ File data_file;
+ if (!MY_S_ISREG(sbuf.st_mode))
+ {
+ fprintf(stderr,"%s: User query supplied file was not a regular file\n",
+ my_progname);
+ exit(1);
+ }
+ if ((data_file= my_open(user_supplied_post_statements, O_RDWR, MYF(0))) == -1)
+ {
+ fprintf(stderr,"%s: Could not open query supplied file\n", my_progname);
+ exit(1);
+ }
+ tmp_string= (char *)my_malloc(sbuf.st_size + 1,
+ MYF(MY_ZEROFILL|MY_FAE|MY_WME));
+ my_read(data_file, tmp_string, sbuf.st_size, MYF(0));
+ tmp_string[sbuf.st_size]= '\0';
+ my_close(data_file,MYF(0));
+ if (user_supplied_post_statements)
+ parse_delimiter(tmp_string, &post_statements,
+ delimiter[0]);
+ my_free((gptr)tmp_string, MYF(0));
+ }
+ else if (user_supplied_post_statements)
+ {
+ parse_delimiter(user_supplied_post_statements, &post_statements,
+ delimiter[0]);
+ }
+
+ if (verbose >= 2)
+ printf("Parsing engines to use.\n");
+
if (default_engine)
- parse_delimiter(default_engine, &engine_statements, ',');
+ parse_option(default_engine, &engine_options, ',');
if (tty_password)
opt_password= get_tty_password(NullS);
@@ -937,24 +1435,99 @@ static int run_query(MYSQL *mysql, const char *query, int len)
return 0;
}
- if (verbose >= 2)
+ if (verbose >= 3)
printf("%.*s;\n", len, query);
return mysql_real_query(mysql, query, len);
}
+static int
+generate_primary_key_list(MYSQL *mysql, option_string *engine_stmt)
+{
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+ unsigned long long counter;
+ DBUG_ENTER("generate_primary_key_list");
+
+ /*
+ Blackhole is a special case, this allows us to test the upper end
+ of the server during load runs.
+ */
+ if (opt_only_print || (engine_stmt &&
+ strstr(engine_stmt->string, "blackhole")))
+ {
+ primary_keys_number_of= 1;
+ primary_keys= (char **)my_malloc((uint)(sizeof(char *) *
+ primary_keys_number_of),
+ MYF(MY_ZEROFILL|MY_FAE|MY_WME));
+ /* Yes, we strdup a const string to simplify the interface */
+ primary_keys[0]= my_strdup("796c4422-1d94-102a-9d6d-00e0812d", MYF(0));
+ }
+ else
+ {
+ if (run_query(mysql, "SELECT id from t1", strlen("SELECT id from t1")))
+ {
+ fprintf(stderr,"%s: Cannot select GUID primary keys. (%s)\n", my_progname,
+ mysql_error(mysql));
+ exit(1);
+ }
+
+ result= mysql_store_result(mysql);
+ primary_keys_number_of= mysql_num_rows(result);
+
+ /* So why check this? Blackhole :) */
+ if (primary_keys_number_of)
+ {
+ /*
+ We create the structure and loop and create the items.
+ */
+ primary_keys= (char **)my_malloc((uint)(sizeof(char *) *
+ primary_keys_number_of),
+ MYF(MY_ZEROFILL|MY_FAE|MY_WME));
+ row= mysql_fetch_row(result);
+ for (counter= 0; counter < primary_keys_number_of;
+ counter++, row= mysql_fetch_row(result))
+ primary_keys[counter]= my_strdup(row[0], MYF(0));
+ }
+
+ mysql_free_result(result);
+ }
+
+ DBUG_RETURN(0);
+}
+
+static int
+drop_primary_key_list(void)
+{
+ unsigned long long counter;
+
+ if (primary_keys_number_of)
+ {
+ for (counter= 0; counter < primary_keys_number_of; counter++)
+ my_free((gptr)primary_keys[counter], MYF(0));
+
+ my_free((gptr)primary_keys, MYF(0));
+ }
+
+ return 0;
+}
static int
create_schema(MYSQL *mysql, const char *db, statement *stmt,
- statement *engine_stmt)
+ option_string *engine_stmt)
{
char query[HUGE_STRING_LENGTH];
statement *ptr;
+ statement *after_create;
int len;
+ ulonglong count;
DBUG_ENTER("create_schema");
len= snprintf(query, HUGE_STRING_LENGTH, "CREATE SCHEMA `%s`", db);
+ if (verbose >= 2)
+ printf("Loading Pre-data\n");
+
if (run_query(mysql, query, len))
{
fprintf(stderr,"%s: Cannot create schema %s : %s\n", my_progname, db,
@@ -968,8 +1541,9 @@ create_schema(MYSQL *mysql, const char *db, statement *stmt,
}
else
{
- if (verbose >= 2)
+ if (verbose >= 3)
printf("%s;\n", query);
+
if (mysql_select_db(mysql, db))
{
fprintf(stderr,"%s: Cannot select schema '%s': %s\n",my_progname, db,
@@ -990,16 +1564,46 @@ create_schema(MYSQL *mysql, const char *db, statement *stmt,
}
}
- for (ptr= stmt; ptr && ptr->length; ptr= ptr->next)
+ count= 0;
+ after_create= stmt;
+
+limit_not_met:
+ for (ptr= after_create; ptr && ptr->length; ptr= ptr->next, count++)
{
- if (run_query(mysql, ptr->string, ptr->length))
+ if (auto_generate_sql && ( auto_generate_sql_number == count))
+ break;
+
+ if (engine_stmt && engine_stmt->option && ptr->type == CREATE_TABLE_TYPE)
{
- fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
- my_progname, (uint)ptr->length, ptr->string, mysql_error(mysql));
- exit(1);
+ char buffer[HUGE_STRING_LENGTH];
+
+ snprintf(buffer, HUGE_STRING_LENGTH, "%s %s", ptr->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 (run_query(mysql, ptr->string, ptr->length))
+ {
+ fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
+ my_progname, (uint)ptr->length, ptr->string, mysql_error(mysql));
+ exit(1);
+ }
}
}
+ if (auto_generate_sql && (auto_generate_sql_number > count ))
+ {
+ /* Special case for auto create, we don't want to create tables twice */
+ after_create= stmt->next;
+ goto limit_not_met;
+ }
+
DBUG_RETURN(0);
}
@@ -1024,136 +1628,84 @@ drop_schema(MYSQL *mysql, const char *db)
}
static int
+run_statements(MYSQL *mysql, statement *stmt)
+{
+ statement *ptr;
+ DBUG_ENTER("run_statements");
+
+ for (ptr= stmt; ptr && ptr->length; ptr= ptr->next)
+ {
+ if (run_query(mysql, ptr->string, ptr->length))
+ {
+ fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
+ my_progname, (uint)ptr->length, ptr->string, mysql_error(mysql));
+ exit(1);
+ }
+ }
+
+ DBUG_RETURN(0);
+}
+
+static int
run_scheduler(stats *sptr, statement *stmts, uint concur, ulonglong limit)
{
-#ifndef __WIN__
uint x;
-#endif
- File lock_file;
struct timeval start_time, end_time;
thread_context con;
+ pthread_t mainthread; /* Thread descriptor */
+ pthread_attr_t attr; /* Thread attributes */
DBUG_ENTER("run_scheduler");
con.stmt= stmts;
con.limit= limit;
- con.thread= opt_use_threads ? 1 :0;
-
- lock_file= my_open(lock_file_str, O_CREAT|O_WRONLY|O_TRUNC, MYF(0));
- if (!opt_slave)
- if (my_lock(lock_file, F_WRLCK, 0, F_TO_EOF, MYF(0)))
- {
- fprintf(stderr,"%s: Could not get lockfile\n",
- my_progname);
- exit(0);
- }
+ pthread_attr_init(&attr);
+ pthread_attr_setdetachstate(&attr,
+ PTHREAD_CREATE_DETACHED);
-#ifdef HAVE_LIBPTHREAD
- if (opt_use_threads)
- {
- pthread_t mainthread; /* Thread descriptor */
- pthread_attr_t attr; /* Thread attributes */
-
- for (x= 0; x < concur; x++)
- {
- pthread_attr_init(&attr);
- pthread_attr_setdetachstate(&attr,
- PTHREAD_CREATE_DETACHED);
+ pthread_mutex_lock(&counter_mutex);
+ thread_counter= 0;
- /* now create the thread */
- if (pthread_create(&mainthread, &attr, (void *)run_task,
- (void *)&con) != 0)
- {
- fprintf(stderr,"%s: Could not create thread\n",
- my_progname);
- exit(0);
- }
- }
- }
-#endif
-#if !(defined(__WIN__) || defined(__NETWARE__))
-#ifdef HAVE_LIBPTHREAD
- else
-#endif
+ pthread_mutex_lock(&sleeper_mutex);
+ master_wakeup= 1;
+ pthread_mutex_unlock(&sleeper_mutex);
+ for (x= 0; x < concur; x++)
{
- fflush(NULL);
- for (x= 0; x < concur; x++)
+ /* now you create the thread */
+ if (pthread_create(&mainthread, &attr, run_task,
+ (void *)&con) != 0)
{
- int pid;
- DBUG_PRINT("info", ("x: %d concurrency: %u", x, *concurrency));
- pid= fork();
- switch(pid)
- {
- case 0:
- /* child */
- DBUG_PRINT("info", ("fork returned 0, calling task(\"%s\"), pid %d gid %d",
- stmts ? stmts->string : "", pid, getgid()));
- if (verbose >= 2)
- fprintf(stderr,
- "%s: fork returned 0, calling task pid %d gid %d\n",
- my_progname, pid, getgid());
- run_task(&con);
- exit(0);
- break;
- case -1:
- /* error */
- DBUG_PRINT("info",
- ("fork returned -1, failing pid %d gid %d", pid, getgid()));
- fprintf(stderr,
- "%s: Failed on fork: -1, max procs per parent exceeded.\n",
- my_progname);
- /*exit(1);*/
- goto WAIT;
- default:
- /* parent, forked */
- DBUG_PRINT("info", ("default, break: pid %d gid %d", pid, getgid()));
- if (verbose >= 2)
- fprintf(stderr,"%s: fork returned %d, gid %d\n",
- my_progname, pid, getgid());
- break;
- }
+ fprintf(stderr,"%s: Could not create thread\n",
+ my_progname);
+ exit(0);
}
+ thread_counter++;
}
-#endif
+ pthread_mutex_unlock(&counter_mutex);
+ pthread_attr_destroy(&attr);
- /* Lets release use some clients! */
- if (!opt_slave)
- my_lock(lock_file, F_UNLCK, 0, F_TO_EOF, MYF(0));
+ pthread_mutex_lock(&sleeper_mutex);
+ master_wakeup= 0;
+ pthread_mutex_unlock(&sleeper_mutex);
+ pthread_cond_broadcast(&sleep_threshhold);
gettimeofday(&start_time, NULL);
/*
- We look to grab a write lock at this point. Once we get it we know that
- all clients have completed their work.
+ We loop until we know that all children have cleaned up.
*/
- if (opt_use_threads)
+ pthread_mutex_lock(&counter_mutex);
+ while (thread_counter)
{
- if (my_lock(lock_file, F_WRLCK, 0, F_TO_EOF, MYF(0)))
- {
- fprintf(stderr,"%s: Could not get lockfile\n",
- my_progname);
- exit(0);
- }
- my_lock(lock_file, F_UNLCK, 0, F_TO_EOF, MYF(0));
- }
-#ifndef __WIN__
- else
- {
-WAIT:
- while (x--)
- {
- int status, pid;
- pid= wait(&status);
- DBUG_PRINT("info", ("Parent: child %d status %d", pid, status));
- if (status != 0)
- printf("%s: Child %d died with the status %d\n",
- my_progname, pid, status);
- }
+ struct timespec abstime;
+
+ set_timespec(abstime, 3);
+ pthread_cond_timedwait(&count_threshhold, &counter_mutex, &abstime);
}
-#endif
+ pthread_mutex_unlock(&counter_mutex);
+
gettimeofday(&end_time, NULL);
- my_close(lock_file, MYF(0));
sptr->timing= timedif(end_time, start_time);
sptr->users= concur;
@@ -1163,28 +1715,41 @@ WAIT:
}
-int
-run_task(thread_context *con)
+pthread_handler_t run_task(void *p)
{
ulonglong counter= 0, queries;
- File lock_file= -1;
MYSQL *mysql;
MYSQL_RES *result;
MYSQL_ROW row;
statement *ptr;
+ thread_context *con= (thread_context *)p;
DBUG_ENTER("run_task");
DBUG_PRINT("info", ("task script \"%s\"", con->stmt ? con->stmt->string : ""));
+ pthread_mutex_lock(&sleeper_mutex);
+ while (master_wakeup)
+ {
+ pthread_cond_wait(&sleep_threshhold, &sleeper_mutex);
+ }
+ pthread_mutex_unlock(&sleeper_mutex);
+
if (!(mysql= mysql_init(NULL)))
- goto end;
+ {
+ fprintf(stderr,"%s: mysql_init() failed ERROR : %s\n",
+ my_progname, mysql_error(mysql));
+ exit(0);
+ }
- if (con->thread && mysql_thread_init())
- goto end;
+ if (mysql_thread_init())
+ {
+ fprintf(stderr,"%s: mysql_thread_init() failed ERROR : %s\n",
+ my_progname, mysql_error(mysql));
+ exit(0);
+ }
DBUG_PRINT("info", ("trying to connect to host %s as user %s", host, user));
- lock_file= my_open(lock_file_str, O_RDWR, MYF(0));
- my_lock(lock_file, F_RDLCK, 0, F_TO_EOF, MYF(0));
+
if (!opt_only_print)
{
/* Connect to server */
@@ -1213,18 +1778,59 @@ run_task(thread_context *con)
}
DBUG_PRINT("info", ("connected."));
if (verbose >= 3)
- fprintf(stderr, "connected!\n");
+ printf("connected!\n");
queries= 0;
limit_not_met:
for (ptr= con->stmt; ptr && ptr->length; ptr= ptr->next)
{
- if (run_query(mysql, ptr->string, ptr->length))
+ /*
+ We have to execute differently based on query type. This should become a function.
+ */
+ if ((ptr->type == UPDATE_TYPE_REQUIRES_PREFIX) ||
+ (ptr->type == SELECT_TYPE_REQUIRES_PREFIX))
{
- fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
- my_progname, (uint)ptr->length, ptr->string, mysql_error(mysql));
- goto end;
+ int length;
+ unsigned int key_val;
+ char *key;
+ char buffer[HUGE_STRING_LENGTH];
+
+ /*
+ This should only happen if some sort of new engine was
+ implemented that didn't properly handle UPDATEs.
+
+ Just in case someone runs this under an experimental engine we don't
+ want a crash so the if() is placed here.
+ */
+ DBUG_ASSERT(primary_keys_number_of);
+ if (primary_keys_number_of)
+ {
+ key_val= (unsigned int)(random() % primary_keys_number_of);
+ key= primary_keys[key_val];
+
+ DBUG_ASSERT(key);
+
+ length= snprintf(buffer, HUGE_STRING_LENGTH, "%.*s '%s'",
+ (int)ptr->length, ptr->string, key);
+
+ if (run_query(mysql, buffer, length))
+ {
+ fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
+ my_progname, (uint)length, buffer, mysql_error(mysql));
+ exit(0);
+ }
+ }
}
+ else
+ {
+ if (run_query(mysql, ptr->string, ptr->length))
+ {
+ fprintf(stderr,"%s: Cannot run query %.*s ERROR : %s\n",
+ my_progname, (uint)ptr->length, ptr->string, mysql_error(mysql));
+ exit(0);
+ }
+ }
+
if (mysql_field_count(mysql))
{
result= mysql_store_result(mysql);
@@ -1243,20 +1849,97 @@ limit_not_met:
end:
- if (lock_file != -1)
- {
- my_lock(lock_file, F_UNLCK, 0, F_TO_EOF, MYF(0));
- my_close(lock_file, MYF(0));
- }
-
if (!opt_only_print)
mysql_close(mysql);
- if (con->thread)
- my_thread_end();
+ my_thread_end();
+
+ pthread_mutex_lock(&counter_mutex);
+ thread_counter--;
+ pthread_cond_signal(&count_threshhold);
+ pthread_mutex_unlock(&counter_mutex);
+
DBUG_RETURN(0);
}
+uint
+parse_option(const char *origin, option_string **stmt, char delm)
+{
+ char *retstr;
+ char *ptr= (char *)origin;
+ option_string **sptr= stmt;
+ option_string *tmp;
+ uint length= strlen(origin);
+ 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));
+ (retstr= strchr(ptr, delm));
+ tmp->next= (option_string *)my_malloc(sizeof(option_string),
+ MYF(MY_ZEROFILL|MY_FAE|MY_WME)),
+ tmp= tmp->next)
+ {
+ char buffer[HUGE_STRING_LENGTH];
+ char *buffer_ptr;
+
+ count++;
+ strncpy(buffer, ptr, (size_t)(retstr - ptr));
+ if ((buffer_ptr= strchr(buffer, ':')))
+ {
+ char *option_ptr;
+
+ tmp->length= (size_t)(buffer_ptr - buffer);
+ tmp->string= my_strndup(ptr, (uint)tmp->length, MYF(MY_FAE));
+
+ option_ptr= ptr + 1 + tmp->length;
+
+ /* Move past the : and the first string */
+ tmp->option_length= (size_t)(retstr - option_ptr);
+ tmp->option= my_strndup(option_ptr, (uint)tmp->option_length,
+ MYF(MY_FAE));
+ }
+ else
+ {
+ tmp->string= my_strndup(ptr, (size_t)(retstr - ptr), MYF(MY_FAE));
+ tmp->length= (size_t)(retstr - ptr);
+ }
+
+ ptr+= retstr - ptr + 1;
+ if (isspace(*ptr))
+ ptr++;
+ count++;
+ }
+
+ if (ptr != origin+length)
+ {
+ char *origin_ptr;
+
+ if ((origin_ptr= strchr(ptr, ':')))
+ {
+ char *option_ptr;
+
+ tmp->length= (size_t)(origin_ptr - ptr);
+ tmp->string= my_strndup(origin, tmp->length, MYF(MY_FAE));
+
+ option_ptr= (char *)ptr + 1 + tmp->length;
+
+ /* Move past the : and the first string */
+ tmp->option_length= (size_t)((ptr + length) - option_ptr);
+ tmp->option= my_strndup(option_ptr, tmp->option_length,
+ MYF(MY_FAE));
+ }
+ else
+ {
+ tmp->length= (size_t)((ptr + length) - ptr);
+ tmp->string= my_strndup(ptr, tmp->length, MYF(MY_FAE));
+ }
+
+ count++;
+ }
+
+ return count;
+}
+
uint
parse_delimiter(const char *script, statement **stmt, char delm)
@@ -1268,13 +1951,15 @@ parse_delimiter(const char *script, statement **stmt, char delm)
uint length= strlen(script);
uint count= 0; /* We know that there is always one */
- for (tmp= *sptr= (statement *)my_malloc(sizeof(statement), MYF(MY_ZEROFILL));
+ for (tmp= *sptr= (statement *)my_malloc(sizeof(statement),
+ MYF(MY_ZEROFILL|MY_FAE|MY_WME));
(retstr= strchr(ptr, delm));
- tmp->next= (statement *)my_malloc(sizeof(statement), MYF(MY_ZEROFILL)),
+ tmp->next= (statement *)my_malloc(sizeof(statement),
+ MYF(MY_ZEROFILL|MY_FAE|MY_WME)),
tmp= tmp->next)
{
count++;
- tmp->string= my_strndup(ptr, (size_t)(retstr - ptr), MYF(MY_FAE));
+ tmp->string= my_strndup(ptr, (uint)(retstr - ptr), MYF(MY_FAE));
tmp->length= (size_t)(retstr - ptr);
ptr+= retstr - ptr + 1;
if (isspace(*ptr))
@@ -1284,7 +1969,7 @@ parse_delimiter(const char *script, statement **stmt, char delm)
if (ptr != script+length)
{
- tmp->string= my_strndup(ptr, (size_t)((script + length) - ptr),
+ tmp->string= my_strndup(ptr, (uint)((script + length) - ptr),
MYF(MY_FAE));
tmp->length= (size_t)((script + length) - ptr);
count++;
@@ -1306,7 +1991,8 @@ parse_comma(const char *string, uint **range)
if (*ptr == ',') count++;
/* One extra spot for the NULL */
- nptr= *range= (uint *)my_malloc(sizeof(uint) * (count + 1), MYF(MY_ZEROFILL));
+ nptr= *range= (uint *)my_malloc(sizeof(uint) * (count + 1),
+ MYF(MY_ZEROFILL|MY_FAE|MY_WME));
ptr= (char *)string;
x= 0;
@@ -1341,23 +2027,25 @@ void
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,query,%ld.%03ld,%ld.%03ld,%ld.%03ld,%d,%llu\n",
+ "%s,%s,%ld.%03ld,%ld.%03ld,%ld.%03ld,%d,%llu\n",
con->engine ? con->engine : "", /* Storage engine we ran against */
+ ptr, /* Load type */
con->avg_timing / 1000, con->avg_timing % 1000, /* Time to load */
con->min_timing / 1000, con->min_timing % 1000, /* Min time */
con->max_timing / 1000, con->max_timing % 1000, /* Max time */
con->users, /* Children used */
con->avg_rows /* Queries run */
);
- my_write(csv_file, buffer, strlen(buffer), MYF(0));
+ my_write(csv_file, buffer, (uint)strlen(buffer), MYF(0));
}
void
-generate_stats(conclusions *con, statement *eng, stats *sptr)
+generate_stats(conclusions *con, option_string *eng, stats *sptr)
{
stats *ptr;
- int x;
+ unsigned int x;
con->min_timing= sptr->timing;
con->max_timing= sptr->timing;
@@ -1387,6 +2075,24 @@ generate_stats(conclusions *con, statement *eng, stats *sptr)
}
void
+option_cleanup(option_string *stmt)
+{
+ option_string *ptr, *nptr;
+ if (!stmt)
+ return;
+
+ for (ptr= stmt; ptr; ptr= nptr)
+ {
+ nptr= ptr->next;
+ if (ptr->string)
+ my_free((gptr)ptr->string, MYF(0));
+ if (ptr->option)
+ my_free((gptr)ptr->option, MYF(0));
+ my_free((gptr)(byte *)ptr, MYF(0));
+ }
+}
+
+void
statement_cleanup(statement *stmt)
{
statement *ptr, *nptr;
@@ -1397,7 +2103,7 @@ statement_cleanup(statement *stmt)
{
nptr= ptr->next;
if (ptr->string)
- my_free(ptr->string, MYF(0));
- my_free((byte *)ptr, MYF(0));
+ my_free((gptr)ptr->string, MYF(0));
+ my_free((gptr)(byte *)ptr, MYF(0));
}
}
diff --git a/client/mysqltest.c b/client/mysqltest.c
index 3f462c2af77..e4eb06953e2 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -31,7 +31,7 @@
Holyfoot
*/
-#define MTEST_VERSION "3.1"
+#define MTEST_VERSION "3.2"
#include <my_global.h>
#include <mysql_embed.h>
@@ -60,6 +60,11 @@
# endif
#endif
+/* Use cygwin for --exec and --system before 5.0 */
+#if MYSQL_VERSION_ID < 50000
+#define USE_CYGWIN
+#endif
+
#define MAX_VAR_NAME_LENGTH 256
#define MAX_COLUMNS 256
#define MAX_EMBEDDED_SERVER_ARGS 64
@@ -101,11 +106,11 @@ static my_bool parsing_disabled= 0;
static my_bool info_flag;
static my_bool display_result_vertically= FALSE, display_metadata= FALSE;
static my_bool disable_query_log= 0, disable_result_log= 0;
-static my_bool disable_warnings= 0, disable_ps_warnings= 0;
+static my_bool disable_warnings= 0;
static my_bool disable_info= 1;
static my_bool abort_on_error= 1;
static my_bool server_initialized= 0;
-
+static my_bool is_windows= 0;
static char **default_argv;
static const char *load_default_groups[]= { "mysqltest", "client", 0 };
static char line_buffer[MAX_DELIMITER_LENGTH], *line_buffer_pos= line_buffer;
@@ -261,7 +266,6 @@ enum enum_commands {
Q_ENABLE_RESULT_LOG, Q_DISABLE_RESULT_LOG,
Q_WAIT_FOR_SLAVE_TO_STOP,
Q_ENABLE_WARNINGS, Q_DISABLE_WARNINGS,
- Q_ENABLE_PS_WARNINGS, Q_DISABLE_PS_WARNINGS,
Q_ENABLE_INFO, Q_DISABLE_INFO,
Q_ENABLE_METADATA, Q_DISABLE_METADATA,
Q_EXEC, Q_DELIMITER,
@@ -275,7 +279,7 @@ enum enum_commands {
Q_DISABLE_PARSING, Q_ENABLE_PARSING,
Q_REPLACE_REGEX, Q_REMOVE_FILE, Q_FILE_EXIST,
Q_WRITE_FILE, Q_COPY_FILE, Q_PERL, Q_DIE, Q_EXIT,
- Q_CHMOD_FILE,
+ Q_CHMOD_FILE, Q_APPEND_FILE, Q_CAT_FILE, Q_DIFF_FILES,
Q_UNKNOWN, /* Unknown command. */
Q_COMMENT, /* Comments, ignored. */
@@ -325,8 +329,6 @@ const char *command_names[]=
"wait_for_slave_to_stop",
"enable_warnings",
"disable_warnings",
- "enable_ps_warnings",
- "disable_ps_warnings",
"enable_info",
"disable_info",
"enable_metadata",
@@ -359,6 +361,9 @@ const char *command_names[]=
/* Don't execute any more commands, compare result */
"exit",
"chmod",
+ "append_file",
+ "cat_file",
+ "diff_files",
0
};
@@ -410,6 +415,9 @@ TYPELIB command_typelib= {array_elements(command_names),"",
static DYNAMIC_STRING ds_res, ds_progress, ds_warning_messages;
static DYNAMIC_STRING global_ds_warnings, global_eval_query;
+char builtin_echo[FN_REFLEN];
+
+
void die(const char *fmt, ...)
ATTRIBUTE_FORMAT(printf, 1, 2);
void abort_not_supported_test(const char *fmt, ...)
@@ -418,6 +426,8 @@ void verbose_msg(const char *fmt, ...)
ATTRIBUTE_FORMAT(printf, 1, 2);
void warning_msg(const char *fmt, ...)
ATTRIBUTE_FORMAT(printf, 1, 2);
+void log_msg(const char *fmt, ...)
+ ATTRIBUTE_FORMAT(printf, 1, 2);
VAR* var_from_env(const char *, const char *);
VAR* var_init(VAR* v, const char *name, int name_len, const char *val,
@@ -435,6 +445,7 @@ void dump_progress();
void do_eval(DYNAMIC_STRING *query_eval, const char *query,
const char *query_end, my_bool pass_through_escape_chars);
void str_to_file(const char *fname, char *str, int size);
+void str_to_file2(const char *fname, char *str, int size, my_bool append);
#ifdef __WIN__
void free_tmp_sh_file();
@@ -580,6 +591,7 @@ void do_eval(DYNAMIC_STRING *query_eval, const char *query,
dynstr_append_mem(query_eval, p, 1);
break;
default:
+ escaped= 0;
dynstr_append_mem(query_eval, p, 1);
break;
}
@@ -936,10 +948,10 @@ void warning_msg(const char *fmt, ...)
dynstr_append_mem(&ds_warning_messages,
buff, len);
}
-#ifndef __WIN__
- len= vsnprintf(buff, sizeof(buff), fmt, args);
+
+ len= my_vsnprintf(buff, sizeof(buff), fmt, args);
dynstr_append_mem(&ds_warning_messages, buff, len);
-#endif
+
dynstr_append(&ds_warning_messages, "\n");
va_end(args);
@@ -947,6 +959,25 @@ void warning_msg(const char *fmt, ...)
}
+void log_msg(const char *fmt, ...)
+{
+ va_list args;
+ char buff[512];
+ size_t len;
+ DBUG_ENTER("log_msg");
+
+ memset(buff, 0, sizeof(buff));
+ va_start(args, fmt);
+ len= my_vsnprintf(buff, sizeof(buff)-1, fmt, args);
+ va_end(args);
+
+ dynstr_append_mem(&ds_res, buff, len);
+ dynstr_append(&ds_res, "\n");
+
+ DBUG_VOID_RETURN;
+}
+
+
/*
Compare content of the string ds to content of file fname
*/
@@ -1519,29 +1550,36 @@ void do_source(struct st_command *command)
}
-#ifdef __WIN__
+#if defined __WIN__
+
+#ifdef USE_CYGWIN
/* Variables used for temporary sh files used for emulating Unix on Windows */
char tmp_sh_name[64], tmp_sh_cmd[70];
+#endif
void init_tmp_sh_file()
{
+#ifdef USE_CYGWIN
/* Format a name for the tmp sh file that is unique for this process */
my_snprintf(tmp_sh_name, sizeof(tmp_sh_name), "tmp_%d.sh", getpid());
/* Format the command to execute in order to run the script */
my_snprintf(tmp_sh_cmd, sizeof(tmp_sh_cmd), "sh %s", tmp_sh_name);
+#endif
}
void free_tmp_sh_file()
{
+#ifdef USE_CYGWIN
my_delete(tmp_sh_name, MYF(0));
+#endif
}
#endif
FILE* my_popen(DYNAMIC_STRING *ds_cmd, const char *mode)
{
-#ifdef __WIN__
+#if defined __WIN__ && defined USE_CYGWIN
/* Dump the command into a sh script file and execute with popen */
str_to_file(tmp_sh_name, ds_cmd->str, ds_cmd->length);
return popen(tmp_sh_cmd, mode);
@@ -1551,6 +1589,64 @@ FILE* my_popen(DYNAMIC_STRING *ds_cmd, const char *mode)
}
+static void init_builtin_echo(void)
+{
+#ifdef __WIN__
+
+ /* Look for "echo.exe" in same dir as mysqltest was started from */
+ dirname_part(builtin_echo, my_progname);
+ fn_format(builtin_echo, ".\\echo.exe",
+ builtin_echo, "", MYF(MY_REPLACE_DIR));
+
+ /* Make sure echo.exe exists */
+ if (access(builtin_echo, F_OK) != 0)
+ builtin_echo[0]= 0;
+ return;
+
+#else
+
+ builtin_echo[0]= 0;
+ return;
+
+#endif
+}
+
+
+/*
+ Replace a substring
+
+ SYNOPSIS
+ replace
+ ds_str The string to search and perform the replace in
+ search_str The string to search for
+ search_len Length of the string to search for
+ replace_str The string to replace with
+ replace_len Length of the string to replace with
+
+ RETURN
+ 0 String replaced
+ 1 Could not find search_str in str
+*/
+
+static int replace(DYNAMIC_STRING *ds_str,
+ const char *search_str, ulong search_len,
+ const char *replace_str, ulong replace_len)
+{
+ DYNAMIC_STRING ds_tmp;
+ const char *start= strstr(ds_str->str, search_str);
+ if (!start)
+ return 1;
+ init_dynamic_string(&ds_tmp, "",
+ ds_str->length + replace_len, 256);
+ dynstr_append_mem(&ds_tmp, ds_str->str, start - ds_str->str);
+ dynstr_append_mem(&ds_tmp, replace_str, replace_len);
+ dynstr_append(&ds_tmp, start + search_len);
+ dynstr_set(ds_str, ds_tmp.str);
+ dynstr_free(&ds_tmp);
+ return 0;
+}
+
+
/*
Execute given command.
@@ -1569,13 +1665,13 @@ FILE* my_popen(DYNAMIC_STRING *ds_cmd, const char *mode)
NOTE
Although mysqltest is executed from cygwin shell, the command will be
executed in "cmd.exe". Thus commands like "rm" etc can NOT be used, use
- system for those commands.
+ mysqltest commmand(s) like "remove_file" for that
*/
void do_exec(struct st_command *command)
{
int error;
- char buf[1024];
+ char buf[512];
FILE *res_file;
char *cmd= command->first_argument;
DYNAMIC_STRING ds_cmd;
@@ -1591,7 +1687,25 @@ void do_exec(struct st_command *command)
init_dynamic_string(&ds_cmd, 0, command->query_len+256, 256);
/* Eval the command, thus replacing all environment variables */
- do_eval(&ds_cmd, cmd, command->end, TRUE);
+ do_eval(&ds_cmd, cmd, command->end, !is_windows);
+
+ /* Check if echo should be replaced with "builtin" echo */
+ if (builtin_echo[0] && strncmp(cmd, "echo", 4) == 0)
+ {
+ /* Replace echo with our "builtin" echo */
+ replace(&ds_cmd, "echo", 4, builtin_echo, strlen(builtin_echo));
+ }
+
+#ifdef __WIN__
+#ifndef USE_CYGWIN
+ /* Replace /dev/null with NUL */
+ while(replace(&ds_cmd, "/dev/null", 9, "NUL", 3) == 0)
+ ;
+ /* Replace "closed stdout" with non existing output fd */
+ while(replace(&ds_cmd, ">&-", 3, ">&4", 3) == 0)
+ ;
+#endif
+#endif
DBUG_PRINT("info", ("Executing '%s' as '%s'",
command->first_argument, ds_cmd.str));
@@ -1618,7 +1732,11 @@ void do_exec(struct st_command *command)
my_bool ok= 0;
if (command->abort_on_error)
+ {
+ log_msg("exec of '%s failed, error: %d, status: %d, errno: %d",
+ ds_cmd.str, error, status, errno);
die("command \"%s\" failed", command->first_argument);
+ }
DBUG_PRINT("info",
("error: %d, status: %d", error, status));
@@ -1642,6 +1760,8 @@ void do_exec(struct st_command *command)
command->expected_errors.err[0].code.errnum != 0)
{
/* Error code we wanted was != 0, i.e. not an expected success */
+ log_msg("exec of '%s failed, error: %d, errno: %d",
+ ds_cmd.str, error, errno);
die("command \"%s\" succeeded - should have failed with errno %d...",
command->first_argument, command->expected_errors.err[0].code.errnum);
}
@@ -1712,7 +1832,7 @@ int do_modify_var(struct st_command *command,
int my_system(DYNAMIC_STRING* ds_cmd)
{
-#ifdef __WIN__
+#if defined __WIN__ && defined USE_CYGWIN
/* Dump the command into a sh script file and execute with system */
str_to_file(tmp_sh_name, ds_cmd->str, ds_cmd->length);
return system(tmp_sh_cmd);
@@ -1746,7 +1866,16 @@ void do_system(struct st_command *command)
init_dynamic_string(&ds_cmd, 0, command->query_len + 64, 256);
/* Eval the system command, thus replacing all environment variables */
- do_eval(&ds_cmd, command->first_argument, command->end, TRUE);
+ do_eval(&ds_cmd, command->first_argument, command->end, !is_windows);
+
+#ifdef __WIN__
+#ifndef USE_CYGWIN
+ /* Replace /dev/null with NUL */
+ while(replace(&ds_cmd, "/dev/null", 9, "NUL", 3) == 0)
+ ;
+#endif
+#endif
+
DBUG_PRINT("info", ("running system command '%s' as '%s'",
command->first_argument, ds_cmd.str));
@@ -1967,6 +2096,38 @@ void read_until_delimiter(DYNAMIC_STRING *ds,
}
+void do_write_file_command(struct st_command *command, my_bool append)
+{
+ static DYNAMIC_STRING ds_content;
+ static DYNAMIC_STRING ds_filename;
+ static DYNAMIC_STRING ds_delimiter;
+ const struct command_arg write_file_args[] = {
+ "filename", ARG_STRING, TRUE, &ds_filename, "File to write to",
+ "delimiter", ARG_STRING, FALSE, &ds_delimiter, "Delimiter to read until"
+ };
+ DBUG_ENTER("do_write_file");
+
+ check_command_args(command,
+ command->first_argument,
+ write_file_args,
+ sizeof(write_file_args)/sizeof(struct command_arg),
+ ' ');
+
+ /* If no delimiter was provided, use EOF */
+ if (ds_delimiter.length == 0)
+ dynstr_set(&ds_delimiter, "EOF");
+
+ init_dynamic_string(&ds_content, "", 1024, 1024);
+ read_until_delimiter(&ds_content, &ds_delimiter);
+ DBUG_PRINT("info", ("Writing to file: %s", ds_filename.str));
+ str_to_file2(ds_filename.str, ds_content.str, ds_content.length, append);
+ dynstr_free(&ds_content);
+ dynstr_free(&ds_filename);
+ dynstr_free(&ds_delimiter);
+ DBUG_VOID_RETURN;
+}
+
+
/*
SYNOPSIS
do_write_file
@@ -1996,36 +2157,174 @@ void read_until_delimiter(DYNAMIC_STRING *ds,
void do_write_file(struct st_command *command)
{
- static DYNAMIC_STRING ds_content;
+ do_write_file_command(command, FALSE);
+}
+
+
+/*
+ SYNOPSIS
+ do_append_file
+ command called command
+
+ DESCRIPTION
+ append_file <file_name> [<delimiter>];
+ <what to write line 1>
+ <...>
+ < what to write line n>
+ EOF
+
+ --append_file <file_name>;
+ <what to write line 1>
+ <...>
+ < what to write line n>
+ EOF
+
+ Append everything between the "append_file" command
+ and 'delimiter' to "file_name"
+
+ Default <delimiter> is EOF
+
+*/
+
+void do_append_file(struct st_command *command)
+{
+ do_write_file_command(command, TRUE);
+}
+
+
+/*
+ SYNOPSIS
+ do_cat_file
+ command called command
+
+ DESCRIPTION
+ cat_file <file_name>;
+
+ Print the given file to result log
+
+*/
+
+void do_cat_file(struct st_command *command)
+{
+ int fd;
+ uint len;
+ char buff[512];
static DYNAMIC_STRING ds_filename;
- static DYNAMIC_STRING ds_delimiter;
- const struct command_arg write_file_args[] = {
- "filename", ARG_STRING, TRUE, &ds_filename, "File to write to",
- "delimiter", ARG_STRING, FALSE, &ds_delimiter, "Delimiter to read until"
+ const struct command_arg cat_file_args[] = {
+ "filename", ARG_STRING, TRUE, &ds_filename, "File to read from"
};
- DBUG_ENTER("do_write_file");
+ DBUG_ENTER("do_cat_file");
check_command_args(command,
command->first_argument,
- write_file_args,
- sizeof(write_file_args)/sizeof(struct command_arg),
+ cat_file_args,
+ sizeof(cat_file_args)/sizeof(struct command_arg),
' ');
- /* If no delimiter was provided, use EOF */
- if (ds_delimiter.length == 0)
- dynstr_set(&ds_delimiter, "EOF");
+ DBUG_PRINT("info", ("Reading from, file: %s", ds_filename.str));
- init_dynamic_string(&ds_content, "", 1024, 1024);
- read_until_delimiter(&ds_content, &ds_delimiter);
- DBUG_PRINT("info", ("Writing to file: %s", ds_filename.str));
- str_to_file(ds_filename.str, ds_content.str, ds_content.length);
- dynstr_free(&ds_content);
+ if ((fd= my_open(ds_filename.str, O_RDONLY, MYF(0))) < 0)
+ die("Failed to open file %s", ds_filename.str);
+ while((len= my_read(fd, (byte*)&buff,
+ sizeof(buff), MYF(0))) > 0)
+ {
+ char *p= buff, *start= buff;
+ while (p < buff+len)
+ {
+ /* Convert cr/lf to lf */
+ if (*p == '\r' && *(p+1) && *(p+1)== '\n')
+ {
+ /* Add fake newline instead of cr and output the line */
+ *p= '\n';
+ p++; /* Step past the "fake" newline */
+ dynstr_append_mem(&ds_res, start, p-start);
+ p++; /* Step past the "fake" newline */
+ start= p;
+ }
+ else
+ p++;
+ }
+ /* Output any chars that migh be left */
+ dynstr_append_mem(&ds_res, start, p-start);
+ }
+ my_close(fd, MYF(0));
dynstr_free(&ds_filename);
- dynstr_free(&ds_delimiter);
DBUG_VOID_RETURN;
}
+
+/*
+ SYNOPSIS
+ do_diff_files
+ command called command
+
+ DESCRIPTION
+ diff_files <file1> <file2>;
+
+ Fails if the two files differ.
+
+*/
+
+void do_diff_files(struct st_command *command)
+{
+ int error= 0;
+ int fd, fd2;
+ uint len, len2;
+ char buff[512], buff2[512];
+ static DYNAMIC_STRING ds_filename;
+ static DYNAMIC_STRING ds_filename2;
+ const struct command_arg diff_file_args[] = {
+ "file1", ARG_STRING, TRUE, &ds_filename, "First file to diff",
+ "file2", ARG_STRING, TRUE, &ds_filename2, "Second file to diff"
+ };
+ DBUG_ENTER("do_diff_files");
+
+ check_command_args(command,
+ command->first_argument,
+ diff_file_args,
+ sizeof(diff_file_args)/sizeof(struct command_arg),
+ ' ');
+
+ if ((fd= my_open(ds_filename.str, O_RDONLY, MYF(0))) < 0)
+ die("Failed to open first file %s", ds_filename.str);
+ if ((fd2= my_open(ds_filename2.str, O_RDONLY, MYF(0))) < 0)
+ {
+ my_close(fd, MYF(0));
+ die("Failed to open second file %s", ds_filename2.str);
+ }
+ while((len= my_read(fd, (byte*)&buff,
+ sizeof(buff), MYF(0))) > 0)
+ {
+ if ((len2= my_read(fd2, (byte*)&buff2,
+ sizeof(buff2), MYF(0))) != len)
+ {
+ /* File 2 was smaller */
+ error= 1;
+ break;
+ }
+ if ((memcmp(buff, buff2, len)))
+ {
+ /* Content of this part differed */
+ error= 1;
+ break;
+ }
+ }
+ if (my_read(fd2, (byte*)&buff2,
+ sizeof(buff2), MYF(0)) > 0)
+ {
+ /* File 1 was smaller */
+ error= 1;
+ }
+
+ my_close(fd, MYF(0));
+ my_close(fd2, MYF(0));
+ dynstr_free(&ds_filename);
+ dynstr_free(&ds_filename2);
+ handle_command_error(command, error);
+ DBUG_VOID_RETURN;
+}
+
/*
SYNOPSIS
do_perl
@@ -3241,7 +3540,7 @@ void do_connect(struct st_command *command)
opt_ssl_capath, opt_ssl_cipher);
#if MYSQL_VERSION_ID >= 50000
/* Turn on ssl_verify_server_cert only if host is "localhost" */
- opt_ssl_verify_server_cert= !strcmp(ds_connection_name.str, "localhost");
+ opt_ssl_verify_server_cert= !strcmp(ds_host.str, "localhost");
mysql_options(&next_con->mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
&opt_ssl_verify_server_cert);
#endif
@@ -4181,21 +4480,22 @@ int parse_args(int argc, char **argv)
return 0;
}
-
/*
Write the content of str into file
SYNOPSIS
- str_to_file
+ str_to_file2
fname - name of file to truncate/create and write to
str - content to write to file
size - size of content witten to file
+ append - append to file instead of overwriting old file
*/
-void str_to_file(const char *fname, char *str, int size)
+void str_to_file2(const char *fname, char *str, int size, my_bool append)
{
int fd;
char buff[FN_REFLEN];
+ int flags= O_WRONLY | O_CREAT;
if (!test_if_hard_path(fname))
{
strxmov(buff, opt_basedir, fname, NullS);
@@ -4203,14 +4503,33 @@ void str_to_file(const char *fname, char *str, int size)
}
fn_format(buff, fname, "", "", MY_UNPACK_FILENAME);
- if ((fd= my_open(buff, O_WRONLY | O_CREAT | O_TRUNC,
+ if (!append)
+ flags|= O_TRUNC;
+ if ((fd= my_open(buff, flags,
MYF(MY_WME | MY_FFNF))) < 0)
die("Could not open %s: errno = %d", buff, errno);
+ if (append && my_seek(fd, 0, SEEK_END, MYF(0)) == MY_FILEPOS_ERROR)
+ die("Could not find end of file %s: errno = %d", buff, errno);
if (my_write(fd, (byte*)str, size, MYF(MY_WME|MY_FNABP)))
die("write failed");
my_close(fd, MYF(0));
}
+/*
+ Write the content of str into file
+
+ SYNOPSIS
+ str_to_file
+ fname - name of file to truncate/create and write to
+ str - content to write to file
+ size - size of content witten to file
+*/
+
+void str_to_file(const char *fname, char *str, int size)
+{
+ str_to_file2(fname, str, size, FALSE);
+}
+
void dump_result_to_reject_file(char *buf, int size)
{
@@ -5047,8 +5366,9 @@ void run_query_stmt(MYSQL *mysql, struct st_command *command,
/*
If we got here the statement succeeded and was expected to do so,
get data. Note that this can still give errors found during execution!
+ Store the result of the query if if will return any fields
*/
- if (mysql_stmt_store_result(stmt))
+ if (mysql_stmt_field_count(stmt) && mysql_stmt_store_result(stmt))
{
handle_error(command, mysql_stmt_errno(stmt),
mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds);
@@ -5643,7 +5963,11 @@ int main(int argc, char **argv)
parser.current_line= parser.read_lines= 0;
memset(&var_reg, 0, sizeof(var_reg));
+ init_builtin_echo();
#ifdef __WIN__
+#ifndef USE_CYGWIN
+ is_windows= 1;
+#endif
init_tmp_sh_file();
init_win_path_patterns();
#endif
@@ -5688,15 +6012,13 @@ int main(int argc, char **argv)
#ifdef HAVE_OPENSSL
-#if MYSQL_VERSION_ID >= 50000
- opt_ssl_verify_server_cert= TRUE; /* Always on in mysqltest */
-#endif
-
if (opt_use_ssl)
{
mysql_ssl_set(&cur_con->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
opt_ssl_capath, opt_ssl_cipher);
#if MYSQL_VERSION_ID >= 50000
+ /* Turn on ssl_verify_server_cert only if host is "localhost" */
+ opt_ssl_verify_server_cert= opt_host && !strcmp(opt_host, "localhost");
mysql_options(&cur_con->mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
&opt_ssl_verify_server_cert);
#endif
@@ -5761,8 +6083,6 @@ int main(int argc, char **argv)
case Q_DISABLE_RESULT_LOG: disable_result_log=1; break;
case Q_ENABLE_WARNINGS: disable_warnings=0; break;
case Q_DISABLE_WARNINGS: disable_warnings=1; break;
- case Q_ENABLE_PS_WARNINGS: disable_ps_warnings=0; break;
- case Q_DISABLE_PS_WARNINGS: disable_ps_warnings=1; 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;
@@ -5778,6 +6098,9 @@ int main(int argc, char **argv)
case Q_REMOVE_FILE: do_remove_file(command); break;
case Q_FILE_EXIST: do_file_exist(command); break;
case Q_WRITE_FILE: do_write_file(command); break;
+ case Q_APPEND_FILE: do_append_file(command); break;
+ case Q_DIFF_FILES: do_diff_files(command); break;
+ case Q_CAT_FILE: do_cat_file(command); break;
case Q_COPY_FILE: do_copy_file(command); break;
case Q_CHMOD_FILE: do_chmod_file(command); break;
case Q_PERL: do_perl(command); break;