summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--client/Makefile.am4
-rw-r--r--client/client_priv.h2
-rw-r--r--client/mysqlslap.c1162
-rwxr-xr-xmysql-test/mysql-test-run.pl15
-rw-r--r--mysql-test/mysql-test-run.sh11
-rw-r--r--mysql-test/r/mysqlslap.result68
-rw-r--r--mysql-test/t/mysqlslap.test9
7 files changed, 1267 insertions, 4 deletions
diff --git a/client/Makefile.am b/client/Makefile.am
index 804f194085f..4d4bb55cc17 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -31,7 +31,8 @@ LDADD= @CLIENT_EXTRA_LDFLAGS@ \
$(top_builddir)/libmysql/libmysqlclient.la
bin_PROGRAMS = mysql mysqladmin mysqlcheck mysqlshow \
mysqldump mysqlimport mysqltest mysqlbinlog \
- mysqltestmanagerc mysqltestmanager-pwgen
+ mysqltestmanagerc mysqltestmanager-pwgen \
+ mysqlslap
noinst_HEADERS = sql_string.h completion_hash.h my_readline.h \
client_priv.h
mysql_SOURCES = mysql.cc readline.cc sql_string.cc completion_hash.cc
@@ -46,6 +47,7 @@ mysqltestmanager_pwgen_SOURCES = mysqlmanager-pwgen.c
mysqltestmanagerc_SOURCES= mysqlmanagerc.c $(yassl_dummy_link_fix)
mysqlcheck_SOURCES= mysqlcheck.c $(yassl_dummy_link_fix)
mysqlshow_SOURCES= mysqlshow.c $(yassl_dummy_link_fix)
+mysqlslap_SOURCES= mysqlslap.c $(yassl_dummy_link_fix)
mysqldump_SOURCES= mysqldump.c $(yassl_dummy_link_fix)
mysqlimport_SOURCES= mysqlimport.c $(yassl_dummy_link_fix)
sql_src=log_event.h mysql_priv.h log_event.cc my_decimal.h my_decimal.cc
diff --git a/client/client_priv.h b/client/client_priv.h
index a9d5364df49..3aff331a472 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -51,5 +51,5 @@ enum options_client
#endif
OPT_TRIGGERS,
OPT_IGNORE_TABLE,OPT_INSERT_IGNORE,OPT_SHOW_WARNINGS,OPT_DROP_DATABASE,
- OPT_TZ_UTC, OPT_AUTO_CLOSE
+ OPT_TZ_UTC, OPT_AUTO_CLOSE, OPT_CREATE_SLAP_SCHEMA
};
diff --git a/client/mysqlslap.c b/client/mysqlslap.c
new file mode 100644
index 00000000000..5e280b332bf
--- /dev/null
+++ b/client/mysqlslap.c
@@ -0,0 +1,1162 @@
+/* Copyright (C) 2005 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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
+
+ coded by: Patrick Galbraith
+*/
+
+
+/*
+
+ MySQL Slap
+
+ A simple program designed to work as if multiple clients querying the database,
+ then reporting the timing of each stage.
+
+ MySQL slap runs three stages:
+ 1) Create Schema (single client)
+ 2) Insert data (many clients)
+ 3) Load test (many clients)
+ 4) Cleanup (disconnection, drop table if specified, single client)
+
+Examples:
+
+Supply your own create, insert and query SQL statements, with 5 clients
+loading (10 inserts for each), 50 clients querying:
+
+./mysqlslap --create="CREATE TABLE A (a int)" --data="INSERT INTO A (23)" --iterations=200
+ --query="SELECT * FROM A" --number-rows=10 --concurrency=50 --load-concurrency=5
+
+Let the program build create, insert and query SQL statements with a table of
+two int columns, 3 varchar columns, with 5 clients loading data
+(12 inserts each), 5 clients querying, drop schema before creating:
+
+./mysqlslap --concurrency=5 --concurrency-load=5 --iterations=20 --number-int-cols=2 --number-char-cols=3 --number-rows=12 --auto-generate-sql
+
+Let the program build the query SQL statement with a table of
+two int columns, 3 varchar columns, 5 clients querying, don't
+create the table or insert the data (using the previous test's schema
+and data)
+
+./mysqlslap --concurrency=5 --iterations=20 --number-int-cols=2 --number-char-cols=3 --number-rows=12 --auto-generate-sql --skip-data-load --skip-create-schema
+
+Tell the program to load the create, insert and query SQL statements
+from the specified files which the create.sql file has multiple table creation
+statements delimited by ';', multiple insert statements delimited by ';',
+and multiple queries delimited by ';', run all the load statements with 5
+clients, 5 times per client, and run all the queries in the query file with
+5 clients:
+
+/mysqlslap --drop-schema --concurrency=5 --concurrency-load=5 --iterations=5 --query=query.sql --create=create.sql --data=insert.sql --delimiter=";" --number-rows=5
+
+Same as the last test run, with short options
+./mysqlslap -D -c 5 -l 5 -i 5 -q query.sql --create create.sql -d insert.sql -F ";" -n 5
+
+*/
+
+#define SHOW_VERSION "0.1"
+
+#define HUGE_STRING_LENGTH 8096
+#define RAND_STRING_SIZE 126
+
+#include "client_priv.h"
+#include <my_sys.h>
+#include <m_string.h>
+#include <mysql.h>
+#include <mysqld_error.h>
+#include <my_dir.h>
+#include <signal.h>
+#include <stdarg.h>
+#include <sslopt-vars.h>
+#include <sys/time.h>
+#include <sys/ipc.h>
+#include <sys/shm.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+
+
+static int drop_schema(MYSQL *mysql, const char *db);
+unsigned int get_random_number(void);
+unsigned int get_random_string(char *buf);
+static int build_table_string(void);
+static int build_insert_string(void);
+static int build_query_string(void);
+static int create_schema(MYSQL *mysql, const char *db,const char *script);
+static int run_scheduler(const char *script, int(*task)(const char *),
+ unsigned int concur);
+int run_task(const char *script);
+int load_data(const char *script);
+
+static char *host= NULL, *opt_password= NULL, *user= NULL,
+ *user_supplied_query= NULL, *user_supplied_data= NULL,
+ *create_string= NULL, *default_engine= NULL, *delimiter= NULL,
+ *opt_mysql_unix_port= NULL;
+
+static my_bool opt_compress= FALSE, opt_count= FALSE, tty_password= FALSE,
+ opt_drop= FALSE, create_string_alloced= FALSE,
+ insert_string_alloced= FALSE, query_string_alloced= FALSE,
+ generated_insert_flag= FALSE, opt_silent= FALSE,
+ auto_generate_sql= FALSE, opt_skip_create= FALSE,
+ opt_skip_data_load= FALSE, opt_skip_query= FALSE;
+
+static int verbose= 0, num_int_cols=-1, num_char_cols=-1, delimiter_length= 0;
+static char *default_charset= (char*) MYSQL_DEFAULT_CHARSET_NAME;
+static unsigned int number_of_rows= 1000, number_of_iterations= 1000,
+ concurrency= 1, concurrency_load= 1, children_spawned= 1;
+
+const char *default_dbug_option="d:t:o,/tmp/mysqlslap.trace";
+
+static uint opt_protocol= 0;
+
+static void get_options(int *argc,char ***argv);
+static uint opt_mysql_port= 0;
+
+static const char *load_default_groups[]= { "mysqlslap","client",0 };
+#if ELEGANT_SOLUTION
+static const char ALPHANUMERICS[]=
+ "0123456789ABCDEFGHIJKLMNOPQRSTWXYZabcdefghijklmnopqrstuvwxyz";
+static const ALPHANUMERICS_SIZE= (sizeof(ALPHANUMERICS)-1);
+#endif
+
+/* returns the time in ms between two timevals */
+
+static double timedif(struct timeval end, struct timeval begin)
+{
+ double seconds;
+ DBUG_ENTER("timedif");
+
+ seconds= (double)(end.tv_usec - begin.tv_usec)/1000000;
+ DBUG_PRINT("info", ("end.tv_usec %d - begin.tv_usec %d = %d microseconds ( fseconds %f)",
+ end.tv_usec, begin.tv_usec,
+ (end.tv_usec - begin.tv_usec),
+ seconds));
+ seconds += (double)(end.tv_sec - begin.tv_sec);
+ DBUG_PRINT("info", ("end.tv_sec %d - begin.tv_sec %d = %d seconds (fseconds %f)",
+ end.tv_sec, begin.tv_sec,
+ (end.tv_sec - begin.tv_sec), seconds));
+
+ DBUG_PRINT("info", ("returning time %f seconds", seconds));
+ DBUG_RETURN(seconds);
+}
+
+
+int main(int argc, char **argv)
+{
+ my_bool first_argument_uses_wildcards= 0;
+ char *wild;
+ MYSQL mysql;
+ int client_flag= 0;
+ double time_difference;
+ struct timeval tmp_time, start_time, load_time, run_time;
+ /* for the string generation later */
+
+ DBUG_ENTER("main");
+ MY_INIT(argv[0]);
+
+ /* for any string generation later on */
+ if (auto_generate_sql)
+ srandom((unsigned int) tmp_time.tv_usec);
+
+ bzero(&load_time, sizeof(struct timeval));
+ bzero(&run_time, sizeof(struct timeval));
+ load_defaults("my",load_default_groups,&argc,&argv);
+ get_options(&argc,&argv);
+ /* globals? Yes, so we only have to run strlen once */
+ if (delimiter)
+ delimiter_length= strlen(delimiter);
+
+ wild= 0;
+ if (argc)
+ {
+ char *pos= argv[argc-1], *to;
+ for (to= pos ; *pos ; pos++, to++)
+ {
+ switch (*pos) {
+ case '*':
+ *pos= '%';
+ first_argument_uses_wildcards= 1;
+ break;
+ case '?':
+ *pos= '_';
+ first_argument_uses_wildcards= 1;
+ break;
+ case '%':
+ case '_':
+ first_argument_uses_wildcards= 1;
+ break;
+ case '\\':
+ pos++;
+ default: break;
+ }
+ *to= *pos;
+ }
+ *to= *pos; /* just to copy a '\0' if '\\' was used */
+ }
+ if (first_argument_uses_wildcards)
+ wild= argv[--argc];
+ else if (argc == 3) /* We only want one field */
+ wild= argv[--argc];
+
+ if (argc > 2)
+ {
+ fprintf(stderr,"%s: Too many arguments\n",my_progname);
+ exit(1);
+ }
+ mysql_init(&mysql);
+ if (opt_compress)
+ mysql_options(&mysql,MYSQL_OPT_COMPRESS,NullS);
+#ifdef HAVE_OPENSSL
+ if (opt_use_ssl)
+ mysql_ssl_set(&mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
+ opt_ssl_capath, opt_ssl_cipher);
+#endif
+ if (opt_protocol)
+ mysql_options(&mysql,MYSQL_OPT_PROTOCOL,(char*)&opt_protocol);
+#ifdef HAVE_SMEM
+ if (shared_memory_base_name)
+ mysql_options(&mysql,MYSQL_SHARED_MEMORY_BASE_NAME,shared_memory_base_name);
+#endif
+ mysql_options(&mysql, MYSQL_SET_CHARSET_NAME, default_charset);
+
+ client_flag|= CLIENT_MULTI_RESULTS;
+ if (!(mysql_real_connect(&mysql,host,user,opt_password,
+ (first_argument_uses_wildcards) ? "" :
+ argv[0],opt_mysql_port,opt_mysql_unix_port,
+ client_flag)))
+ {
+ fprintf(stderr,"%s: %s\n",my_progname,mysql_error(&mysql));
+ exit(1);
+ }
+
+ /*
+ we might not want to load any data, if for instance we are calling
+ a stored_procedure that doesn't use data, or we know we already have
+ data in the table
+ */
+ if (opt_drop)
+ drop_schema(&mysql, "mysqlslap");
+
+ if (!opt_skip_create)
+ create_schema(&mysql, "mysqlslap", create_string);
+
+ if (!opt_skip_data_load)
+ {
+ gettimeofday(&start_time, NULL);
+ DBUG_PRINT("info", ("user_supplied_data %s", user_supplied_data));
+ run_scheduler(user_supplied_data, load_data, concurrency_load);
+ gettimeofday(&load_time, NULL);
+ time_difference= timedif(load_time, start_time);
+ if (!opt_silent)
+ {
+ printf("Seconds to load data: %.5f\n",time_difference);
+ printf("Number of clients loading data: %d\n", children_spawned);
+ printf("Number of inserts per client: %d\n", number_of_rows);
+ }
+ }
+
+ if (!opt_skip_query)
+ {
+ run_scheduler(user_supplied_query, run_task, concurrency);
+ gettimeofday(&run_time, 0);
+ time_difference= timedif(run_time, load_time);
+
+ if (!opt_silent)
+ {
+ printf("Seconds to run all queries: %.5f\n", time_difference);
+ printf("Number of clients running queries: %d\n", children_spawned);
+ printf("Number of queries per client: %d\n", number_of_iterations);
+ }
+ }
+ if (opt_drop)
+ drop_schema(&mysql, "mysqlslap");
+
+ mysql_close(&mysql); /* Close & free connection */
+
+ /* now free all the strings we created */
+ if (opt_password)
+ my_free(opt_password,MYF(0));
+ if (create_string_alloced)
+ my_free(create_string,MYF(0));
+ if (insert_string_alloced)
+ my_free(user_supplied_data,MYF(0));
+ if (query_string_alloced)
+ my_free(user_supplied_query,MYF(0));
+#ifdef HAVE_SMEM
+ if (shared_memory_base_name)
+ my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
+#endif
+ my_end(0);
+
+ DBUG_RETURN(0); /* No compiler warnings */
+}
+
+static struct my_option my_long_options[] =
+{
+ {"auto-generate-sql", 'a', "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},
+ {"compress", 'C', "Use compression in server/client protocol.",
+ (gptr*) &opt_compress, (gptr*) &opt_compress, 0, GET_BOOL, NO_ARG, 0, 0, 0,
+ 0, 0, 0},
+ {"concurrency-load", 'l', "Number of clients to simulate for data load.",
+ (gptr*) &concurrency_load, (gptr*) &concurrency_load, 0,
+ GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"concurrency", 'c', "Number of clients to simulate for query to run.",
+ (gptr*) &concurrency, (gptr*) &concurrency, 0, GET_UINT,
+ REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"create", OPT_CREATE_SLAP_SCHEMA, "File or string to use for create.",
+ (gptr*) &create_string, (gptr*) &create_string, 0, GET_STR, REQUIRED_ARG,
+ 0, 0, 0, 0, 0, 0},
+ {"data", 'd',
+ "File or string with INSERT to use for populating table(s).",
+ (gptr*) &user_supplied_data, (gptr*) &user_supplied_data, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.",
+ (gptr*) &default_dbug_option, (gptr*) &default_dbug_option, 0, GET_STR,
+ OPT_ARG, 0, 0, 0, 0, 0, 0},
+ {"delimiter", 'F', "Delimiter to use in SQL statements supplied in file or command line.",
+ (gptr*) &delimiter, (gptr*) &delimiter, 0, GET_STR, REQUIRED_ARG,
+ 0, 0, 0, 0, 0, 0},
+ {"drop-schema", 'D',
+ "Drop schema if it exists prior to running, and after running",
+ (gptr*) &opt_drop, (gptr*) &opt_drop, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"engine", 'e', "Storage engine to use for creating the table.",
+ (gptr*) &default_engine, (gptr*) &default_engine, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, 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},
+ {"iterations", 'i', "Number of iterations.", (gptr*) &number_of_iterations,
+ (gptr*) &number_of_iterations, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"number-char-cols", 'x', "Number of INT columns to create table with if specifying --sql-generate-sql.",
+ (gptr*) &num_char_cols, (gptr*) &num_char_cols, 0, GET_UINT, REQUIRED_ARG,
+ 0, 0, 0, 0, 0, 0},
+ {"number-int-cols", 'y', "Number of VARCHAR columns to create table with if specifying --sql-generate-sql.",
+ (gptr*) &num_int_cols, (gptr*) &num_int_cols, 0, GET_UINT, REQUIRED_ARG,
+ 0, 0, 0, 0, 0, 0},
+ {"number-rows", 'n', "Number of rows to insert when loading data.", (gptr*) &number_of_rows,
+ (gptr*) &number_of_rows, 0, GET_UINT, REQUIRED_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},
+ {"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},
+#ifdef __WIN__
+ {"pipe", 'W', "Use named pipes to connect to server.", 0, 0, 0, GET_NO_ARG,
+ NO_ARG, 0, 0, 0, 0, 0, 0},
+#endif
+ {"protocol", OPT_MYSQL_PROTOCOL,
+ "The protocol of connection (tcp,socket,pipe,memory).",
+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"skip-create-schema", 'A', "Don't create a schema, use existing schema.",
+ (gptr*) &opt_skip_create, (gptr*) &opt_skip_create, 0, GET_BOOL, NO_ARG,
+ 0, 0, 0, 0, 0, 0},
+ {"skip-data-load", 'L', "Don't load any data, use existing data set.",
+ (gptr*) &opt_skip_data_load, (gptr*) &opt_skip_data_load, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"skip-query", 'Q', "Don't run any queries.",
+ (gptr*) &opt_skip_query, (gptr*) &opt_skip_query, 0, GET_BOOL, NO_ARG,
+ 0, 0, 0, 0, 0, 0},
+ {"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},
+#ifdef HAVE_SMEM
+ {"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
+ "Base name of shared memory.", (gptr*) &shared_memory_base_name,
+ (gptr*) &shared_memory_base_name, 0, GET_STR_ALLOC, REQUIRED_ARG,
+ 0, 0, 0, 0, 0, 0},
+#endif
+ {"query", 'q', "Query to run or file containing query to run.",
+ (gptr*) &user_supplied_query, (gptr*) &user_supplied_query,
+ 0, GET_STR, REQUIRED_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>
+#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},
+#endif
+ {"verbose", 'v',
+ "More verbose output; You can use this multiple times to get even more verbose output.",
+ (gptr*) &verbose, (gptr*) &verbose, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"version", 'V', "Output version information and exit.", 0, 0, 0, GET_NO_ARG,
+ NO_ARG, 0, 0, 0, 0, 0, 0},
+ {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
+};
+
+
+#include <help_start.h>
+
+static void print_version(void)
+{
+ printf("%s Ver %s Distrib %s, for %s (%s)\n",my_progname,SHOW_VERSION,
+ MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
+}
+
+
+static void usage(void)
+{
+ print_version();
+ puts("Copyright (C) 2005 MySQL AB");
+ puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,\
+ \nand you are welcome to modify and redistribute it under the GPL \
+ license\n");
+ puts("Run a query multiple times against the server\n");
+ printf("Usage: %s [OPTIONS] [database [table [column]]]\n",my_progname);
+ print_defaults("my",load_default_groups);
+ my_print_help(my_long_options);
+}
+
+#include <help_end.h>
+
+static my_bool
+get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
+ char *argument)
+{
+ DBUG_ENTER("get_one_option");
+ switch(optid) {
+#ifdef __NETWARE__
+ case OPT_AUTO_CLOSE:
+ setscreenmode(SCR_AUTOCLOSE_ON_EXIT);
+ break;
+#endif
+ case 'v':
+ verbose++;
+ break;
+ case 'p':
+ if (argument)
+ {
+ char *start= argument;
+ my_free(opt_password,MYF(MY_ALLOW_ZERO_PTR));
+ opt_password= my_strdup(argument,MYF(MY_FAE));
+ while (*argument) *argument++= 'x'; /* Destroy argument */
+ if (*start)
+ start[1]= 0; /* Cut length of argument */
+ tty_password= 0;
+ }
+ else
+ tty_password= 1;
+ break;
+ case 'W':
+#ifdef __WIN__
+ opt_protocol= MYSQL_PROTOCOL_PIPE;
+#endif
+ break;
+ case OPT_MYSQL_PROTOCOL:
+ {
+ if ((opt_protocol= find_type(argument, &sql_protocol_typelib,0)) <= 0)
+ {
+ fprintf(stderr, "Unknown option to protocol: %s\n", argument);
+ exit(1);
+ }
+ break;
+ }
+ case '#':
+ DBUG_PUSH(argument ? argument : default_dbug_option);
+ break;
+#include <sslopt-case.h>
+ case 'V':
+ print_version();
+ exit(0);
+ break;
+ case '?':
+ case 'I': /* Info */
+ usage();
+ exit(0);
+ }
+ DBUG_RETURN(0);
+}
+
+/*
+ get_random_number()
+
+ returns a random number to be used in building an sql statement
+*/
+unsigned int
+get_random_number(void)
+{
+ int num;
+ char rstate[8];
+ struct timeval timestruct;
+
+ DBUG_ENTER("get_random_number");
+ gettimeofday(&timestruct, NULL);
+ initstate(timestruct.tv_usec, rstate, sizeof(rstate));
+ setstate(rstate);
+ num= random();
+ DBUG_RETURN(num);
+}
+
+unsigned int
+get_random_string(char *buf)
+{
+ char *buf_ptr= buf;
+ int x, chr= 0;
+
+ DBUG_ENTER("get_random_string");
+ for (x= RAND_STRING_SIZE; x > 0; x--)
+ {
+ /*
+ why this tmp_num? Because for some reason, x's value gets
+ munged during call of random()
+ */
+ int tmp_num= x;
+ chr= random()% tmp_num;
+ /*
+ avoiding problematic chars for insert
+ */
+ if (chr >= 48 && chr <= 122 && chr != 96 && chr != 92)
+ *buf_ptr++= chr;
+ }
+
+ /*
+ strlen
+ */
+ DBUG_RETURN(buf_ptr- buf);
+}
+#if ELEGANT_SOLUTION
+/*
+ I would like to use this, but for some reason, subsequent calls to
+ this function result in buf having non-alpha characters added beyond it's
+ size, which in turn corrupt the insert string.
+*/
+unsigned int
+get_random_string(char *buf)
+{
+ char *buf_ptr=buf;
+ int x= RAND_STRING_SIZE;
+
+ DBUG_ENTER("get_random_string");
+ DBUG_PRINT("info", ("RANDOM STRING buf %s length %d", buf, buf_ptr - buf));
+ while(x--)
+ {
+ int tmp_x=x;
+ *buf_ptr++= ALPHANUMERICS[random() % ALPHANUMERICS_SIZE];
+ x= tmp_x;
+ //fprintf(stderr, "get_random_string %s %lx x %d\n", buf_ptr, buf_ptr,
+ //tmp_x);
+ }
+ DBUG_PRINT("info", ("RANDOM STRING buf %s length %d", buf, buf_ptr - buf));
+
+ /* strlen */
+ DBUG_RETURN(buf_ptr- buf);
+}
+#endif
+/*
+ build_table_string
+
+ This function builds a create table query if the user opts to not supply
+ a file or string containing a create table statement
+*/
+static int
+build_table_string(void)
+{
+ char buf[512];
+ int col_count;
+ DYNAMIC_STRING table_string;
+ DBUG_ENTER("build_table_string");
+
+ DBUG_PRINT("info", ("num int cols %d num char cols %d",
+ num_int_cols, num_char_cols));
+
+ init_dynamic_string(&table_string, "", 1024, 1024);
+
+ dynstr_append_mem(&table_string, "CREATE TABLE `t1` (\n", 20);
+ for (col_count= 1; col_count <= num_int_cols; col_count++)
+ {
+ sprintf(buf, "intcol%d INT(32)", col_count);
+ dynstr_append(&table_string, buf);
+
+ if (col_count < num_int_cols || num_char_cols > 0)
+ dynstr_append_mem(&table_string, ",", 1);
+
+ dynstr_append_mem(&table_string, "\n", 1);
+ }
+ for (col_count= 1; col_count <= num_char_cols; col_count++)
+ {
+ sprintf(buf, "charcol%d VARCHAR(128)", col_count);
+ dynstr_append(&table_string, buf);
+
+ if (col_count < num_char_cols)
+ dynstr_append_mem(&table_string, ",", 1);
+
+ dynstr_append_mem(&table_string, "\n", 1);
+ }
+ dynstr_append_mem(&table_string, ")\n", 2);
+ create_string= (char *)my_malloc(table_string.length+1, MYF(MY_WME));
+ create_string_alloced= 1;
+ strmov(create_string, table_string.str);
+ DBUG_PRINT("info", ("create_string %s", create_string));
+ dynstr_free(&table_string);
+ DBUG_RETURN(0);
+}
+
+/*
+ build_insert_string()
+
+ This function builds insert statements when the user opts to not supply
+ a insert file or string containing insert data
+*/
+static int
+build_insert_string(void)
+{
+ char buf[RAND_STRING_SIZE];
+ int col_count;
+ DYNAMIC_STRING insert_string;
+ MYSQL mysql;
+ DBUG_ENTER("build_insert_string");
+ mysql_init(&mysql);
+
+ 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++)
+ {
+ sprintf(buf, "%d", get_random_number());
+ dynstr_append(&insert_string, buf);
+
+ if (col_count < num_int_cols || num_char_cols > 0)
+ dynstr_append_mem(&insert_string, ",", 1);
+ }
+ for (col_count= 1; col_count <= num_char_cols; col_count++)
+ {
+ char *buf_tmp= (char *) my_malloc(RAND_STRING_SIZE, MYF(MY_WME));
+ int buf_len;
+ buf_len= get_random_string((char *) &buf);
+ mysql_real_escape_string(&mysql, buf_tmp, (char *) &buf, buf_len);
+ dynstr_append_mem(&insert_string, "'", 1);
+ dynstr_append_mem(&insert_string, buf_tmp, buf_len);
+ dynstr_append_mem(&insert_string, "'", 1);
+ my_free(buf_tmp, MYF(0));
+
+ if (col_count < num_char_cols)
+ dynstr_append_mem(&insert_string, ",", 1);
+
+ }
+ dynstr_append_mem(&insert_string, ")", 1);
+
+ /*
+ since this function can be called if the user wants varying insert
+ statement in the for loop where inserts run, free in advance
+ */
+ if (insert_string_alloced)
+ my_free(user_supplied_data,MYF(0));
+ user_supplied_data= (char *)my_malloc(insert_string.length+1, MYF(MY_WME));
+ insert_string_alloced= 1;
+ strmov(user_supplied_data, insert_string.str);
+ DBUG_PRINT("info", ("generated_insert_data %s", user_supplied_data));
+ dynstr_free(&insert_string);
+ mysql_close(&mysql);
+ DBUG_RETURN(insert_string.length+1);
+}
+
+/*
+ build_query_string()
+
+ This function builds a query if the user opts to not supply a query
+ statement or file containing a query statement
+*/
+static int
+build_query_string(void)
+{
+ char buf[512];
+ int col_count;
+ static DYNAMIC_STRING query_string;
+ DBUG_ENTER("build_query_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);
+ dynstr_append(&query_string, buf);
+
+ if (col_count < num_int_cols || num_char_cols > 0)
+ dynstr_append_mem(&query_string, ",", 1);
+
+ }
+ for (col_count= 1; col_count <= num_char_cols; col_count++)
+ {
+ sprintf(buf, "charcol%d", col_count);
+ 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);
+ user_supplied_query= (char *)my_malloc(query_string.length+1, MYF(MY_WME));
+ query_string_alloced= 1;
+ strmov(user_supplied_query, query_string.str);
+ DBUG_PRINT("info", ("user_supplied_query %s", user_supplied_query));
+ dynstr_free(&query_string);
+ DBUG_RETURN(0);
+}
+
+static void
+get_options(int *argc,char ***argv)
+{
+ int ho_error;
+ MY_STAT sbuf; /* Stat information for the data file */
+
+ DBUG_ENTER("get_options");
+ if ((ho_error= handle_options(argc, argv, my_long_options, get_one_option)))
+ exit(ho_error);
+
+ /*
+ Default policy - if they don't supply either char or int cols, and
+ also no data, then default to 1 of each.
+ */
+ if (num_int_cols == 0 && num_char_cols == 0 && auto_generate_sql &&
+ !user_supplied_data)
+ {
+ num_int_cols= 1;
+ num_char_cols= 1;
+ }
+
+ if (!default_engine)
+ default_engine= (char *)"MYISAM";
+
+ if (!user)
+ user= (char *)"root";
+
+ if(auto_generate_sql && create_string &&
+ user_supplied_data && user_supplied_query)
+ {
+ fprintf(stderr,
+ "%s: Can't use --auto-generate-sql when create, insert, and query strings are specified!\n",
+ my_progname);
+ exit(1);
+ }
+
+ if (opt_skip_create && opt_drop)
+ {
+ fprintf(stderr,"You cannot specify to drop the schema and skip schema creation!\n");
+ exit(1);
+ }
+
+ if (!opt_skip_create)
+ {
+ if (auto_generate_sql && !create_string)
+ build_table_string();
+ else if (create_string && my_stat(create_string, &sbuf, MYF(0)))
+ {
+ File data_file;
+ if (!MY_S_ISREG(sbuf.st_mode))
+ {
+ fprintf(stderr,"%s: Create file was not a regular file\n",
+ my_progname);
+ exit(1);
+ }
+ if ((data_file= my_open(create_string, O_RDWR, MYF(0))) == -1)
+ {
+ fprintf(stderr,"%s: Could not open create file\n", my_progname);
+ exit(1);
+ }
+ create_string= (char *)my_malloc(sbuf.st_size+1, MYF(MY_WME));
+ create_string_alloced= 1;
+ my_read(data_file, create_string, sbuf.st_size, MYF(0));
+ create_string[sbuf.st_size]= '\0';
+ my_close(data_file,MYF(0));
+ }
+ else if (!auto_generate_sql && !create_string)
+ {
+ fprintf(stderr,"%s: Must use --auto-generate-sql or --create option\n",
+ my_progname);
+ exit(1);
+ }
+ }
+
+ if (opt_skip_data_load)
+ {
+ if (user_supplied_data)
+ fprintf(stderr,
+ "Warning: Specified data to INSERT, but data load is disabled.\n");
+ }
+ else
+ {
+ if (!user_supplied_data && auto_generate_sql)
+ {
+ int length;
+ generated_insert_flag= 1;
+ length= build_insert_string();
+ DBUG_PRINT("info", ("user_supplied_data is %s", user_supplied_data));
+ }
+ else if (my_stat(user_supplied_data, &sbuf, MYF(0)))
+ {
+ File data_file;
+ if (!MY_S_ISREG(sbuf.st_mode))
+ {
+ fprintf(stderr,"%s: User data supplied file was not a regular file\n",
+ my_progname);
+ exit(1);
+ }
+ if ((data_file= my_open(user_supplied_data, O_RDWR, MYF(0))) == -1)
+ {
+ fprintf(stderr,"%s: Could not open data supplied file\n", my_progname);
+ exit(1);
+ }
+ user_supplied_data= (char *)my_malloc(sbuf.st_size+1, MYF(MY_WME));
+ insert_string_alloced= 1;
+ my_read(data_file, user_supplied_data, sbuf.st_size, MYF(0));
+ user_supplied_data[sbuf.st_size]= '\0';
+ my_close(data_file,MYF(0));
+ }
+ else if (!user_supplied_query && !auto_generate_sql)
+ {
+ fprintf(stderr,"%s: No user supplied data to insert or --auto-generate-sql\
+ specified!\n", my_progname);
+ exit(1);
+ }
+ }
+
+ if (!opt_skip_query)
+ {
+ if (!user_supplied_query && auto_generate_sql)
+ {
+ build_query_string();
+ }
+ else if (my_stat(user_supplied_query, &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_query, O_RDWR, MYF(0))) == -1)
+ {
+ fprintf(stderr,"%s: Could not open query supplied file\n", my_progname);
+ exit(1);
+ }
+ user_supplied_query= (char *)my_malloc(sbuf.st_size+1, MYF(MY_WME));
+ query_string_alloced= 1;
+ my_read(data_file, user_supplied_query, sbuf.st_size, MYF(0));
+ user_supplied_query[sbuf.st_size]= '\0';
+ my_close(data_file,MYF(0));
+ }
+ else if (!user_supplied_query && !auto_generate_sql)
+ {
+ fprintf(stderr,"%s: No user supplied query or --auto-generate-sql\
+ specified!\n", my_progname);
+ exit(1);
+ }
+ }
+
+ if (tty_password)
+ opt_password= get_tty_password(NullS);
+ if (opt_count)
+ {
+ /*
+ We need to set verbose to 2 as we need to change the output to include
+ the number-of-rows column
+ */
+ verbose= 2;
+ }
+ DBUG_VOID_RETURN;
+}
+
+
+static int
+create_schema(MYSQL *mysql,const char *db,const char *script)
+{
+ char query[HUGE_STRING_LENGTH], buffer[HUGE_STRING_LENGTH];
+
+ DBUG_ENTER("create_schema");
+ snprintf(query, HUGE_STRING_LENGTH, "DROP SCHEMA IF EXISTS `%s`", db);
+ DBUG_PRINT("info", ("query %s", query));
+ mysql_query(mysql, query);
+
+ snprintf(query, HUGE_STRING_LENGTH, "CREATE SCHEMA `%s`", db);
+ DBUG_PRINT("info", ("query %s", query));
+ if (mysql_query(mysql, query))
+ {
+ fprintf(stderr,"%s: Cannot create schema %s : %s\n", my_progname, db,
+ mysql_error(mysql));
+ exit(1);
+ }
+
+ if (mysql_select_db(mysql,db))
+ {
+ fprintf(stderr,"%s: Cannot select schema '%s': %s\n",my_progname, db,
+ mysql_error(mysql));
+ exit(1);
+ }
+
+ snprintf(buffer, HUGE_STRING_LENGTH, "set storage_engine=`%s`",
+ default_engine);
+ if (mysql_query(mysql, buffer))
+ {
+ fprintf(stderr,"%s: Cannot set default engine: %s\n", my_progname,
+ mysql_error(mysql));
+ exit(1);
+ }
+
+ if (delimiter)
+ {
+ char *retstr;
+ char buf[HUGE_STRING_LENGTH];
+
+ while((retstr= strstr(script, delimiter)))
+ {
+ strncpy((char*)&buf, script, retstr - script);
+ buf[retstr - script]= '\0';
+ script+= retstr - script + delimiter_length;
+ DBUG_PRINT("info", ("running create QUERY %s", (char *)buf));
+ if (mysql_query(mysql, buf))
+ {
+ fprintf(stderr,"%s: Cannot run query %s ERROR : %s\n",
+ my_progname, (char *)buf, mysql_error(mysql));
+ exit(1);
+ }
+ }
+ }
+ /*
+ remainder, if there was a delimeter, or the whole query if not a
+ delimiter. If less than 3, can't be anything useful
+ */
+ if ((strlen(script)) < 3)
+ DBUG_RETURN(0);
+ if (mysql_query(mysql, script))
+ {
+ fprintf(stderr,"%s: Cannot create tables: %s\n", my_progname,
+ mysql_error(mysql));
+ exit(1);
+ }
+
+ DBUG_RETURN(0);
+}
+
+static int
+drop_schema(MYSQL *mysql,const char *db)
+{
+ char query[HUGE_STRING_LENGTH];
+
+ DBUG_ENTER("drop_schema");
+ snprintf(query, HUGE_STRING_LENGTH, "DROP SCHEMA IF EXISTS `%s`", db);
+ if (mysql_query(mysql, query))
+ {
+ fprintf(stderr,"%s: Cannot drop database '%s' ERROR : %s\n",
+ my_progname, db, mysql_error(mysql));
+ exit(1);
+ }
+
+ DBUG_RETURN(0);
+}
+
+
+static int
+run_scheduler(const char *script,
+ int(*task)(const char *), unsigned int concur)
+{
+ uint x;
+
+ DBUG_ENTER("run_scheduler");
+ /*
+ reset to 0
+ */
+ children_spawned= 0;
+
+ for (x= 0; x < concur; x++)
+ {
+ int pid;
+ DBUG_PRINT("info", ("x %d concurrency %d", x, concurrency));
+ pid= fork();
+ switch(pid)
+ {
+ case 0:
+ /* child */
+ DBUG_PRINT("info", ("fork returned 0, calling task(\"%s\"), pid %d gid %d",
+ script, pid, getgid()));
+ if (verbose >= 2)
+ fprintf(stderr,
+ "%s: fork returned 0, calling task(\"%s\") pid %d gid %d\n",
+ my_progname, script, pid, getgid());
+ task(script);
+ 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;
+ }
+ children_spawned++;
+ }
+
+WAIT:
+ while (x--)
+ {
+ int status, pid;
+ pid= wait(&status);
+ DBUG_PRINT("info", ("Parent: child %d status %d", pid, status));
+ }
+
+ DBUG_RETURN(0);
+}
+
+int
+run_task(const char *script)
+{
+ uint counter= 0, x;
+ MYSQL mysql;
+ MYSQL_RES *result;
+ MYSQL_ROW row;
+
+ DBUG_ENTER("run_task");
+ DBUG_PRINT("info", ("task script \"%s\"", script));
+
+ mysql_init(&mysql);
+
+ DBUG_PRINT("info", ("trying to connect to host %s as user %s", host, user));
+ if (!(mysql_real_connect(&mysql, host, user, opt_password,
+ "mysqlslap", opt_mysql_port, opt_mysql_unix_port,
+ 0)))
+ {
+ fprintf(stderr,"%s: %s\n",my_progname,mysql_error(&mysql));
+ exit(1);
+ }
+ DBUG_PRINT("info", ("connected."));
+
+ for (x= 0; x < number_of_iterations; x++)
+ {
+ if (delimiter)
+ {
+ char *retstr;
+ char buf[HUGE_STRING_LENGTH];
+
+ while((retstr= strstr(script, delimiter)))
+ {
+ strncpy((char*)&buf, script, retstr - script);
+ buf[retstr - script]= '\0';
+ script+= retstr - script + delimiter_length;
+ DBUG_PRINT("info", ("running QUERY %s", (char *)buf));
+ if (mysql_query(&mysql, (char *)buf))
+ {
+ fprintf(stderr,"%s: Cannot run query %s ERROR : %s\n",
+ my_progname, buf, mysql_error(&mysql));
+ exit(1);
+ }
+
+ result= mysql_store_result(&mysql);
+ while ((row = mysql_fetch_row(result)))
+ {
+ counter++;
+ }
+ mysql_free_result(result);
+ result= 0;
+ }
+ }
+ if ((strlen(script)) < 3)
+ DBUG_RETURN(0);
+ if (mysql_query(&mysql, script))
+ {
+ fprintf(stderr,"%s: Cannot run query %s ERROR : %s\n",
+ my_progname, script, mysql_error(&mysql));
+ exit(1);
+ }
+
+ result= mysql_store_result(&mysql);
+ while ((row = mysql_fetch_row(result)))
+ counter++;
+ mysql_free_result(result);
+ result= 0;
+
+ }
+
+ mysql_close(&mysql);
+
+ DBUG_RETURN(0);
+}
+
+
+int
+load_data(const char *script)
+{
+ unsigned int x;
+ MYSQL mysql;
+
+ DBUG_ENTER("load_data");
+ DBUG_PRINT("info", ("task load_data, pid %d", getpid()));
+ mysql_init(&mysql);
+
+ if (!(mysql_real_connect(&mysql, host, user, opt_password,
+ "mysqlslap", opt_mysql_port, opt_mysql_unix_port,
+ 0)))
+ {
+ fprintf(stderr,"%s: Unable to connect to mysqlslap ERROR: %s\n",
+ my_progname, mysql_error(&mysql));
+ exit(1);
+ }
+
+ for (x= 0; x < number_of_rows; x++)
+ {
+ if (delimiter)
+ {
+ char *retstr;
+ char buf[HUGE_STRING_LENGTH];
+
+ while((retstr= strstr(script, delimiter)))
+ {
+ strncpy((char*)&buf, script, retstr - script);
+ buf[retstr - script]= '\0';
+ script+= retstr - script + delimiter_length;
+ DBUG_PRINT("info", ("running INSERT %s", (char *)buf));
+ if (mysql_query(&mysql, (char *)buf))
+ {
+ fprintf(stderr,"%s: Cannot run query %s ERROR : %s\n",
+ my_progname, buf, mysql_error(&mysql));
+ exit(1);
+ }
+ }
+ }
+ if ((strlen(script)) < 3)
+ DBUG_RETURN(0);
+ if (mysql_query(&mysql, script))
+ {
+ DBUG_PRINT("info", ("iteration %d with INSERT statement %s", script));
+ fprintf(stderr,"%s: Cannot insert into table using script: %s ERROR: %s\n",
+ my_progname, script, mysql_error(&mysql));
+ exit(1);
+ }
+ /* this causes variable data on the insert string */
+ if (auto_generate_sql)
+ {
+ build_insert_string();
+ strmov((char *)script, (char *)user_supplied_data);
+ }
+ }
+
+ mysql_close(&mysql);
+
+ DBUG_RETURN(0);
+}
+
diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl
index e2168b7f273..5cbdeb25fde 100755
--- a/mysql-test/mysql-test-run.pl
+++ b/mysql-test/mysql-test-run.pl
@@ -173,6 +173,7 @@ our $exe_mysql_client_test;
our $exe_mysqld;
our $exe_mysqlcheck; # Called from test case
our $exe_mysqldump; # Called from test case
+our $exe_mysqlslap; # Called from test case
our $exe_mysqlimport; # Called from test case
our $exe_mysqlshow; # Called from test case
our $exe_mysql_fix_system_tables;
@@ -930,7 +931,8 @@ sub executable_setup () {
}
$exe_mysqlcheck= mtr_exe_exists("$path_client_bindir/mysqlcheck");
$exe_mysqldump= mtr_exe_exists("$path_client_bindir/mysqldump");
- $exe_mysqlimport= mtr_exe_exists("$path_client_bindir/mysqlimport");
+ $exe_mysqlslap= mtr_exe_exists("$path_client_bindir/mysqlslap");
+ $exe_mysqlimport= mtr_exe_exists("$path_client_bindir/mysqlimport");
$exe_mysqlshow= mtr_exe_exists("$path_client_bindir/mysqlshow");
$exe_mysqlbinlog= mtr_exe_exists("$path_client_bindir/mysqlbinlog");
$exe_mysqladmin= mtr_exe_exists("$path_client_bindir/mysqladmin");
@@ -947,7 +949,7 @@ sub executable_setup () {
$path_client_bindir= mtr_path_exists("$glob_basedir/bin");
$exe_mysqlcheck= mtr_exe_exists("$path_client_bindir/mysqlcheck");
$exe_mysqldump= mtr_exe_exists("$path_client_bindir/mysqldump");
- $exe_mysqlimport= mtr_exe_exists("$path_client_bindir/mysqlimport");
+ $exe_mysqlslap= mtr_exe_exists("$path_client_bindir/mysqlslap");
$exe_mysqlshow= mtr_exe_exists("$path_client_bindir/mysqlshow");
$exe_mysqlbinlog= mtr_exe_exists("$path_client_bindir/mysqlbinlog");
$exe_mysqladmin= mtr_exe_exists("$path_client_bindir/mysqladmin");
@@ -2458,6 +2460,14 @@ sub run_mysqltest ($) {
$cmdline_mysqldump .=
" --debug=d:t:A,$opt_vardir/log/mysqldump.trace";
}
+ my $cmdline_mysqlslap= "$exe_mysqlslap -uroot " .
+ "--port=$master->[0]->{'path_myport'} " .
+ "--socket=$master->[0]->{'path_mysock'} --password=";
+ if ( $opt_debug )
+ {
+ $cmdline_mysqlslap .=
+ " --debug=d:t:A,$opt_vardir/log/mysqldump.trace";
+ }
my $cmdline_mysqlimport= "$exe_mysqlimport -uroot " .
"--port=$master->[0]->{'path_myport'} " .
"--socket=$master->[0]->{'path_mysock'} --password=";
@@ -2519,6 +2529,7 @@ sub run_mysqltest ($) {
$ENV{'MYSQL'}= $cmdline_mysql;
$ENV{'MYSQL_CHECK'}= $cmdline_mysqlcheck;
$ENV{'MYSQL_DUMP'}= $cmdline_mysqldump;
+ $ENV{'MYSQL_SLAP'}= $cmdline_mysqlslap;
$ENV{'MYSQL_IMPORT'}= $cmdline_mysqlimport;
$ENV{'MYSQL_SHOW'}= $cmdline_mysqlshow;
$ENV{'MYSQL_BINLOG'}= $cmdline_mysqlbinlog;
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index 2cb462831fa..1feb16703c4 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -243,6 +243,7 @@ EXTRA_MASTER_OPT=""
EXTRA_MYSQL_TEST_OPT=""
EXTRA_MYSQLCHECK_OPT=""
EXTRA_MYSQLDUMP_OPT=""
+EXTRA_MYSQLSLAP_OPT=""
EXTRA_MYSQLSHOW_OPT=""
EXTRA_MYSQLBINLOG_OPT=""
USE_RUNNING_SERVER=0
@@ -519,6 +520,8 @@ while test $# -gt 0; do
--debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysqlcheck.trace"
EXTRA_MYSQLDUMP_OPT="$EXTRA_MYSQLDUMP_OPT \
--debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysqldump.trace"
+ EXTRA_MYSQLSLAP_OPT="$EXTRA_MYSQLSLAP_OPT \
+ --debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysqlslap.trace"
EXTRA_MYSQLSHOW_OPT="$EXTRA_MYSQLSHOW_OPT \
--debug=d:t:A,$MYSQL_TEST_DIR/var/log/mysqlshow.trace"
EXTRA_MYSQLBINLOG_OPT="$EXTRA_MYSQLBINLOG_OPT \
@@ -629,6 +632,11 @@ if [ x$SOURCE_DIST = x1 ] ; then
else
MYSQL_DUMP="$BASEDIR/client/mysqldump"
fi
+ if [ -f "$BASEDIR/client/.libs/mysqlslap" ] ; then
+ MYSQL_SLAP="$BASEDIR/client/.libs/mysqlslap"
+ else
+ MYSQL_SLAP="$BASEDIR/client/mysqlslap"
+ fi
if [ -f "$BASEDIR/client/.libs/mysqlimport" ] ; then
MYSQL_IMPORT="$BASEDIR/client/.libs/mysqlimport"
else
@@ -709,6 +717,7 @@ else
MYSQL_TEST="$CLIENT_BINDIR/mysqltest"
MYSQL_CHECK="$CLIENT_BINDIR/mysqlcheck"
MYSQL_DUMP="$CLIENT_BINDIR/mysqldump"
+ MYSQL_SLAP="$CLIENT_BINDIR/mysqlslap"
MYSQL_SHOW="$CLIENT_BINDIR/mysqlshow"
MYSQL_IMPORT="$CLIENT_BINDIR/mysqlimport"
MYSQL_BINLOG="$CLIENT_BINDIR/mysqlbinlog"
@@ -796,6 +805,7 @@ MYSQL_DUMP_DIR="$MYSQL_DUMP"
export MYSQL_DUMP_DIR
MYSQL_CHECK="$MYSQL_CHECK --no-defaults -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLCHECK_OPT"
MYSQL_DUMP="$MYSQL_DUMP --no-defaults -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLDUMP_OPT"
+MYSQL_SLAP="$MYSQL_SLAP -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLSLAP_OPT"
MYSQL_SHOW="$MYSQL_SHOW -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLSHOW_OPT"
MYSQL_BINLOG="$MYSQL_BINLOG --no-defaults --local-load=$MYSQL_TMP_DIR --character-sets-dir=$CHARSETSDIR $EXTRA_MYSQLBINLOG_OPT"
MYSQL_IMPORT="$MYSQL_IMPORT -uroot --socket=$MASTER_MYSOCK --password=$DBPASSWD $EXTRA_MYSQLDUMP_OPT"
@@ -803,6 +813,7 @@ MYSQL_FIX_SYSTEM_TABLES="$MYSQL_FIX_SYSTEM_TABLES --no-defaults --host=localhost
MYSQL="$MYSQL --no-defaults --host=localhost --port=$MASTER_MYPORT --socket=$MASTER_MYSOCK --user=root --password=$DBPASSWD"
export MYSQL MYSQL_CHECK MYSQL_DUMP MYSQL_SHOW MYSQL_BINLOG MYSQL_FIX_SYSTEM_TABLES MYSQL_IMPORT
export CLIENT_BINDIR MYSQL_CLIENT_TEST CHARSETSDIR MYSQL_MY_PRINT_DEFAULTS
+export MYSQL_SLAP
export NDB_TOOLS_DIR
export NDB_MGM
export NDB_BACKUP_DIR
diff --git a/mysql-test/r/mysqlslap.result b/mysql-test/r/mysqlslap.result
new file mode 100644
index 00000000000..08e64e25ef5
--- /dev/null
+++ b/mysql-test/r/mysqlslap.result
@@ -0,0 +1,68 @@
+/home/patg/mysql-build/mysql-5.1-slap/client/.libs/lt-mysqlslap Ver 0.1 Distrib 5.1.3-alpha, for suse-linux (i686)
+Copyright (C) 2005 MySQL AB
+This software comes with ABSOLUTELY NO WARRANTY. This is free software,
+and you are welcome to modify and redistribute it under the GPL license
+
+Run a query multiple times against the server
+
+Usage: /home/patg/mysql-build/mysql-5.1-slap/client/.libs/lt-mysqlslap [OPTIONS] [database [table [column]]]
+
+Default options are read from the following files in the given order:
+/etc/my.cnf ~/.my.cnf
+The following groups are read: mysqlslap client
+The following options may be given as the first argument:
+--print-defaults Print the program argument list and exit
+--no-defaults Don't read default options from any options file
+--defaults-file=# Only read default options from the given file #
+--defaults-extra-file=# Read this file after the global files are read
+ -a, --auto-generate-sql
+ Generate SQL where not supplied by file or command line.
+ -C, --compress Use compression in server/client protocol.
+ -l, --concurrency-load=#
+ Number of clients to simulate for data load.
+ -c, --concurrency=# Number of clients to simulate for query to run.
+ --create=name File or string to use for create.
+ -d, --data=name File or string with INSERT to use for populating
+ table(s).
+ -#, --debug[=name] Output debug log. Often this is 'd:t:o,filename'.
+ -F, --delimiter=name
+ Delimiter to use in SQL statements supplied in file or
+ command line.
+ -D, --drop-schema Drop schema if it exists prior to running, and after
+ running
+ -e, --engine=name Storage engine to use for creating the table.
+ -?, --help Display this help and exit.
+ -h, --host=name Connect to host.
+ -i, --iterations=# Number of iterations.
+ -x, --number-char-cols=#
+ Number of INT columns to create table with if specifying
+ --sql-generate-sql.
+ -y, --number-int-cols=#
+ Number of VARCHAR columns to create table with if
+ specifying --sql-generate-sql.
+ -n, --number-rows=# Number of rows to insert when loading data.
+ -p, --password[=name]
+ Password to use when connecting to server. If password is
+ not given it's asked from the tty.
+ -P, --port=# Port number to use for connection.
+ --protocol=name The protocol of connection (tcp,socket,pipe,memory).
+ -A, --skip-create-schema
+ Don't create a schema, use existing schema.
+ -L, --skip-data-load
+ Don't load any data, use existing data set.
+ -Q, --skip-query Don't run any queries.
+ -s, --silent Run program in silent mode - no output.
+ -q, --query=name Query to run or file containing query to run.
+ -S, --socket=name Socket file to use for connection.
+ --ssl Enable SSL for connection (automatically enabled with
+ other flags). Disable with --skip-ssl.
+ --ssl-key=name X509 key in PEM format (implies --ssl).
+ --ssl-cert=name X509 cert in PEM format (implies --ssl).
+ --ssl-ca=name CA file in PEM format (check OpenSSL docs, implies
+ --ssl).
+ --ssl-capath=name CA directory (check OpenSSL docs, implies --ssl).
+ --ssl-cipher=name SSL cipher to use (implies --ssl).
+ -u, --user=name User for login if not current user.
+ -v, --verbose More verbose output; You can use this multiple times to
+ get even more verbose output.
+ -V, --version Output version information and exit.
diff --git a/mysql-test/t/mysqlslap.test b/mysql-test/t/mysqlslap.test
new file mode 100644
index 00000000000..7df7f96f5ee
--- /dev/null
+++ b/mysql-test/t/mysqlslap.test
@@ -0,0 +1,9 @@
+# Can't run test of external client with embedded server
+--source include/not_embedded.inc
+
+--exec $MYSQL_SLAP --help
+--exec $MYSQL_SLAP --silent --drop-schema --concurrency=5 --concurrency-load=5 --iterations=20 --number-int-cols=2 --number-char-cols=3 --number-rows=12 --auto-generate-sql
+
+--exec $MYSQL_SLAP --silent --drop-schema --concurrency=5 --concurrency-load=5 --iterations=20 --number-rows=10 --query="select * from t1" --data="INSERT INTO t1 VALUES (1, 'This is a test')" --create="CREATE TABLE t1 (id int, name varchar(64))"
+
+--exec $MYSQL_SLAP --silent --drop-schema --concurrency=5 --concurrency-load=5 --iterations=20 --delimiter=";" --number-rows=10 --query="select * from t1;select * from t2" --data="INSERT INTO t1 VALUES (1, 'This is a test'); insert into t2 values ('test', 'test2')" --create="CREATE TABLE t1 (id int, name varchar(64)); create table t2(foo1 varchar(32), foo2 varchar(32))"