diff options
-rw-r--r-- | client/Makefile.am | 4 | ||||
-rw-r--r-- | client/client_priv.h | 2 | ||||
-rw-r--r-- | client/mysqlslap.c | 1162 | ||||
-rwxr-xr-x | mysql-test/mysql-test-run.pl | 15 | ||||
-rw-r--r-- | mysql-test/mysql-test-run.sh | 11 | ||||
-rw-r--r-- | mysql-test/r/mysqlslap.result | 68 | ||||
-rw-r--r-- | mysql-test/t/mysqlslap.test | 9 |
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(×truct, 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))" |