Loading client/mysqltest.c +265 −88 Original line number Diff line number Diff line Loading @@ -42,7 +42,7 @@ **********************************************************************/ #define MTEST_VERSION "2.5" #define MTEST_VERSION "2.6" #include <my_global.h> #include <mysql_embed.h> Loading Loading @@ -108,7 +108,8 @@ enum {OPT_MANAGER_USER=256,OPT_MANAGER_HOST,OPT_MANAGER_PASSWD, OPT_MANAGER_PORT,OPT_MANAGER_WAIT_TIMEOUT, OPT_SKIP_SAFEMALLOC, OPT_SSL_SSL, OPT_SSL_KEY, OPT_SSL_CERT, OPT_SSL_CA, OPT_SSL_CAPATH, OPT_SSL_CIPHER,OPT_PS_PROTOCOL}; OPT_SSL_CIPHER,OPT_PS_PROTOCOL,OPT_SP_PROTOCOL,OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL}; /* ************************************************************************ */ /* Loading Loading @@ -158,7 +159,11 @@ static char *db = 0, *pass=0; const char *user = 0, *host = 0, *unix_sock = 0, *opt_basedir="./"; static int port = 0; static my_bool opt_big_test= 0, opt_compress= 0, silent= 0, verbose = 0; static my_bool tty_password= 0, ps_protocol= 0, ps_protocol_enabled= 0; static my_bool tty_password= 0; static my_bool ps_protocol= 0, ps_protocol_enabled= 0; static my_bool sp_protocol= 0, sp_protocol_enabled= 0; static my_bool view_protocol= 0, view_protocol_enabled= 0; static my_bool cursor_protocol= 0, cursor_protocol_enabled= 0; static int parsing_disabled= 0; static uint start_lineno, *lineno; const char *manager_user="root",*manager_host=0; Loading Loading @@ -212,11 +217,14 @@ static int got_end_timer= FALSE; static void timer_output(void); static ulonglong timer_now(void); static my_regex_t ps_re; /* Holds precompiled re for valid PS statements */ static void ps_init_re(void); static int ps_match_re(char *); static char *ps_eprint(int); static void ps_free_reg(void); /* Precompiled re's */ static my_regex_t ps_re; /* the query can be run using PS protocol */ static my_regex_t sp_re; /* the query can be run as a SP */ static my_regex_t view_re; /* the query can be run as a view*/ static void init_re(void); static int match_re(my_regex_t *, char *); static void free_re(void); static const char *embedded_server_groups[]= { Loading @@ -240,6 +248,7 @@ struct connection { MYSQL mysql; char *name; MYSQL_STMT* stmt; }; typedef struct Loading Loading @@ -433,7 +442,6 @@ static VAR* var_init(VAR* v, const char *name, int name_len, const char *val, static void var_free(void* v); int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname); void dump_result_to_reject_file(const char *record_file, char *buf, int size); int close_connection(struct st_query*); Loading Loading @@ -539,6 +547,9 @@ static void close_cons() DBUG_ENTER("close_cons"); for (--next_con; next_con >= cons; --next_con) { if (next_con->stmt) mysql_stmt_close(next_con->stmt); next_con->stmt= 0; mysql_close(&next_con->mysql); my_free(next_con->name, MYF(MY_ALLOW_ZERO_PTR)); } Loading Loading @@ -593,8 +604,7 @@ static void free_used_memory() my_free(pass,MYF(MY_ALLOW_ZERO_PTR)); free_defaults(default_argv); mysql_server_end(); if (ps_protocol) ps_free_reg(); free_re(); DBUG_VOID_RETURN; } Loading Loading @@ -660,7 +670,7 @@ void init_parser() } int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname) static int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname) { MY_STAT stat_info; char *tmp, *res_ptr; Loading Loading @@ -2715,6 +2725,15 @@ static struct my_option my_long_options[] = {"ps-protocol", OPT_PS_PROTOCOL, "Use prepared statements protocol for communication", (gptr*) &ps_protocol, (gptr*) &ps_protocol, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"sp-protocol", OPT_SP_PROTOCOL, "Use stored procedures for select", (gptr*) &sp_protocol, (gptr*) &sp_protocol, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"cursor-protocol", OPT_CURSOR_PROTOCOL, "Use cursors for prepared statment", (gptr*) &cursor_protocol, (gptr*) &cursor_protocol, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"view-protocol", OPT_VIEW_PROTOCOL, "Use views for select", (gptr*) &view_protocol, (gptr*) &view_protocol, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"quiet", 's', "Suppress all normal output.", (gptr*) &silent, (gptr*) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"record", 'r', "Record output of test_file into result file.", Loading Loading @@ -2776,8 +2795,6 @@ void usage() #include <help_end.h> #include <help_end.h> static my_bool get_one_option(int optid, const struct my_option *opt __attribute__((unused)), Loading Loading @@ -3222,6 +3239,7 @@ static void append_table_headings(DYNAMIC_STRING* ds, static void append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql) { uint count; MYSQL_RES *warn_res; DBUG_ENTER("append_warnings"); if (!(count= mysql_warning_count(mysql))) Loading @@ -3237,12 +3255,10 @@ static void append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql) if (mysql_real_query(mysql, "SHOW WARNINGS", 13)) die("Error running query \"SHOW WARNINGS\": %s", mysql_error(mysql)); MYSQL_RES *warn_res= mysql_store_result(mysql); if (!warn_res) if (!(warn_res= mysql_store_result(mysql))) die("Warning count is %u but didn't get any warnings", count); dynstr_append_mem(ds, "Warnings:\n", 10); append_result(ds, warn_res); mysql_free_result(warn_res); Loading @@ -3258,6 +3274,7 @@ static void append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql) run_query_normal mysql - mysql handle command - currrent command pointer flags -flags indicating wheter to SEND and/or REAP query - query string to execute query_len - length query string to execute ds - output buffer wherte to store result form query Loading @@ -3279,7 +3296,7 @@ static void run_query_normal(MYSQL *mysql, struct st_query *command, if (flags & QUERY_SEND) { /* Send the query, using the undocumented function mysql_send_query Send the query */ if (mysql_send_query(mysql, query, query_len)) { Loading @@ -3295,7 +3312,7 @@ static void run_query_normal(MYSQL *mysql, struct st_query *command, do { /* When on first result set, call mysql_read_query_result to retrrieve When on first result set, call mysql_read_query_result to retrieve answer to the query sent earlier */ if ((counter==0) && mysql_read_query_result(mysql)) Loading Loading @@ -3526,17 +3543,19 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, { MYSQL_RES *res= NULL; /* Note that here 'res' is meta data result set */ MYSQL_STMT *stmt; DYNAMIC_STRING ds_prepare_warnings; DBUG_ENTER("run_query_stmt"); DBUG_PRINT("query", ("'%-.60s'", query)); /* We must allocate a new stmt for each query in this program because this may be a new connection. Well, it could be stored togeter with mysql pointer in cur_con struct Init a new stmt if it's not alreday one created for this connectoon */ if(!(stmt= cur_con->stmt)) { if (!(stmt= mysql_stmt_init(mysql))) die("unable to init stmt structure"); cur_con->stmt= stmt; } /* Prepare the query Loading @@ -3548,11 +3567,36 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, goto end; } /* Get the warnings from mysql_stmt_prepare and keep them in a separate string */ if (!disable_warnings) { init_dynamic_string(&ds_prepare_warnings, "", 1024, 1024); append_warnings(&ds_prepare_warnings, mysql); } /* No need to call mysql_stmt_bind_param() because we have no parameter markers. */ #ifdef BUG14013_FIXED /* Use cursor when retrieving result */ if (cursor_protocol_enabled) { unsigned long type= CURSOR_TYPE_READ_ONLY; if (mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type)) die("mysql_stmt_attr_set(STMT_ATTR_CURSOR_TYPE) failed': %d %s", mysql_stmt_errno(stmt), mysql_stmt_error(stmt)); } #endif /* Execute the query */ Loading @@ -3571,7 +3615,7 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, { my_bool one= 1; if (mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*) &one)) die("mysql_stmt_attr_set failed': %d %s", die("mysql_stmt_attr_set(STMT_ATTR_UPDATE_MAX_LENGTH) failed': %d %s", mysql_stmt_errno(stmt), mysql_stmt_error(stmt)); } Loading @@ -3589,14 +3633,14 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, /* If we got here the statement was both executed and read succeesfully */ handle_no_error(command); if (!disable_result_log) { /* Not all statements creates a result set. If there is one we can now create another normal result set that contains the meta data. This set can be handled almost like any other non prepared statement result set. */ if (!disable_result_log) { if ((res= mysql_stmt_result_metadata(stmt)) != NULL) { /* Take the column count from meta info */ Loading @@ -3614,29 +3658,44 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, mysql_free_result(res); /* Free normal result set with meta data */ } else { /* This is a query without resultset */ /* Add warnings from prepare to output */ if (!disable_warnings) dynstr_append(ds, ds_prepare_warnings.str); } if (!disable_warnings) append_warnings(ds, mysql); if (!disable_info) append_info(ds, (ulong)mysql_affected_rows(mysql), mysql_info(mysql)); } end: free_replace(); if (!disable_warnings) dynstr_free(&ds_prepare_warnings); /* We save the return code (mysql_stmt_errno(stmt)) from the last call sent to the server into the mysqltest builtin variable $mysql_errno. This variable then can be used from the test case itself. */ var_set_errno(mysql_stmt_errno(stmt)); mysql_stmt_close(stmt); DBUG_VOID_RETURN; } /* Run query flags control the phased/stages of query execution to be performed Loading @@ -3653,10 +3712,12 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, static void run_query(MYSQL *mysql, struct st_query *command, int flags) { DYNAMIC_STRING *ds; DYNAMIC_STRING ds_tmp; DYNAMIC_STRING ds_result; DYNAMIC_STRING eval_query; char *query; int query_len; my_bool view_created= 0, sp_created= 0; my_bool complete_query= ((flags & QUERY_SEND) && (flags & QUERY_REAP)); /* Evaluate query if this is an eval command Loading @@ -3682,13 +3743,15 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) */ if (command->record_file[0]) { init_dynamic_string(&ds_tmp, "", 16384, 65536); ds= &ds_tmp; init_dynamic_string(&ds_result, "", 16384, 65536); ds= &ds_result; } else ds= &ds_res; /* Store the query into the output buffer */ /* Log the query into the output buffer */ if (!disable_query_log && (flags & QUERY_SEND)) { replace_dynstr_append_mem(ds, query, query_len); Loading @@ -3696,22 +3759,107 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) dynstr_append_mem(ds, "\n", 1); } if (view_protocol_enabled && complete_query && match_re(&view_re, query)) { /* Create the query as a view. Use replace since view can exist from a failed mysqltest run */ DYNAMIC_STRING query_str; init_dynamic_string(&query_str, "CREATE OR REPLACE VIEW mysqltest_tmp_v AS ", query_len+64, 256); dynstr_append_mem(&query_str, query, query_len); if (mysql_query(mysql, query_str.str)) { /* Failed to create the view, this is not fatal just run the query the normal way */ DBUG_PRINT("view_create_error", ("Failed to create view '%s': %d: %s", query_str.str, mysql_errno(mysql), mysql_error(mysql))); } else { /* Yes, it was possible to create this query as a view */ view_created= 1; query= (char*)"SELECT * FROM mysqltest_tmp_v"; query_len = strlen(query); } dynstr_free(&query_str); } if (sp_protocol_enabled && complete_query && match_re(&sp_re, query)) { /* Create the query as a stored procedure Drop first since sp can exist from a failed mysqltest run */ DYNAMIC_STRING query_str; init_dynamic_string(&query_str, "DROP PROCEDURE IF EXISTS mysqltest_tmp_sp;\n", query_len+64, 256); mysql_query(mysql, query_str.str); dynstr_set(&query_str, "CREATE PROCEDURE mysqltest_tmp_sp()\n"); dynstr_append_mem(&query_str, query, query_len); if (mysql_query(mysql, query_str.str)) { /* Failed to create the stored procedure for this query, this is not fatal just run the query the normal way */ DBUG_PRINT("sp_create_error", ("Failed to create sp '%s': %d: %s", query_str.str, mysql_errno(mysql), mysql_error(mysql))); } else { sp_created= 1; query= (char*)"CALL mysqltest_tmp_sp()"; query_len = strlen(query); } dynstr_free(&query_str); } /* Find out how to run this query We don't have a mysql_stmt_send_execute() so it must be a complete SEND+REAP to use prepared statement Always run with normal C API if it's not a complete SEND + REAP If it is a '?' in the query it may be a SQL level prepared statement already and we can't do it twice */ if (ps_protocol_enabled && (flags & QUERY_SEND) && (flags & QUERY_REAP) && ps_match_re(query)) complete_query && match_re(&ps_re, query)) run_query_stmt(mysql, command, query, query_len, ds); else run_query_normal(mysql, command, flags, query, query_len, ds); if (sp_created) { if (mysql_query(mysql, "DROP PROCEDURE mysqltest_tmp_sp ")) die("Failed to drop sp: %d: %s", mysql_errno(mysql), mysql_error(mysql)); } if (view_created) { if (mysql_query(mysql, "DROP VIEW mysqltest_tmp_v ")) die("Failed to drop view: %d: %s", mysql_errno(mysql), mysql_error(mysql)); } if (record) { /* Recording in progress */ Loading @@ -3730,19 +3878,45 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) check_result(ds, command->record_file, command->require_file); } if (ds == &ds_tmp) dynstr_free(&ds_tmp); if (ds == &ds_result) dynstr_free(&ds_result); if (command->type == Q_EVAL) dynstr_free(&eval_query); } /****************************************************************************\ * Functions to match SQL statements that can be prepared * Functions to detect different SQL statements \****************************************************************************/ static void ps_init_re(void) static char *re_eprint(int err) { static char epbuf[100]; size_t len= my_regerror(REG_ITOA|err, (my_regex_t *)NULL, epbuf, sizeof(epbuf)); assert(len <= sizeof(epbuf)); return(epbuf); } static void init_re_comp(my_regex_t *re, const char* str) { int err= my_regcomp(re, str, (REG_EXTENDED | REG_ICASE | REG_NOSUB), &my_charset_latin1); if (err) { char erbuf[100]; int len= my_regerror(err, re, erbuf, sizeof(erbuf)); die("error %s, %d/%d `%s'\n", re_eprint(err), len, (int)sizeof(erbuf), erbuf); } } static void init_re(void) { /* Filter for queries that can be run using the MySQL Prepared Statements C API */ const char *ps_re_str = "^(" "[[:space:]]*REPLACE[[:space:]]|" Loading @@ -3757,50 +3931,48 @@ static void ps_init_re(void) "[[:space:]]*UPDATE[[:space:]]+MULTI[[:space:]]|" "[[:space:]]*INSERT[[:space:]]+SELECT[[:space:]])"; int err= my_regcomp(&ps_re, ps_re_str, (REG_EXTENDED | REG_ICASE | REG_NOSUB), &my_charset_latin1); if (err) { char erbuf[100]; int len= my_regerror(err, &ps_re, erbuf, sizeof(erbuf)); fprintf(stderr, "error %s, %d/%d `%s'\n", ps_eprint(err), len, (int)sizeof(erbuf), erbuf); exit(1); } /* Filter for queries that can be run using the Stored procedures */ const char *sp_re_str =ps_re_str; /* Filter for queries that can be run as views */ const char *view_re_str = "^(" "[[:space:]]*SELECT[[:space:]])"; init_re_comp(&ps_re, ps_re_str); init_re_comp(&sp_re, sp_re_str); init_re_comp(&view_re, view_re_str); } static int ps_match_re(char *stmt_str) static int match_re(my_regex_t *re, char *str) { int err= my_regexec(&ps_re, stmt_str, (size_t)0, NULL, 0); int err= my_regexec(re, str, (size_t)0, NULL, 0); if (err == 0) return 1; else if (err == REG_NOMATCH) return 0; else { char erbuf[100]; int len= my_regerror(err, &ps_re, erbuf, sizeof(erbuf)); fprintf(stderr, "error %s, %d/%d `%s'\n", ps_eprint(err), len, (int)sizeof(erbuf), erbuf); exit(1); } int len= my_regerror(err, re, erbuf, sizeof(erbuf)); die("error %s, %d/%d `%s'\n", re_eprint(err), len, (int)sizeof(erbuf), erbuf); } static char *ps_eprint(int err) { static char epbuf[100]; size_t len= my_regerror(REG_ITOA|err, (my_regex_t *)NULL, epbuf, sizeof(epbuf)); assert(len <= sizeof(epbuf)); return(epbuf); return 0; } static void ps_free_reg(void) static void free_re(void) { my_regfree(&ps_re); my_regfree(&sp_re); my_regfree(&view_re); } /****************************************************************************/ Loading Loading @@ -3930,8 +4102,7 @@ static void init_var_hash(MYSQL *mysql) v= var_init(0,"MAX_TABLES", 0, (sizeof(ulong) == 4) ? "31" : "62",0); my_hash_insert(&var_hash, (byte*) v); v= var_init(0,"SERVER_VERSION", 0, mysql_get_server_info(mysql), 0); my_hash_insert(&var_hash, (byte*) v); v= var_init(0,"DB", 2, db, 0); my_hash_insert(&var_hash, (byte*) v); v= var_init(0,"DB", 2, db, 0); my_hash_insert(&var_hash, (byte*) v); DBUG_VOID_RETURN; } Loading Loading @@ -3988,11 +4159,15 @@ int main(int argc, char **argv) if (manager_host) init_manager(); #endif if (ps_protocol) { init_re(); ps_protocol_enabled= ps_protocol; sp_protocol_enabled= sp_protocol; view_protocol_enabled= view_protocol; cursor_protocol_enabled= cursor_protocol; /* Cursor protcol implies ps protocol */ if (cursor_protocol_enabled) ps_protocol_enabled= 1; ps_init_re(); } if (!( mysql_init(&cur_con->mysql))) die("Failed in mysql_init()"); if (opt_compress) Loading Loading @@ -5282,3 +5457,5 @@ FILE *my_popen(const char *cmd, const char *mode __attribute__((unused))) } #endif /* __NETWARE__ or __WIN__*/ mysql-test/mysql-test-run.pl +25 −0 Original line number Diff line number Diff line Loading @@ -191,6 +191,9 @@ our $opt_ssl; our $opt_skip_ssl; our $opt_ssl_supported; our $opt_ps_protocol; our $opt_sp_protocol; our $opt_cursor_protocol; our $opt_view_protocol; our $opt_current_test; our $opt_ddd; Loading Loading @@ -490,6 +493,9 @@ sub command_line_setup () { # Control what engine/variation to run 'embedded-server' => \$opt_embedded_server, 'ps-protocol' => \$opt_ps_protocol, 'sp-protocol' => \$opt_sp_protocol, 'view-protocol' => \$opt_view_protocol, 'cursor-protocol' => \$opt_cursor_protocol, 'ssl|with-openssl' => \$opt_ssl, 'skip-ssl' => \$opt_skip_ssl, 'compress' => \$opt_compress, Loading Loading @@ -2554,6 +2560,21 @@ sub run_mysqltest ($) { mtr_add_arg($args, "--ps-protocol"); } if ( $opt_sp_protocol ) { mtr_add_arg($args, "--sp-protocol"); } if ( $opt_view_protocol ) { mtr_add_arg($args, "--view-protocol"); } if ( $opt_cursor_protocol ) { mtr_add_arg($args, "--cursor-protocol"); } if ( $opt_strace_client ) { $exe= "strace"; # FIXME there are ktrace, .... Loading Loading @@ -2685,6 +2706,10 @@ Options to control what engine/variation to run embedded-server Use the embedded server, i.e. no mysqld daemons ps-protocol Use the binary protocol between client and server cursor-protocol Use the cursor protocol between client and server (implies --ps-protocol) view-protocol Create a view to execute all non updating queries sp-protocol Create a stored procedure to execute all queries compress Use the compressed protocol between client and server ssl Use ssl protocol between client and server skip-ssl Dont start sterver with support for ssl connections Loading Loading
client/mysqltest.c +265 −88 Original line number Diff line number Diff line Loading @@ -42,7 +42,7 @@ **********************************************************************/ #define MTEST_VERSION "2.5" #define MTEST_VERSION "2.6" #include <my_global.h> #include <mysql_embed.h> Loading Loading @@ -108,7 +108,8 @@ enum {OPT_MANAGER_USER=256,OPT_MANAGER_HOST,OPT_MANAGER_PASSWD, OPT_MANAGER_PORT,OPT_MANAGER_WAIT_TIMEOUT, OPT_SKIP_SAFEMALLOC, OPT_SSL_SSL, OPT_SSL_KEY, OPT_SSL_CERT, OPT_SSL_CA, OPT_SSL_CAPATH, OPT_SSL_CIPHER,OPT_PS_PROTOCOL}; OPT_SSL_CIPHER,OPT_PS_PROTOCOL,OPT_SP_PROTOCOL,OPT_CURSOR_PROTOCOL, OPT_VIEW_PROTOCOL}; /* ************************************************************************ */ /* Loading Loading @@ -158,7 +159,11 @@ static char *db = 0, *pass=0; const char *user = 0, *host = 0, *unix_sock = 0, *opt_basedir="./"; static int port = 0; static my_bool opt_big_test= 0, opt_compress= 0, silent= 0, verbose = 0; static my_bool tty_password= 0, ps_protocol= 0, ps_protocol_enabled= 0; static my_bool tty_password= 0; static my_bool ps_protocol= 0, ps_protocol_enabled= 0; static my_bool sp_protocol= 0, sp_protocol_enabled= 0; static my_bool view_protocol= 0, view_protocol_enabled= 0; static my_bool cursor_protocol= 0, cursor_protocol_enabled= 0; static int parsing_disabled= 0; static uint start_lineno, *lineno; const char *manager_user="root",*manager_host=0; Loading Loading @@ -212,11 +217,14 @@ static int got_end_timer= FALSE; static void timer_output(void); static ulonglong timer_now(void); static my_regex_t ps_re; /* Holds precompiled re for valid PS statements */ static void ps_init_re(void); static int ps_match_re(char *); static char *ps_eprint(int); static void ps_free_reg(void); /* Precompiled re's */ static my_regex_t ps_re; /* the query can be run using PS protocol */ static my_regex_t sp_re; /* the query can be run as a SP */ static my_regex_t view_re; /* the query can be run as a view*/ static void init_re(void); static int match_re(my_regex_t *, char *); static void free_re(void); static const char *embedded_server_groups[]= { Loading @@ -240,6 +248,7 @@ struct connection { MYSQL mysql; char *name; MYSQL_STMT* stmt; }; typedef struct Loading Loading @@ -433,7 +442,6 @@ static VAR* var_init(VAR* v, const char *name, int name_len, const char *val, static void var_free(void* v); int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname); void dump_result_to_reject_file(const char *record_file, char *buf, int size); int close_connection(struct st_query*); Loading Loading @@ -539,6 +547,9 @@ static void close_cons() DBUG_ENTER("close_cons"); for (--next_con; next_con >= cons; --next_con) { if (next_con->stmt) mysql_stmt_close(next_con->stmt); next_con->stmt= 0; mysql_close(&next_con->mysql); my_free(next_con->name, MYF(MY_ALLOW_ZERO_PTR)); } Loading Loading @@ -593,8 +604,7 @@ static void free_used_memory() my_free(pass,MYF(MY_ALLOW_ZERO_PTR)); free_defaults(default_argv); mysql_server_end(); if (ps_protocol) ps_free_reg(); free_re(); DBUG_VOID_RETURN; } Loading Loading @@ -660,7 +670,7 @@ void init_parser() } int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname) static int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname) { MY_STAT stat_info; char *tmp, *res_ptr; Loading Loading @@ -2715,6 +2725,15 @@ static struct my_option my_long_options[] = {"ps-protocol", OPT_PS_PROTOCOL, "Use prepared statements protocol for communication", (gptr*) &ps_protocol, (gptr*) &ps_protocol, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"sp-protocol", OPT_SP_PROTOCOL, "Use stored procedures for select", (gptr*) &sp_protocol, (gptr*) &sp_protocol, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"cursor-protocol", OPT_CURSOR_PROTOCOL, "Use cursors for prepared statment", (gptr*) &cursor_protocol, (gptr*) &cursor_protocol, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"view-protocol", OPT_VIEW_PROTOCOL, "Use views for select", (gptr*) &view_protocol, (gptr*) &view_protocol, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"quiet", 's', "Suppress all normal output.", (gptr*) &silent, (gptr*) &silent, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0}, {"record", 'r', "Record output of test_file into result file.", Loading Loading @@ -2776,8 +2795,6 @@ void usage() #include <help_end.h> #include <help_end.h> static my_bool get_one_option(int optid, const struct my_option *opt __attribute__((unused)), Loading Loading @@ -3222,6 +3239,7 @@ static void append_table_headings(DYNAMIC_STRING* ds, static void append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql) { uint count; MYSQL_RES *warn_res; DBUG_ENTER("append_warnings"); if (!(count= mysql_warning_count(mysql))) Loading @@ -3237,12 +3255,10 @@ static void append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql) if (mysql_real_query(mysql, "SHOW WARNINGS", 13)) die("Error running query \"SHOW WARNINGS\": %s", mysql_error(mysql)); MYSQL_RES *warn_res= mysql_store_result(mysql); if (!warn_res) if (!(warn_res= mysql_store_result(mysql))) die("Warning count is %u but didn't get any warnings", count); dynstr_append_mem(ds, "Warnings:\n", 10); append_result(ds, warn_res); mysql_free_result(warn_res); Loading @@ -3258,6 +3274,7 @@ static void append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql) run_query_normal mysql - mysql handle command - currrent command pointer flags -flags indicating wheter to SEND and/or REAP query - query string to execute query_len - length query string to execute ds - output buffer wherte to store result form query Loading @@ -3279,7 +3296,7 @@ static void run_query_normal(MYSQL *mysql, struct st_query *command, if (flags & QUERY_SEND) { /* Send the query, using the undocumented function mysql_send_query Send the query */ if (mysql_send_query(mysql, query, query_len)) { Loading @@ -3295,7 +3312,7 @@ static void run_query_normal(MYSQL *mysql, struct st_query *command, do { /* When on first result set, call mysql_read_query_result to retrrieve When on first result set, call mysql_read_query_result to retrieve answer to the query sent earlier */ if ((counter==0) && mysql_read_query_result(mysql)) Loading Loading @@ -3526,17 +3543,19 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, { MYSQL_RES *res= NULL; /* Note that here 'res' is meta data result set */ MYSQL_STMT *stmt; DYNAMIC_STRING ds_prepare_warnings; DBUG_ENTER("run_query_stmt"); DBUG_PRINT("query", ("'%-.60s'", query)); /* We must allocate a new stmt for each query in this program because this may be a new connection. Well, it could be stored togeter with mysql pointer in cur_con struct Init a new stmt if it's not alreday one created for this connectoon */ if(!(stmt= cur_con->stmt)) { if (!(stmt= mysql_stmt_init(mysql))) die("unable to init stmt structure"); cur_con->stmt= stmt; } /* Prepare the query Loading @@ -3548,11 +3567,36 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, goto end; } /* Get the warnings from mysql_stmt_prepare and keep them in a separate string */ if (!disable_warnings) { init_dynamic_string(&ds_prepare_warnings, "", 1024, 1024); append_warnings(&ds_prepare_warnings, mysql); } /* No need to call mysql_stmt_bind_param() because we have no parameter markers. */ #ifdef BUG14013_FIXED /* Use cursor when retrieving result */ if (cursor_protocol_enabled) { unsigned long type= CURSOR_TYPE_READ_ONLY; if (mysql_stmt_attr_set(stmt, STMT_ATTR_CURSOR_TYPE, (void*) &type)) die("mysql_stmt_attr_set(STMT_ATTR_CURSOR_TYPE) failed': %d %s", mysql_stmt_errno(stmt), mysql_stmt_error(stmt)); } #endif /* Execute the query */ Loading @@ -3571,7 +3615,7 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, { my_bool one= 1; if (mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*) &one)) die("mysql_stmt_attr_set failed': %d %s", die("mysql_stmt_attr_set(STMT_ATTR_UPDATE_MAX_LENGTH) failed': %d %s", mysql_stmt_errno(stmt), mysql_stmt_error(stmt)); } Loading @@ -3589,14 +3633,14 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, /* If we got here the statement was both executed and read succeesfully */ handle_no_error(command); if (!disable_result_log) { /* Not all statements creates a result set. If there is one we can now create another normal result set that contains the meta data. This set can be handled almost like any other non prepared statement result set. */ if (!disable_result_log) { if ((res= mysql_stmt_result_metadata(stmt)) != NULL) { /* Take the column count from meta info */ Loading @@ -3614,29 +3658,44 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, mysql_free_result(res); /* Free normal result set with meta data */ } else { /* This is a query without resultset */ /* Add warnings from prepare to output */ if (!disable_warnings) dynstr_append(ds, ds_prepare_warnings.str); } if (!disable_warnings) append_warnings(ds, mysql); if (!disable_info) append_info(ds, (ulong)mysql_affected_rows(mysql), mysql_info(mysql)); } end: free_replace(); if (!disable_warnings) dynstr_free(&ds_prepare_warnings); /* We save the return code (mysql_stmt_errno(stmt)) from the last call sent to the server into the mysqltest builtin variable $mysql_errno. This variable then can be used from the test case itself. */ var_set_errno(mysql_stmt_errno(stmt)); mysql_stmt_close(stmt); DBUG_VOID_RETURN; } /* Run query flags control the phased/stages of query execution to be performed Loading @@ -3653,10 +3712,12 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, static void run_query(MYSQL *mysql, struct st_query *command, int flags) { DYNAMIC_STRING *ds; DYNAMIC_STRING ds_tmp; DYNAMIC_STRING ds_result; DYNAMIC_STRING eval_query; char *query; int query_len; my_bool view_created= 0, sp_created= 0; my_bool complete_query= ((flags & QUERY_SEND) && (flags & QUERY_REAP)); /* Evaluate query if this is an eval command Loading @@ -3682,13 +3743,15 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) */ if (command->record_file[0]) { init_dynamic_string(&ds_tmp, "", 16384, 65536); ds= &ds_tmp; init_dynamic_string(&ds_result, "", 16384, 65536); ds= &ds_result; } else ds= &ds_res; /* Store the query into the output buffer */ /* Log the query into the output buffer */ if (!disable_query_log && (flags & QUERY_SEND)) { replace_dynstr_append_mem(ds, query, query_len); Loading @@ -3696,22 +3759,107 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) dynstr_append_mem(ds, "\n", 1); } if (view_protocol_enabled && complete_query && match_re(&view_re, query)) { /* Create the query as a view. Use replace since view can exist from a failed mysqltest run */ DYNAMIC_STRING query_str; init_dynamic_string(&query_str, "CREATE OR REPLACE VIEW mysqltest_tmp_v AS ", query_len+64, 256); dynstr_append_mem(&query_str, query, query_len); if (mysql_query(mysql, query_str.str)) { /* Failed to create the view, this is not fatal just run the query the normal way */ DBUG_PRINT("view_create_error", ("Failed to create view '%s': %d: %s", query_str.str, mysql_errno(mysql), mysql_error(mysql))); } else { /* Yes, it was possible to create this query as a view */ view_created= 1; query= (char*)"SELECT * FROM mysqltest_tmp_v"; query_len = strlen(query); } dynstr_free(&query_str); } if (sp_protocol_enabled && complete_query && match_re(&sp_re, query)) { /* Create the query as a stored procedure Drop first since sp can exist from a failed mysqltest run */ DYNAMIC_STRING query_str; init_dynamic_string(&query_str, "DROP PROCEDURE IF EXISTS mysqltest_tmp_sp;\n", query_len+64, 256); mysql_query(mysql, query_str.str); dynstr_set(&query_str, "CREATE PROCEDURE mysqltest_tmp_sp()\n"); dynstr_append_mem(&query_str, query, query_len); if (mysql_query(mysql, query_str.str)) { /* Failed to create the stored procedure for this query, this is not fatal just run the query the normal way */ DBUG_PRINT("sp_create_error", ("Failed to create sp '%s': %d: %s", query_str.str, mysql_errno(mysql), mysql_error(mysql))); } else { sp_created= 1; query= (char*)"CALL mysqltest_tmp_sp()"; query_len = strlen(query); } dynstr_free(&query_str); } /* Find out how to run this query We don't have a mysql_stmt_send_execute() so it must be a complete SEND+REAP to use prepared statement Always run with normal C API if it's not a complete SEND + REAP If it is a '?' in the query it may be a SQL level prepared statement already and we can't do it twice */ if (ps_protocol_enabled && (flags & QUERY_SEND) && (flags & QUERY_REAP) && ps_match_re(query)) complete_query && match_re(&ps_re, query)) run_query_stmt(mysql, command, query, query_len, ds); else run_query_normal(mysql, command, flags, query, query_len, ds); if (sp_created) { if (mysql_query(mysql, "DROP PROCEDURE mysqltest_tmp_sp ")) die("Failed to drop sp: %d: %s", mysql_errno(mysql), mysql_error(mysql)); } if (view_created) { if (mysql_query(mysql, "DROP VIEW mysqltest_tmp_v ")) die("Failed to drop view: %d: %s", mysql_errno(mysql), mysql_error(mysql)); } if (record) { /* Recording in progress */ Loading @@ -3730,19 +3878,45 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) check_result(ds, command->record_file, command->require_file); } if (ds == &ds_tmp) dynstr_free(&ds_tmp); if (ds == &ds_result) dynstr_free(&ds_result); if (command->type == Q_EVAL) dynstr_free(&eval_query); } /****************************************************************************\ * Functions to match SQL statements that can be prepared * Functions to detect different SQL statements \****************************************************************************/ static void ps_init_re(void) static char *re_eprint(int err) { static char epbuf[100]; size_t len= my_regerror(REG_ITOA|err, (my_regex_t *)NULL, epbuf, sizeof(epbuf)); assert(len <= sizeof(epbuf)); return(epbuf); } static void init_re_comp(my_regex_t *re, const char* str) { int err= my_regcomp(re, str, (REG_EXTENDED | REG_ICASE | REG_NOSUB), &my_charset_latin1); if (err) { char erbuf[100]; int len= my_regerror(err, re, erbuf, sizeof(erbuf)); die("error %s, %d/%d `%s'\n", re_eprint(err), len, (int)sizeof(erbuf), erbuf); } } static void init_re(void) { /* Filter for queries that can be run using the MySQL Prepared Statements C API */ const char *ps_re_str = "^(" "[[:space:]]*REPLACE[[:space:]]|" Loading @@ -3757,50 +3931,48 @@ static void ps_init_re(void) "[[:space:]]*UPDATE[[:space:]]+MULTI[[:space:]]|" "[[:space:]]*INSERT[[:space:]]+SELECT[[:space:]])"; int err= my_regcomp(&ps_re, ps_re_str, (REG_EXTENDED | REG_ICASE | REG_NOSUB), &my_charset_latin1); if (err) { char erbuf[100]; int len= my_regerror(err, &ps_re, erbuf, sizeof(erbuf)); fprintf(stderr, "error %s, %d/%d `%s'\n", ps_eprint(err), len, (int)sizeof(erbuf), erbuf); exit(1); } /* Filter for queries that can be run using the Stored procedures */ const char *sp_re_str =ps_re_str; /* Filter for queries that can be run as views */ const char *view_re_str = "^(" "[[:space:]]*SELECT[[:space:]])"; init_re_comp(&ps_re, ps_re_str); init_re_comp(&sp_re, sp_re_str); init_re_comp(&view_re, view_re_str); } static int ps_match_re(char *stmt_str) static int match_re(my_regex_t *re, char *str) { int err= my_regexec(&ps_re, stmt_str, (size_t)0, NULL, 0); int err= my_regexec(re, str, (size_t)0, NULL, 0); if (err == 0) return 1; else if (err == REG_NOMATCH) return 0; else { char erbuf[100]; int len= my_regerror(err, &ps_re, erbuf, sizeof(erbuf)); fprintf(stderr, "error %s, %d/%d `%s'\n", ps_eprint(err), len, (int)sizeof(erbuf), erbuf); exit(1); } int len= my_regerror(err, re, erbuf, sizeof(erbuf)); die("error %s, %d/%d `%s'\n", re_eprint(err), len, (int)sizeof(erbuf), erbuf); } static char *ps_eprint(int err) { static char epbuf[100]; size_t len= my_regerror(REG_ITOA|err, (my_regex_t *)NULL, epbuf, sizeof(epbuf)); assert(len <= sizeof(epbuf)); return(epbuf); return 0; } static void ps_free_reg(void) static void free_re(void) { my_regfree(&ps_re); my_regfree(&sp_re); my_regfree(&view_re); } /****************************************************************************/ Loading Loading @@ -3930,8 +4102,7 @@ static void init_var_hash(MYSQL *mysql) v= var_init(0,"MAX_TABLES", 0, (sizeof(ulong) == 4) ? "31" : "62",0); my_hash_insert(&var_hash, (byte*) v); v= var_init(0,"SERVER_VERSION", 0, mysql_get_server_info(mysql), 0); my_hash_insert(&var_hash, (byte*) v); v= var_init(0,"DB", 2, db, 0); my_hash_insert(&var_hash, (byte*) v); v= var_init(0,"DB", 2, db, 0); my_hash_insert(&var_hash, (byte*) v); DBUG_VOID_RETURN; } Loading Loading @@ -3988,11 +4159,15 @@ int main(int argc, char **argv) if (manager_host) init_manager(); #endif if (ps_protocol) { init_re(); ps_protocol_enabled= ps_protocol; sp_protocol_enabled= sp_protocol; view_protocol_enabled= view_protocol; cursor_protocol_enabled= cursor_protocol; /* Cursor protcol implies ps protocol */ if (cursor_protocol_enabled) ps_protocol_enabled= 1; ps_init_re(); } if (!( mysql_init(&cur_con->mysql))) die("Failed in mysql_init()"); if (opt_compress) Loading Loading @@ -5282,3 +5457,5 @@ FILE *my_popen(const char *cmd, const char *mode __attribute__((unused))) } #endif /* __NETWARE__ or __WIN__*/
mysql-test/mysql-test-run.pl +25 −0 Original line number Diff line number Diff line Loading @@ -191,6 +191,9 @@ our $opt_ssl; our $opt_skip_ssl; our $opt_ssl_supported; our $opt_ps_protocol; our $opt_sp_protocol; our $opt_cursor_protocol; our $opt_view_protocol; our $opt_current_test; our $opt_ddd; Loading Loading @@ -490,6 +493,9 @@ sub command_line_setup () { # Control what engine/variation to run 'embedded-server' => \$opt_embedded_server, 'ps-protocol' => \$opt_ps_protocol, 'sp-protocol' => \$opt_sp_protocol, 'view-protocol' => \$opt_view_protocol, 'cursor-protocol' => \$opt_cursor_protocol, 'ssl|with-openssl' => \$opt_ssl, 'skip-ssl' => \$opt_skip_ssl, 'compress' => \$opt_compress, Loading Loading @@ -2554,6 +2560,21 @@ sub run_mysqltest ($) { mtr_add_arg($args, "--ps-protocol"); } if ( $opt_sp_protocol ) { mtr_add_arg($args, "--sp-protocol"); } if ( $opt_view_protocol ) { mtr_add_arg($args, "--view-protocol"); } if ( $opt_cursor_protocol ) { mtr_add_arg($args, "--cursor-protocol"); } if ( $opt_strace_client ) { $exe= "strace"; # FIXME there are ktrace, .... Loading Loading @@ -2685,6 +2706,10 @@ Options to control what engine/variation to run embedded-server Use the embedded server, i.e. no mysqld daemons ps-protocol Use the binary protocol between client and server cursor-protocol Use the cursor protocol between client and server (implies --ps-protocol) view-protocol Create a view to execute all non updating queries sp-protocol Create a stored procedure to execute all queries compress Use the compressed protocol between client and server ssl Use ssl protocol between client and server skip-ssl Dont start sterver with support for ssl connections Loading