From e5eb7cbf2958663dda1b72e1c0d98e66d25d218c Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Mon, 31 Oct 2005 12:25:08 +0100 Subject: [PATCH 01/19] WL#2930 Adding view and cursor 'protocols' to mysqltest - Cleanup of mysqltest.c before extending it --- client/mysqltest.c | 1531 +++++++++++++-------------- mysql-test/include/master-slave.inc | 6 +- mysql-test/include/ps_query.inc | 1 - mysql-test/r/mysqltest.result | 3 + mysql-test/r/ps_2myisam.result | 2 + mysql-test/r/ps_3innodb.result | 2 + mysql-test/r/ps_4heap.result | 2 + mysql-test/r/ps_5merge.result | 4 + mysql-test/r/ps_6bdb.result | 2 + mysql-test/r/ps_7ndb.result | 2 + mysql-test/t/alias.test | 2 - mysql-test/t/group_by.test | 4 - mysql-test/t/mysqltest.test | 9 + mysql-test/t/union.test | 21 - 14 files changed, 761 insertions(+), 830 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 6653d24e575..308bf6f9b79 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -248,8 +248,6 @@ typedef struct int read_lines,current_line; } PARSER; -MYSQL_RES *last_result=0; - PARSER parser; MASTER_POS master_pos; /* if set, all results are concated and compared against this file */ @@ -437,7 +435,7 @@ 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 reject_dump(const char *record_file, char *buf, int size); +void dump_result_to_reject_file(const char *record_file, char *buf, int size); int close_connection(struct st_query*); static void set_charset(struct st_query*); @@ -464,9 +462,8 @@ void free_replace(); static int insert_pointer_name(reg1 POINTER_ARRAY *pa,my_string name); void free_pointer_array(POINTER_ARRAY *pa); static int initialize_replace_buffer(void); -static void free_replace_buffer(void); static void do_eval(DYNAMIC_STRING *query_eval, const char *query); -void str_to_file(const char *fname, char *str, int size); +static void str_to_file(const char *fname, char *str, int size); int do_server_op(struct st_query *q,const char *op); struct st_replace *glob_replace; @@ -491,10 +488,10 @@ my_bool mysql_rpl_probe(MYSQL *mysql __attribute__((unused))) { return 1; } static void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val, int len); static void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val); -static int handle_error(const char *query, struct st_query *q, - unsigned int err_errno, const char *err_error, - const char *err_sqlstate, DYNAMIC_STRING *ds); -static int handle_no_error(struct st_query *q); +static void handle_error(const char *query, struct st_query *q, + unsigned int err_errno, const char *err_error, + const char *err_sqlstate, DYNAMIC_STRING *ds); +static void handle_no_error(struct st_query *q); static void do_eval(DYNAMIC_STRING* query_eval, const char *query) { @@ -541,8 +538,6 @@ static void do_eval(DYNAMIC_STRING* query_eval, const char *query) static void close_cons() { DBUG_ENTER("close_cons"); - if (last_result) - mysql_free_result(last_result); for (--next_con; next_con >= cons; --next_con) { mysql_close(&next_con->mysql); @@ -734,7 +729,21 @@ err: DBUG_RETURN(res); } -static int check_result(DYNAMIC_STRING* ds, const char *fname, +/* + Check the content of ds against content of file fname + + SYNOPSIS + check_result + ds - content to be checked + fname - name of file to check against + require_option - if set and check fails, the test will be aborted with the special + exit code "not supported test" + + RETURN VALUES + error - the function will not return + +*/ +static void check_result(DYNAMIC_STRING* ds, const char *fname, my_bool require_option) { int res= dyn_string_cmp(ds, fname); @@ -746,17 +755,18 @@ static int check_result(DYNAMIC_STRING* ds, const char *fname, case RESULT_OK: break; /* ok */ case RESULT_LENGTH_MISMATCH: - verbose_msg("Result length mismatch"); + dump_result_to_reject_file(fname, ds->str, ds->length); + die("Result length mismatch"); break; case RESULT_CONTENT_MISMATCH: - verbose_msg("Result content mismatch"); + dump_result_to_reject_file(fname, ds->str, ds->length); + die("Result content mismatch"); break; default: /* impossible */ die("Unknown error code from dyn_string_cmp()"); } - if (res != RESULT_OK) - reject_dump(fname, ds->str, ds->length); - DBUG_RETURN(res); + + DBUG_VOID_RETURN; } @@ -1043,7 +1053,6 @@ static void do_exec(struct st_query *query) { int error; DYNAMIC_STRING *ds= NULL; - DYNAMIC_STRING ds_tmp; char buf[1024]; FILE *res_file; char *cmd= query->first_argument; @@ -1070,14 +1079,7 @@ static void do_exec(struct st_query *query) } else { - if (query->record_file[0]) - { - init_dynamic_string(&ds_tmp, "", 16384, 65536); - ds= &ds_tmp; - } - else - ds= &ds_res; - + ds= &ds_res; while (fgets(buf, sizeof(buf), res_file)) replace_dynstr_append(ds, buf); } @@ -1118,25 +1120,7 @@ static void do_exec(struct st_query *query) cmd, query->expected_errno[0].code.errnum); } - if (!disable_result_log) - { - if (glob_replace) - free_replace(); - - if (record) - { - if (!query->record_file[0] && !result_file) - die("Missing result file"); - if (!result_file) - str_to_file(query->record_file, ds->str, ds->length); - } - else if (query->record_file[0]) - { - error= check_result(ds, query->record_file, query->require_file); - } - if (ds == &ds_tmp) - dynstr_free(&ds_tmp); - } + free_replace(); } @@ -1354,25 +1338,16 @@ int do_echo(struct st_query *q) { char *p= q->first_argument; DYNAMIC_STRING *ds; - DYNAMIC_STRING ds_tmp; VAR v; var_init(&v,0,0,0,0); - if (q->record_file[0]) - { - init_dynamic_string(&ds_tmp, "", 256, 512); - ds= &ds_tmp; - } - else - ds= &ds_res; + ds= &ds_res; eval_expr(&v, p, 0); /* NULL terminated */ if (v.str_val_len) dynstr_append_mem(ds, v.str_val, v.str_val_len); dynstr_append_mem(ds, "\n", 1); var_free(&v); - if (ds == &ds_tmp) - dynstr_free(&ds_tmp); q->last_argument= q->end; return 0; } @@ -1401,7 +1376,7 @@ wait_for_position: die("failed in %s: %d: %s", query_buf, mysql_errno(mysql), mysql_error(mysql)); - if (!(last_result= res= mysql_store_result(mysql))) + if (!(res= mysql_store_result(mysql))) die("mysql_store_result() returned NULL for '%s'", query_buf); if (!(row= mysql_fetch_row(res))) die("empty result in %s", query_buf); @@ -1418,7 +1393,6 @@ wait_for_position: goto wait_for_position; } mysql_free_result(res); - last_result=0; if (rpl_parse) mysql_enable_rpl_parse(mysql); @@ -1457,13 +1431,13 @@ int do_save_master_pos() die("failed in show master status: %d: %s", mysql_errno(mysql), mysql_error(mysql)); - if (!(last_result =res = mysql_store_result(mysql))) + if (!(res = mysql_store_result(mysql))) die("mysql_store_result() retuned NULL for '%s'", query); if (!(row = mysql_fetch_row(res))) die("empty result in show master status"); strnmov(master_pos.file, row[0], sizeof(master_pos.file)-1); master_pos.pos = strtoul(row[1], (char**) 0, 10); - mysql_free_result(res); last_result=0; + mysql_free_result(res); if (rpl_parse) mysql_enable_rpl_parse(mysql); @@ -1832,7 +1806,7 @@ void free_replace() { my_free((char*) glob_replace,MYF(0)); glob_replace=0; - free_replace_buffer(); + my_free(out_buff,MYF(MY_WME)); } DBUG_VOID_RETURN; } @@ -2029,21 +2003,11 @@ int connect_n_handle_errors(struct st_query *q, MYSQL* con, const char* host, const char* db, int port, const char* sock, int* create_conn) { - DYNAMIC_STRING ds_tmp, *ds; + DYNAMIC_STRING *ds; my_bool reconnect= 1; int error= 0; - /* - Altough we ignore --require or --result before connect() command we still - need to handle record_file because of "@result_file sql-command" syntax. - */ - if (q->record_file[0]) - { - init_dynamic_string(&ds_tmp, "", 16384, 65536); - ds= &ds_tmp; - } - else - ds= &ds_res; + ds= &ds_res; if (!disable_query_log) { @@ -2076,13 +2040,15 @@ int connect_n_handle_errors(struct st_query *q, MYSQL* con, const char* host, if (!mysql_real_connect(con, host, user, pass, db, port, sock ? sock: 0, CLIENT_MULTI_STATEMENTS)) { - error= handle_error("connect", q, mysql_errno(con), mysql_error(con), - mysql_sqlstate(con), ds); + handle_error("connect", q, mysql_errno(con), mysql_error(con), + mysql_sqlstate(con), ds); *create_conn= 0; goto err; } - else if (handle_no_error(q)) + else { + handle_no_error(q); + /* Fail if there was no error but we expected it. We also don't want to have connection in this case. @@ -2099,20 +2065,8 @@ int connect_n_handle_errors(struct st_query *q, MYSQL* con, const char* host, */ mysql_options(con, MYSQL_OPT_RECONNECT, (char *)&reconnect); - if (record) - { - if (!q->record_file[0] && !result_file) - die("Missing result file"); - if (!result_file) - str_to_file(q->record_file, ds->str, ds->length); - } - else if (q->record_file[0]) - error|= check_result(ds, q->record_file, q->require_file); - err: free_replace(); - if (ds == &ds_tmp) - dynstr_free(&ds_tmp); return error; } @@ -2470,7 +2424,7 @@ int read_line(char *buf, int size) state= R_Q; } else - state= R_NORMAL; +state= R_NORMAL; break; case R_Q: @@ -2559,7 +2513,7 @@ static char read_query_buf[MAX_QUERY]; int read_query(struct st_query** q_ptr) { - char *p= read_query_buf, *p1; + char *p= read_query_buf; struct st_query* q; DBUG_ENTER("read_query"); @@ -2578,10 +2532,13 @@ int read_query(struct st_query** q_ptr) q->type= Q_UNKNOWN; q->query_buf= q->query= 0; + read_query_buf[0]= 0; if (read_line(read_query_buf, sizeof(read_query_buf))) { + check_eol_junk(read_query_buf); DBUG_RETURN(1); } + DBUG_PRINT("info", ("query: %s", read_query_buf)); if (*p == '#') { @@ -2606,15 +2563,6 @@ int read_query(struct st_query** q_ptr) { while (*p && my_isspace(charset_info, *p)) p++ ; - if (*p == '@') - { - p++; - p1 = q->record_file; - while (!my_isspace(charset_info, *p) && - p1 < q->record_file + sizeof(q->record_file) - 1) - *p1++ = *p++; - *p1 = 0; - } } end: @@ -2862,7 +2810,17 @@ char* safe_str_append(char *buf, const char *str, int size) return buf; } -void str_to_file(const char *fname, char *str, int size) + +/* + Write the content of str into file + + SYNOPSIS + str_to_file + fname - name of file to truncate/create and write to + str - content to write to file + size - size of content witten to file +*/ +static void str_to_file(const char *fname, char *str, int size) { int fd; char buff[FN_REFLEN]; @@ -2881,7 +2839,7 @@ void str_to_file(const char *fname, char *str, int size) my_close(fd, MYF(0)); } -void reject_dump(const char *record_file, char *buf, int size) +void dump_result_to_reject_file(const char *record_file, char *buf, int size) { char reject_file[FN_REFLEN]; str_to_file(fn_format(reject_file, record_file,"",".reject",2), buf, size); @@ -2921,7 +2879,7 @@ static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res) MYSQL_ROW row; uint num_fields= mysql_num_fields(res); MYSQL_FIELD *fields= !display_result_vertically ? 0 : mysql_fetch_fields(res); - unsigned long *lengths; + ulong *lengths; while ((row = mysql_fetch_row(res))) { uint i; @@ -2963,667 +2921,118 @@ static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res) /* -* flags control the phased/stages of query execution to be performed -* if QUERY_SEND bit is on, the query will be sent. If QUERY_REAP is on -* the result will be read - for regular query, both bits must be on + Append all results from ps execution to the dynamic string separated + with '\t'. Values may be converted with 'replace_column' */ -static int run_query_normal(MYSQL *mysql, struct st_query *q, int flags); -static int run_query_stmt (MYSQL *mysql, struct st_query *q, int flags); -static void run_query_stmt_handle_warnings(MYSQL *mysql, DYNAMIC_STRING *ds); -static void run_query_display_metadata(MYSQL_FIELD *field, uint num_fields, - DYNAMIC_STRING *ds); - -static int run_query(MYSQL *mysql, struct st_query *q, int flags) +static void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT* stmt, + MYSQL_FIELD* field, uint num_fields) { - - /* - Try to find out if we can run this statement using the prepared - statement protocol. - - We don't have a mysql_stmt_send_execute() so we only handle - 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 && disable_info && - (flags & QUERY_SEND) && (flags & QUERY_REAP) && ps_match_re(q->query)) - return run_query_stmt(mysql, q, flags); - return run_query_normal(mysql, q, flags); -} - - -static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags) -{ - MYSQL_RES* res= 0; - uint i; - int error= 0, err= 0, counter= 0; - DYNAMIC_STRING *ds; - DYNAMIC_STRING ds_tmp; - DYNAMIC_STRING eval_query; - char* query; - int query_len, got_error_on_send= 0; - DBUG_ENTER("run_query_normal"); - DBUG_PRINT("enter",("flags: %d", flags)); - - if (q->type != Q_EVAL) - { - query = q->query; - query_len = strlen(query); - } - else - { - init_dynamic_string(&eval_query, "", 16384, 65536); - do_eval(&eval_query, q->query); - query = eval_query.str; - query_len = eval_query.length; - } - DBUG_PRINT("enter", ("query: '%-.60s'", query)); - - if (q->record_file[0]) - { - init_dynamic_string(&ds_tmp, "", 16384, 65536); - ds = &ds_tmp; - } - else - ds= &ds_res; - - if (flags & QUERY_SEND) - { - got_error_on_send= mysql_send_query(mysql, query, query_len); - if (got_error_on_send && q->expected_errno[0].type == ERR_EMPTY) - die("unable to send query '%s' (mysql_errno=%d , errno=%d)", - query, mysql_errno(mysql), errno); - } - - do - { - if ((flags & QUERY_SEND) && !disable_query_log && !counter) - { - replace_dynstr_append_mem(ds,query, query_len); - dynstr_append_mem(ds, delimiter, delimiter_length); - dynstr_append_mem(ds, "\n", 1); - } - if (!(flags & QUERY_REAP)) - DBUG_RETURN(0); - - if (got_error_on_send || - (!counter && (*mysql->methods->read_query_result)(mysql)) || - (!(last_result= res= mysql_store_result(mysql)) && - mysql_field_count(mysql))) - { - if (handle_error(query, q, mysql_errno(mysql), mysql_error(mysql), - mysql_sqlstate(mysql), ds)) - error= 1; - goto end; - } - - if (!disable_result_log) - { - ulong affected_rows; /* Ok to be undef if 'disable_info' is set */ - LINT_INIT(affected_rows); - - if (res) - { - MYSQL_FIELD *field= mysql_fetch_fields(res); - uint num_fields= mysql_num_fields(res); - - if (display_metadata) - run_query_display_metadata(field, num_fields, ds); - - if (!display_result_vertically) - { - for (i = 0; i < num_fields; i++) - { - if (i) - dynstr_append_mem(ds, "\t", 1); - replace_dynstr_append(ds, field[i].name); - } - dynstr_append_mem(ds, "\n", 1); - } - append_result(ds, res); - } - - /* - Need to call mysql_affected_rows() before the new - query to find the warnings - */ - if (!disable_info) - affected_rows= (ulong)mysql_affected_rows(mysql); - - /* - Add all warnings to the result. We can't do this if we are in - the middle of processing results from multi-statement, because - this will break protocol. - */ - if (!disable_warnings && !mysql_more_results(mysql) && - mysql_warning_count(mysql)) - { - MYSQL_RES *warn_res=0; - uint count= mysql_warning_count(mysql); - if (!mysql_real_query(mysql, "SHOW WARNINGS", 13)) - warn_res= mysql_store_result(mysql); - if (!warn_res) - die("Warning count is %u but didn't get any warnings", count); - else - { - dynstr_append_mem(ds, "Warnings:\n", 10); - append_result(ds, warn_res); - mysql_free_result(warn_res); - } - } - if (!disable_info) - { - char buf[40]; - sprintf(buf,"affected rows: %lu\n", affected_rows); - dynstr_append(ds, buf); - if (mysql_info(mysql)) - { - dynstr_append(ds, "info: "); - dynstr_append(ds, mysql_info(mysql)); - dynstr_append_mem(ds, "\n", 1); - } - } - } - - if (record) - { - if (!q->record_file[0] && !result_file) - die("Missing result file"); - if (!result_file) - str_to_file(q->record_file, ds->str, ds->length); - } - else if (q->record_file[0]) - { - error= check_result(ds, q->record_file, q->require_file); - } - if (res) - mysql_free_result(res); - last_result= 0; - counter++; - } while (!(err= mysql_next_result(mysql))); - if (err > 0) - { - /* We got an error from mysql_next_result, maybe expected */ - if (handle_error(query, q, mysql_errno(mysql), mysql_error(mysql), - mysql_sqlstate(mysql), ds)) - error= 1; - goto end; - } - - /* If we come here the query is both executed and read successfully */ - if (handle_no_error(q)) - { - error= 1; - goto end; - } - -end: - free_replace(); - last_result=0; - if (ds == &ds_tmp) - dynstr_free(&ds_tmp); - if (q->type == Q_EVAL) - dynstr_free(&eval_query); - - /* - We save the return code (mysql_errno(mysql)) 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_errno(mysql)); - DBUG_RETURN(error); -} - - -/* - Handle errors which occurred after execution - - SYNOPSIS - handle_error() - query - query string - q - query context - err_errno - error number - err_error - error message - err_sqlstate - sql state - ds - dynamic string which is used for output buffer - - NOTE - If there is an unexpected error this function will abort mysqltest - immediately. - - RETURN VALUE - 0 - OK - 1 - Some other error was expected. -*/ - -static int handle_error(const char *query, struct st_query *q, - unsigned int err_errno, const char *err_error, - const char* err_sqlstate, DYNAMIC_STRING *ds) -{ - uint i; - - DBUG_ENTER("handle_error"); - - if (q->require_file) - abort_not_supported_test(); - - if (q->abort_on_error) - die("query '%s' failed: %d: %s", query, err_errno, err_error); - - for (i= 0 ; (uint) i < q->expected_errors ; i++) - { - if (((q->expected_errno[i].type == ERR_ERRNO) && - (q->expected_errno[i].code.errnum == err_errno)) || - ((q->expected_errno[i].type == ERR_SQLSTATE) && - (strcmp(q->expected_errno[i].code.sqlstate, err_sqlstate) == 0))) - { - if (q->expected_errors == 1) - { - /* Only log error if there is one possible error */ - dynstr_append_mem(ds, "ERROR ", 6); - replace_dynstr_append(ds, err_sqlstate); - dynstr_append_mem(ds, ": ", 2); - replace_dynstr_append(ds, err_error); - dynstr_append_mem(ds,"\n",1); - } - /* Don't log error if we may not get an error */ - else if (q->expected_errno[0].type == ERR_SQLSTATE || - (q->expected_errno[0].type == ERR_ERRNO && - q->expected_errno[0].code.errnum != 0)) - dynstr_append(ds,"Got one of the listed errors\n"); - /* OK */ - DBUG_RETURN(0); - } - } - - DBUG_PRINT("info",("i: %d expected_errors: %d", i, q->expected_errors)); - - dynstr_append_mem(ds, "ERROR ",6); - replace_dynstr_append(ds, err_sqlstate); - dynstr_append_mem(ds, ": ", 2); - replace_dynstr_append(ds, err_error); - dynstr_append_mem(ds, "\n", 1); - - if (i) - { - if (q->expected_errno[0].type == ERR_ERRNO) - die("query '%s' failed with wrong errno %d instead of %d...", - q->query, err_errno, q->expected_errno[0].code.errnum); - else - die("query '%s' failed with wrong sqlstate %s instead of %s...", - q->query, err_sqlstate, q->expected_errno[0].code.sqlstate); - DBUG_RETURN(1); - } - - /* - If we do not abort on error, failure to run the query does not fail the - whole test case. - */ - verbose_msg("query '%s' failed: %d: %s", q->query, err_errno, - err_error); - DBUG_RETURN(0); -} - - -/* - Handle absence of errors after execution - - SYNOPSIS - handle_no_error() - q - context of query - - RETURN VALUE - 0 - OK - 1 - Some error was expected from this query. -*/ - -static int handle_no_error(struct st_query *q) -{ - DBUG_ENTER("handle_no_error"); - - if (q->expected_errno[0].type == ERR_ERRNO && - q->expected_errno[0].code.errnum != 0) - { - /* Error code we wanted was != 0, i.e. not an expected success */ - die("query '%s' succeeded - should have failed with errno %d...", - q->query, q->expected_errno[0].code.errnum); - DBUG_RETURN(1); - } - else if (q->expected_errno[0].type == ERR_SQLSTATE && - strcmp(q->expected_errno[0].code.sqlstate,"00000") != 0) - { - /* SQLSTATE we wanted was != "00000", i.e. not an expected success */ - die("query '%s' succeeded - should have failed with sqlstate %s...", - q->query, q->expected_errno[0].code.sqlstate); - DBUG_RETURN(1); - } - - DBUG_RETURN(0); -} - -/****************************************************************************\ - * If --ps-protocol run ordinary statements using prepared statemnt C API -\****************************************************************************/ - -/* - We don't have a mysql_stmt_send_execute() so we only handle - complete SEND+REAP -*/ - -static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags) -{ - int error= 0; /* Function return code if "goto end;" */ - int err; /* Temporary storage of return code from calls */ - int query_len; + MYSQL_BIND *bind; + my_bool *is_null; + ulong *length; ulonglong num_rows; - char *query; - MYSQL_RES *res= NULL; /* Note that here 'res' is meta data result set */ - DYNAMIC_STRING *ds; - DYNAMIC_STRING ds_tmp; - DYNAMIC_STRING eval_query; - MYSQL_STMT *stmt; - DBUG_ENTER("run_query_stmt"); - /* - We must allocate a new stmt for each query in this program becasue this - may be a new connection. - */ - if (!(stmt= mysql_stmt_init(mysql))) - die("unable init stmt structure"); - - if (q->type != Q_EVAL) - { - query= q->query; - query_len= strlen(query); - } - else - { - init_dynamic_string(&eval_query, "", 16384, 65536); - do_eval(&eval_query, q->query); - query= eval_query.str; - query_len= eval_query.length; - } - DBUG_PRINT("query", ("'%-.60s'", query)); - - if (q->record_file[0]) - { - init_dynamic_string(&ds_tmp, "", 16384, 65536); - ds= &ds_tmp; - } - else - ds= &ds_res; - - /* Store the query into the output buffer if not disabled */ - if (!disable_query_log) - { - replace_dynstr_append_mem(ds,query, query_len); - dynstr_append_mem(ds, delimiter, delimiter_length); - dynstr_append_mem(ds, "\n", 1); - } - - /* - We use the prepared statement interface but there is actually no - '?' in the query. If unpreparable we fall back to use normal - C API. - */ - if ((err= mysql_stmt_prepare(stmt, query, query_len)) == CR_NO_PREPARE_STMT) - return run_query_normal(mysql, q, flags); - - if (err != 0) + /* FIXME we don't handle vertical display ..... */ + uint col_idx, row_idx; + + /* Allocate array with bind structs, lengths and NULL flags */ + bind= (MYSQL_BIND*) my_malloc(num_fields * sizeof(MYSQL_BIND), + MYF(MY_WME | MY_FAE | MY_ZEROFILL)); + length= (ulong*) my_malloc(num_fields * sizeof(ulong), + MYF(MY_WME | MY_FAE)); + is_null= (my_bool*) my_malloc(num_fields * sizeof(my_bool), + MYF(MY_WME | MY_FAE)); + + for (col_idx= 0; col_idx < num_fields; col_idx++) { + /* Allocate data for output */ /* - Preparing is part of normal execution and some errors may be expected + FIXME it may be a bug that for non string/blob types + 'max_length' is 0, should try out 'length' in that case */ - if (handle_error(query, q, mysql_stmt_errno(stmt), - mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds)) - error= 1; - goto end; + uint max_length= max(field[col_idx].max_length + 1, 1024); + char *str_data= (char *) my_malloc(max_length, MYF(MY_WME | MY_FAE)); + + bind[col_idx].buffer_type= MYSQL_TYPE_STRING; + bind[col_idx].buffer= (char *)str_data; + bind[col_idx].buffer_length= max_length; + bind[col_idx].is_null= &is_null[col_idx]; + bind[col_idx].length= &length[col_idx]; } - - /* We may have got warnings already, collect them if any */ - if (!disable_ps_warnings) - run_query_stmt_handle_warnings(mysql, ds); - - /* - No need to call mysql_stmt_bind_param() because we have no - parameter markers. - - To optimize performance we use a global 'stmt' that is initiated - once. A new prepare will implicitely close the old one. When we - terminate we will lose the connection, this also closes the last - prepared statement. - */ - - if (mysql_stmt_execute(stmt) != 0) /* 0 == Success */ - { - /* We got an error, maybe expected */ - if (handle_error(query, q, mysql_stmt_errno(stmt), - mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds)) - error= 1; - goto end; - } - - /* - We instruct that we want to update the "max_length" field in - mysql_stmt_store_result(), this is our only way to know how much - buffer to allocate for result data - */ - { - my_bool one= 1; - if ((err= mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, - (void*) &one)) != 0) - die("unable to set stmt attribute " - "'STMT_ATTR_UPDATE_MAX_LENGTH' err: %d", err); - } - - /* - If we got here the statement succeeded and was expected to do so, - get data. Note that this can still give errors found during execution! - */ - if ((err= mysql_stmt_store_result(stmt)) != 0) - { - /* We got an error, maybe expected */ - if(handle_error(query, q, mysql_stmt_errno(stmt), - mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds)) - error = 1; - goto end; - } - - /* If we got here the statement was both executed and read succeesfully */ - if (handle_no_error(q)) - { - error= 1; - goto end; - } - + + /* Fill in the data into the structures created above */ + if (mysql_stmt_bind_result(stmt, bind)) + die("mysql_stmt_bind_result failed: %d: %s", + mysql_stmt_errno(stmt), mysql_stmt_error(stmt)); + + /* Read result from each row */ num_rows= mysql_stmt_num_rows(stmt); - - /* - 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 && ((res= mysql_stmt_result_metadata(stmt)) != NULL)) + for (row_idx= 0; row_idx < num_rows; row_idx++) { - /* Take the column count from meta info */ - MYSQL_FIELD *field= mysql_fetch_fields(res); - uint num_fields= mysql_num_fields(res); - - if (display_metadata) - run_query_display_metadata(field, num_fields, ds); - + if (mysql_stmt_fetch(stmt)) + die("mysql_stmt_fetch failed: %d %s", + mysql_stmt_errno(stmt), mysql_stmt_error(stmt)); + + /* Read result from each column */ + for (col_idx= 0; col_idx < num_fields; col_idx++) + { + /* FIXME is string terminated? */ + const char *val= (const char *)bind[col_idx].buffer; + ulonglong len= *bind[col_idx].length; + if (col_idx < max_replace_column && replace_column[col_idx]) + { + val= replace_column[col_idx]; + len= strlen(val); + } + if (*bind[col_idx].is_null) + { + val= "NULL"; + len= 4; + } + if (!display_result_vertically) + { + if (col_idx) /* No tab before first col */ + dynstr_append_mem(ds, "\t", 1); + replace_dynstr_append_mem(ds, val, (int)len); + } + else + { + dynstr_append(ds, field[col_idx].name); + dynstr_append_mem(ds, "\t", 1); + replace_dynstr_append_mem(ds, val, (int)len); + dynstr_append_mem(ds, "\n", 1); + } + } if (!display_result_vertically) - { - /* Display the table heading with the names tab separated */ - uint col_idx; - for (col_idx= 0; col_idx < num_fields; col_idx++) - { - if (col_idx) - dynstr_append_mem(ds, "\t", 1); - replace_dynstr_append(ds, field[col_idx].name); - } dynstr_append_mem(ds, "\n", 1); - } - - /* Now we are to put the real result into the output buffer */ - /* FIXME when it works, create function append_stmt_result() */ - { - MYSQL_BIND *bind; - my_bool *is_null; - unsigned long *length; - /* FIXME we don't handle vertical display ..... */ - uint col_idx, row_idx; - - /* Allocate array with bind structs, lengths and NULL flags */ - bind= (MYSQL_BIND*) my_malloc(num_fields * sizeof(MYSQL_BIND), - MYF(MY_WME | MY_FAE | MY_ZEROFILL)); - length= (unsigned long*) my_malloc(num_fields * sizeof(unsigned long), - MYF(MY_WME | MY_FAE)); - is_null= (my_bool*) my_malloc(num_fields * sizeof(my_bool), - MYF(MY_WME | MY_FAE)); - - for (col_idx= 0; col_idx < num_fields; col_idx++) - { - /* Allocate data for output */ - /* - FIXME it may be a bug that for non string/blob types - 'max_length' is 0, should try out 'length' in that case - */ - uint max_length= max(field[col_idx].max_length + 1, 1024); - char *str_data= (char *) my_malloc(max_length, MYF(MY_WME | MY_FAE)); - - bind[col_idx].buffer_type= MYSQL_TYPE_STRING; - bind[col_idx].buffer= (char *)str_data; - bind[col_idx].buffer_length= max_length; - bind[col_idx].is_null= &is_null[col_idx]; - bind[col_idx].length= &length[col_idx]; - } - - /* Fill in the data into the structures created above */ - if ((err= mysql_stmt_bind_result(stmt, bind)) != 0) - die("unable to bind result to statement '%s': " - "%s (mysql_stmt_errno=%d returned=%d)", - query, - mysql_stmt_error(stmt), mysql_stmt_errno(stmt), err); - - /* Read result from each row */ - for (row_idx= 0; row_idx < num_rows; row_idx++) - { - if ((err= mysql_stmt_fetch(stmt)) != 0) - die("unable to fetch all rows from statement '%s': " - "%s (mysql_stmt_errno=%d returned=%d)", - query, - mysql_stmt_error(stmt), mysql_stmt_errno(stmt), err); - - /* Read result from each column */ - for (col_idx= 0; col_idx < num_fields; col_idx++) - { - /* FIXME is string terminated? */ - const char *val= (const char *)bind[col_idx].buffer; - ulonglong len= *bind[col_idx].length; - if (col_idx < max_replace_column && replace_column[col_idx]) - { - val= replace_column[col_idx]; - len= strlen(val); - } - if (*bind[col_idx].is_null) - { - val= "NULL"; - len= 4; - } - if (!display_result_vertically) - { - if (col_idx) /* No tab before first col */ - dynstr_append_mem(ds, "\t", 1); - replace_dynstr_append_mem(ds, val, (int)len); - } - else - { - dynstr_append(ds, field[col_idx].name); - dynstr_append_mem(ds, "\t", 1); - replace_dynstr_append_mem(ds, val, (int)len); - dynstr_append_mem(ds, "\n", 1); - } - } - if (!display_result_vertically) - dynstr_append_mem(ds, "\n", 1); - } - - if ((err= mysql_stmt_fetch(stmt)) != MYSQL_NO_DATA) - die("fetch didn't end with MYSQL_NO_DATA from statement " - "'%s': %s (mysql_stmt_errno=%d returned=%d)", - query, - mysql_stmt_error(stmt), mysql_stmt_errno(stmt), err); - - free_replace_column(); - - for (col_idx= 0; col_idx < num_fields; col_idx++) - { - /* Free data for output */ - my_free((gptr)bind[col_idx].buffer, MYF(MY_WME | MY_FAE)); - } - /* Free array with bind structs, lengths and NULL flags */ - my_free((gptr)bind , MYF(MY_WME | MY_FAE)); - my_free((gptr)length , MYF(MY_WME | MY_FAE)); - my_free((gptr)is_null , MYF(MY_WME | MY_FAE)); - } - - /* Add all warnings to the result */ - run_query_stmt_handle_warnings(mysql, ds); - - if (!disable_info) - { - char buf[40]; - sprintf(buf,"affected rows: %lu\n",(ulong) mysql_affected_rows(mysql)); - dynstr_append(ds, buf); - if (mysql_info(mysql)) - { - dynstr_append(ds, "info: "); - dynstr_append(ds, mysql_info(mysql)); - dynstr_append_mem(ds, "\n", 1); - } - } } - run_query_stmt_handle_warnings(mysql, ds); - - if (record) + + if (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA) + die("fetch didn't end with MYSQL_NO_DATA from statement: %d %s", + mysql_stmt_error(stmt), mysql_stmt_errno(stmt)); + + free_replace_column(); + + for (col_idx= 0; col_idx < num_fields; col_idx++) { - if (!q->record_file[0] && !result_file) - die("Missing result file"); - if (!result_file) - str_to_file(q->record_file, ds->str, ds->length); + /* Free data for output */ + my_free((gptr)bind[col_idx].buffer, MYF(MY_WME | MY_FAE)); } - else if (q->record_file[0]) - { - error= check_result(ds, q->record_file, q->require_file); - } - if (res) - mysql_free_result(res); /* Free normal result set with meta data */ - last_result= 0; /* FIXME have no idea what this is about... */ - -end: - free_replace(); - last_result=0; - if (ds == &ds_tmp) - dynstr_free(&ds_tmp); - if (q->type == Q_EVAL) - dynstr_free(&eval_query); - var_set_errno(mysql_stmt_errno(stmt)); - mysql_stmt_close(stmt); - DBUG_RETURN(error); + /* Free array with bind structs, lengths and NULL flags */ + my_free((gptr)bind , MYF(MY_WME | MY_FAE)); + my_free((gptr)length , MYF(MY_WME | MY_FAE)); + my_free((gptr)is_null , MYF(MY_WME | MY_FAE)); } -/****************************************************************************\ - * Broken out sub functions to run_query_stmt() -\****************************************************************************/ +/* + Append metadata for fields to output +*/ -static void run_query_display_metadata(MYSQL_FIELD *field, uint num_fields, - DYNAMIC_STRING *ds) +static void append_metadata(DYNAMIC_STRING *ds, + MYSQL_FIELD *field, + uint num_fields) { MYSQL_FIELD *field_end; dynstr_append(ds,"Catalog\tDatabase\tTable\tTable_alias\tColumn\t" @@ -3676,39 +3085,564 @@ static void run_query_display_metadata(MYSQL_FIELD *field, uint num_fields, } } +/* + Append affected row count and other info to output +*/ -static void run_query_stmt_handle_warnings(MYSQL *mysql, DYNAMIC_STRING *ds) +static void append_info(DYNAMIC_STRING* ds, ulong affected_rows, + const char* info) +{ + char buf[40]; + sprintf(buf,"affected rows: %lu\n", affected_rows); + dynstr_append(ds, buf); + if (info) + { + dynstr_append(ds, "info: "); + dynstr_append(ds, info); + dynstr_append_mem(ds, "\n", 1); + } +} + + +/* + Display the table headings with the names tab separated +*/ +static void append_table_headings(DYNAMIC_STRING* ds, + MYSQL_FIELD* field, + uint num_fields) +{ + uint col_idx; + for (col_idx= 0; col_idx < num_fields; col_idx++) + { + if (col_idx) + dynstr_append_mem(ds, "\t", 1); + replace_dynstr_append(ds, field[col_idx].name); + } + dynstr_append_mem(ds, "\n", 1); +} + +/* + Fetch warnings from server and append to output +*/ + +static void append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql) { uint count; - DBUG_ENTER("run_query_stmt_handle_warnings"); + DBUG_ENTER("append_warnings"); - if (!disable_warnings && (count= mysql_warning_count(mysql))) + if (!(count= mysql_warning_count(mysql))) + DBUG_VOID_RETURN; + + /* + If one day we will support execution of multi-statements + through PS API we should not issue SHOW WARNINGS until + we have not read all results... + */ + DBUG_ASSERT(!mysql_more_results(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) + 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); + + DBUG_VOID_RETURN; +} + + +/* + Run query using MySQL C API + + SYNPOSIS + run_query_normal + mysql - mysql handle + command - currrent command pointer + query - query string to execute + query_len - length query string to execute + ds - output buffer wherte to store result form query + + RETURN VALUE + error - function will not return +*/ + +static void run_query_normal(MYSQL *mysql, struct st_query *command, + int flags, char *query, int query_len, + DYNAMIC_STRING *ds) +{ + MYSQL_RES *res= 0; + int err= 0, counter= 0; + DBUG_ENTER("run_query_normal"); + DBUG_PRINT("enter",("flags: %d", flags)); + DBUG_PRINT("enter", ("query: '%-.60s'", query)); + + if (flags & QUERY_SEND) { - /* - If one day we will support execution of multi-statements - through PS API we should not issue SHOW WARNINGS until - we have not read all results... - */ - DBUG_ASSERT(!mysql_more_results(mysql)); - - if (mysql_real_query(mysql, "SHOW WARNINGS", 13) == 0) + /* + Send the query, using the undocumented function mysql_send_query + */ + if (mysql_send_query(mysql, query, query_len)) { - MYSQL_RES *warn_res= mysql_store_result(mysql); - if (!warn_res) - die("Warning count is %u but didn't get any warnings", - count); - else - { - dynstr_append_mem(ds, "Warnings:\n", 10); - append_result(ds, warn_res); - mysql_free_result(warn_res); - } + handle_error(query, command, mysql_errno(mysql), mysql_error(mysql), + mysql_sqlstate(mysql), ds); + goto end; } } + + if (!(flags & QUERY_REAP)) + DBUG_VOID_RETURN; + + do + { + /* + When on first result set, call mysql_read_query_result to retrrieve + answer to the query sent earlier + */ + if ((counter==0) && mysql_read_query_result(mysql)) + { + handle_error(query, command, mysql_errno(mysql), mysql_error(mysql), + mysql_sqlstate(mysql), ds); + goto end; + + } + + /* + Store the result. If res is NULL, use mysql_field_count to + determine if that was expected + */ + if (!(res= mysql_store_result(mysql)) && mysql_field_count(mysql)) + { + handle_error(query, command, mysql_errno(mysql), mysql_error(mysql), + mysql_sqlstate(mysql), ds); + goto end; + } + + if (!disable_result_log) + { + ulong affected_rows; /* Ok to be undef if 'disable_info' is set */ + LINT_INIT(affected_rows); + + if (res) + { + MYSQL_FIELD *fields= mysql_fetch_fields(res); + uint num_fields= mysql_num_fields(res); + + if (display_metadata) + append_metadata(ds, fields, num_fields); + + if (!display_result_vertically) + append_table_headings(ds, fields, num_fields); + + append_result(ds, res); + } + + /* + Need to call mysql_affected_rows() before the "new" + query to find the warnings + */ + if (!disable_info) + affected_rows= (ulong)mysql_affected_rows(mysql); + + /* + Add all warnings to the result. We can't do this if we are in + the middle of processing results from multi-statement, because + this will break protocol. + */ + if (!disable_warnings && !mysql_more_results(mysql)) + append_warnings(ds, mysql); + + if (!disable_info) + append_info(ds, affected_rows, mysql_info(mysql)); + } + + if (res) + mysql_free_result(res); + counter++; + } while (!(err= mysql_next_result(mysql))); + if (err > 0) + { + /* We got an error from mysql_next_result, maybe expected */ + handle_error(query, command, mysql_errno(mysql), mysql_error(mysql), + mysql_sqlstate(mysql), ds); + goto end; + } + DBUG_ASSERT(err == -1); /* Successful and there are no more results */ + + /* If we come here the query is both executed and read successfully */ + handle_no_error(command); + +end: + free_replace(); + + /* + We save the return code (mysql_errno(mysql)) 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_errno(mysql)); DBUG_VOID_RETURN; } +/* + Handle errors which occurred during execution + + SYNOPSIS + handle_error() + query - query string + q - query context + err_errno - error number + err_error - error message + err_sqlstate - sql state + ds - dynamic string which is used for output buffer + + NOTE + If there is an unexpected error this function will abort mysqltest + immediately. + + RETURN VALUE + error - function will not return +*/ + +static void handle_error(const char *query, struct st_query *q, + unsigned int err_errno, const char *err_error, + const char *err_sqlstate, DYNAMIC_STRING *ds) +{ + uint i; + + DBUG_ENTER("handle_error"); + + if (q->require_file) + abort_not_supported_test(); + + if (q->abort_on_error) + die("query '%s' failed: %d: %s", query, err_errno, err_error); + + for (i= 0 ; (uint) i < q->expected_errors ; i++) + { + if (((q->expected_errno[i].type == ERR_ERRNO) && + (q->expected_errno[i].code.errnum == err_errno)) || + ((q->expected_errno[i].type == ERR_SQLSTATE) && + (strcmp(q->expected_errno[i].code.sqlstate, err_sqlstate) == 0))) + { + if (q->expected_errors == 1) + { + /* Only log error if there is one possible error */ + dynstr_append_mem(ds, "ERROR ", 6); + replace_dynstr_append(ds, err_sqlstate); + dynstr_append_mem(ds, ": ", 2); + replace_dynstr_append(ds, err_error); + dynstr_append_mem(ds,"\n",1); + } + /* Don't log error if we may not get an error */ + else if (q->expected_errno[0].type == ERR_SQLSTATE || + (q->expected_errno[0].type == ERR_ERRNO && + q->expected_errno[0].code.errnum != 0)) + dynstr_append(ds,"Got one of the listed errors\n"); + /* OK */ + DBUG_VOID_RETURN; + } + } + + DBUG_PRINT("info",("i: %d expected_errors: %d", i, q->expected_errors)); + + dynstr_append_mem(ds, "ERROR ",6); + replace_dynstr_append(ds, err_sqlstate); + dynstr_append_mem(ds, ": ", 2); + replace_dynstr_append(ds, err_error); + dynstr_append_mem(ds, "\n", 1); + + if (i) + { + if (q->expected_errno[0].type == ERR_ERRNO) + die("query '%s' failed with wrong errno %d instead of %d...", + q->query, err_errno, q->expected_errno[0].code.errnum); + else + die("query '%s' failed with wrong sqlstate %s instead of %s...", + q->query, err_sqlstate, q->expected_errno[0].code.sqlstate); + } + + /* + If we do not abort on error, failure to run the query does not fail the + whole test case. + */ + verbose_msg("query '%s' failed: %d: %s", q->query, err_errno, + err_error); + DBUG_VOID_RETURN; +} + + +/* + Handle absence of errors after execution + + SYNOPSIS + handle_no_error() + q - context of query + + RETURN VALUE + error - function will not return +*/ + +static void handle_no_error(struct st_query *q) +{ + DBUG_ENTER("handle_no_error"); + + if (q->expected_errno[0].type == ERR_ERRNO && + q->expected_errno[0].code.errnum != 0) + { + /* Error code we wanted was != 0, i.e. not an expected success */ + die("query '%s' succeeded - should have failed with errno %d...", + q->query, q->expected_errno[0].code.errnum); + } + else if (q->expected_errno[0].type == ERR_SQLSTATE && + strcmp(q->expected_errno[0].code.sqlstate,"00000") != 0) + { + /* SQLSTATE we wanted was != "00000", i.e. not an expected success */ + die("query '%s' succeeded - should have failed with sqlstate %s...", + q->query, q->expected_errno[0].code.sqlstate); + } + + DBUG_VOID_RETURN; +} + + +/* + Run query using prepared statement C API + + SYNPOSIS + run_query_stmt + mysql - mysql handle + command - currrent command pointer + query - query string to execute + query_len - length query string to execute + ds - output buffer wherte to store result form query + + RETURN VALUE + error - function will not return +*/ + +static void run_query_stmt(MYSQL *mysql, struct st_query *command, + char *query, int query_len, DYNAMIC_STRING *ds) +{ + MYSQL_RES *res= NULL; /* Note that here 'res' is meta data result set */ + MYSQL_STMT *stmt; + 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 + */ + if (!(stmt= mysql_stmt_init(mysql))) + die("unable to init stmt structure"); + + /* + Prepare the query + */ + if (mysql_stmt_prepare(stmt, query, query_len)) + { + handle_error(query, command, mysql_stmt_errno(stmt), + mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds); + goto end; + } + + /* + No need to call mysql_stmt_bind_param() because we have no + parameter markers. + */ + + /* + Execute the query + */ + if (mysql_stmt_execute(stmt)) + { + handle_error(query, command, mysql_stmt_errno(stmt), + mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds); + goto end; + } + + /* + We instruct that we want to update the "max_length" field in + mysql_stmt_store_result(), this is our only way to know how much + buffer to allocate for result data + */ + { + 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", + mysql_stmt_errno(stmt), mysql_stmt_error(stmt)); + } + + /* + If we got here the statement succeeded and was expected to do so, + get data. Note that this can still give errors found during execution! + */ + if (mysql_stmt_store_result(stmt)) + { + handle_error(query, command, mysql_stmt_errno(stmt), + mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds); + goto end; + } + + /* If we got here the statement was both executed and read succeesfully */ + handle_no_error(command); + + /* + 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 */ + MYSQL_FIELD *fields= mysql_fetch_fields(res); + uint num_fields= mysql_num_fields(res); + + if (display_metadata) + append_metadata(ds, fields, num_fields); + + if (!display_result_vertically) + append_table_headings(ds, fields, num_fields); + + append_stmt_result(ds, stmt, fields, num_fields); + + mysql_free_result(res); /* Free normal result set with meta data */ + + } + + if (!disable_warnings) + append_warnings(ds, mysql); + + if (!disable_info) + append_info(ds, (ulong)mysql_affected_rows(mysql), mysql_info(mysql)); + } + +end: + free_replace(); + /* + 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 + if QUERY_SEND bit is on, the query will be sent. If QUERY_REAP is on + the result will be read - for regular query, both bits must be on + + SYNPOSIS + run_query + mysql - mysql handle + command - currrent command pointer + +*/ + +static void run_query(MYSQL *mysql, struct st_query *command, int flags) +{ + DYNAMIC_STRING *ds; + DYNAMIC_STRING ds_tmp; + DYNAMIC_STRING eval_query; + char *query; + int query_len; + + /* + Evaluate query if this is an eval command + */ + if (command->type == Q_EVAL) + { + init_dynamic_string(&eval_query, "", 16384, 65536); + do_eval(&eval_query, command->query); + query = eval_query.str; + query_len = eval_query.length; + } + else + { + query = command->query; + query_len = strlen(query); + } + + /* + When command->record_file is set the output of _this_ query + should be compared with an already existing file + Create a temporary dynamic string to contain the output from + this query. + */ + if (command->record_file[0]) + { + init_dynamic_string(&ds_tmp, "", 16384, 65536); + ds= &ds_tmp; + } + else + ds= &ds_res; + + /* Store the query into the output buffer */ + if (!disable_query_log && (flags & QUERY_SEND)) + { + replace_dynstr_append_mem(ds,query, query_len); + dynstr_append_mem(ds, delimiter, delimiter_length); + dynstr_append_mem(ds, "\n", 1); + } + + /* + 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 + + 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)) + run_query_stmt(mysql, command, query, query_len, ds); + else + run_query_normal(mysql, command, flags, query, query_len, ds); + + if (record) + { + /* Recording in progress */ + if (!command->record_file[0]) + die("Missing result file"); + + /* Dump the output from _this_ query to the specified record_file */ + str_to_file(command->record_file, ds->str, ds->length); + } + else if (command->record_file[0]) + { + /* + The output from _this_ query should be checked against an already + existing file which has been specified using --require or --result + */ + check_result(ds, command->record_file, command->require_file); + } + + if (ds == &ds_tmp) + dynstr_free(&ds_tmp); + if (command->type == Q_EVAL) + dynstr_free(&eval_query); +} + + /****************************************************************************\ * Functions to match SQL statements that can be prepared \****************************************************************************/ @@ -3911,7 +3845,6 @@ static void init_var_hash(MYSQL *mysql) int main(int argc, char **argv) { - int error = 0; struct st_query *q; my_bool require_file=0, q_send_flag=0, abort_flag= 0, query_executed= 0; @@ -4005,7 +3938,7 @@ int main(int argc, char **argv) processed = 1; switch (q->type) { case Q_CONNECT: - error|= do_connect(q); + do_connect(q); break; case Q_CONNECTION: select_connection(q); break; case Q_DISCONNECT: @@ -4039,7 +3972,7 @@ int main(int argc, char **argv) #endif case Q_INC: do_modify_var(q, "inc", DO_INC); break; case Q_DEC: do_modify_var(q, "dec", DO_DEC); break; - case Q_ECHO: do_echo(q); break; + case Q_ECHO: do_echo(q); query_executed= 1; break; case Q_SYSTEM: do_system(q); break; case Q_DELIMITER: strmake(delimiter, q->first_argument, sizeof(delimiter) - 1); @@ -4066,15 +3999,6 @@ int main(int argc, char **argv) case Q_QUERY_HORIZONTAL: { my_bool old_display_result_vertically= display_result_vertically; - if (!q->query[q->first_word_len]) - { - /* This happens when we use 'query_..' on it's own line */ - q_send_flag=1; - DBUG_PRINT("info", - ("query: '%s' first_word_len: %d send_flag=1", - q->query, q->first_word_len)); - break; - } /* fix up query pointer if this is * first iteration for this line */ if (q->query == q->query_buf) q->query += q->first_word_len + 1; @@ -4085,7 +4009,7 @@ int main(int argc, char **argv) q->require_file=require_file; save_file[0]=0; } - error|= run_query(&cur_con->mysql, q, QUERY_REAP|QUERY_SEND); + run_query(&cur_con->mysql, q, QUERY_REAP|QUERY_SEND); display_result_vertically= old_display_result_vertically; q->last_argument= q->end; query_executed= 1; @@ -4112,7 +4036,7 @@ int main(int argc, char **argv) q->require_file=require_file; save_file[0]=0; } - error |= run_query(&cur_con->mysql, q, flags); + run_query(&cur_con->mysql, q, flags); query_executed= 1; q->last_argument= q->end; break; @@ -4133,7 +4057,7 @@ int main(int argc, char **argv) query and read the result some time later when reap instruction is given on this connection. */ - error |= run_query(&cur_con->mysql, q, QUERY_SEND); + run_query(&cur_con->mysql, q, QUERY_SEND); query_executed= 1; q->last_argument= q->end; break; @@ -4255,6 +4179,12 @@ int main(int argc, char **argv) parser.current_line += current_line_inc; } + /* + The whole test has been executed sucessfully + Time to compare result or save it to record file + The entire output from test is now kept in ds_res + */ + if (!query_executed && result_file && my_stat(result_file, &res_info, 0)) { /* @@ -4265,39 +4195,46 @@ int main(int argc, char **argv) no query output from the test file, e.g. regarded as no error. */ if (res_info.st_size) - error|= (RESULT_CONTENT_MISMATCH | RESULT_LENGTH_MISMATCH); + die("No queries executed but result file found!"); } - if (ds_res.length && !error) + + if (ds_res.length) { if (result_file) { - if (!record) - error |= check_result(&ds_res, result_file, q->require_file); + if (record) + { + /* Dump the output from test to result file */ + str_to_file(result_file, ds_res.str, ds_res.length); + } else - str_to_file(result_file, ds_res.str, ds_res.length); + { + /* Check that the output from test is equal to result file */ + check_result(&ds_res, result_file, 0); + } } else { - /* Print the result to stdout */ + /* No result_file to compare with, print the result to stdout */ printf("%s", ds_res.str); } + } + else + { + /* The test didn't produce any output */ } dynstr_free(&ds_res); - if (!silent) - { - if (error) - printf("not ok\n"); - else - printf("ok\n"); - } - if (!got_end_timer) timer_output(); /* No end_timer cmd, end it */ free_used_memory(); my_end(MY_CHECK_ERROR); - exit(error ? 1 : 0); - return error ? 1 : 0; /* Keep compiler happy */ + + /* Yes, if we got this far the test has suceeded! Sakila smiles */ + if (!silent) + printf("ok\n"); + exit(0); + return 0; /* Keep compiler happy */ } @@ -5094,12 +5031,6 @@ static int initialize_replace_buffer(void) return 0; } -static void free_replace_buffer(void) -{ - my_free(out_buff,MYF(MY_WME)); -} - - /**************************************************************************** Replace results for a column *****************************************************************************/ diff --git a/mysql-test/include/master-slave.inc b/mysql-test/include/master-slave.inc index 5ec4b4379f8..ea09f4e842b 100644 --- a/mysql-test/include/master-slave.inc +++ b/mysql-test/include/master-slave.inc @@ -8,7 +8,8 @@ connection slave; --disable_warnings stop slave; --enable_warnings -@r/slave-stopped.result show status like 'Slave_running'; +--require r/slave-stopped.result +show status like 'Slave_running'; connection master; --disable_warnings drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; @@ -21,7 +22,8 @@ reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; --enable_warnings start slave; -@r/slave-running.result show status like 'Slave_running'; +--require r/slave-running.result +show status like 'Slave_running'; # Set the default connection to 'master' connection master; diff --git a/mysql-test/include/ps_query.inc b/mysql-test/include/ps_query.inc index 27a86f88231..e96d666eaec 100644 --- a/mysql-test/include/ps_query.inc +++ b/mysql-test/include/ps_query.inc @@ -52,7 +52,6 @@ execute stmt1; ##### parameter used for keyword like SELECT (must fail) set @arg00='SELECT' ; -# mysqltest gives no output for the next statement, Why ?? --error 1064 @arg00 a from t1 where a=1; --error 1064 diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index 0ad6db8c57e..abcf4d049ed 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -149,6 +149,9 @@ hello mysqltest: At line 1: End of line junk detected: "6" mysqltest: At line 1: End of line junk detected: "6" mysqltest: At line 1: Missing delimiter +mysqltest: End of line junk detected: "sleep 7 +# Another comment +" mysqltest: At line 1: Extra delimiter ";" found mysqltest: At line 1: Extra delimiter ";" found MySQL diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result index c839c8a65b9..603de2afe4e 100644 --- a/mysql-test/r/ps_2myisam.result +++ b/mysql-test/r/ps_2myisam.result @@ -85,6 +85,8 @@ c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c 1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday 9 9 9 9 9 9 9 9 9 9 9.0000 9.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 0 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext two tuesday set @arg00='SELECT' ; +@arg00 a from t1 where a=1; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 a from t1 where a=1' at line 1 prepare stmt1 from ' ? a from t1 where a=1 '; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a from t1 where a=1' at line 1 set @arg00=1 ; diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result index 81d6180e41f..9e635f60f14 100644 --- a/mysql-test/r/ps_3innodb.result +++ b/mysql-test/r/ps_3innodb.result @@ -85,6 +85,8 @@ c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c 1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday 9 9 9 9 9 9 9 9 9 9 9.0000 9.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 0 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext two tuesday set @arg00='SELECT' ; +@arg00 a from t1 where a=1; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 a from t1 where a=1' at line 1 prepare stmt1 from ' ? a from t1 where a=1 '; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a from t1 where a=1' at line 1 set @arg00=1 ; diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result index 931e6b7c86c..fd51c71cad6 100644 --- a/mysql-test/r/ps_4heap.result +++ b/mysql-test/r/ps_4heap.result @@ -86,6 +86,8 @@ c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c 1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday 9 9 9 9 9 9 9 9 9 9 9.0000 9.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 0 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext two tuesday set @arg00='SELECT' ; +@arg00 a from t1 where a=1; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 a from t1 where a=1' at line 1 prepare stmt1 from ' ? a from t1 where a=1 '; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a from t1 where a=1' at line 1 set @arg00=1 ; diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result index 3b9244c251f..876f7615672 100644 --- a/mysql-test/r/ps_5merge.result +++ b/mysql-test/r/ps_5merge.result @@ -128,6 +128,8 @@ c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c 1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday 9 9 9 9 9 9 9 9 9 9 9.0000 9.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 0 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext two tuesday set @arg00='SELECT' ; +@arg00 a from t1 where a=1; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 a from t1 where a=1' at line 1 prepare stmt1 from ' ? a from t1 where a=1 '; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a from t1 where a=1' at line 1 set @arg00=1 ; @@ -3140,6 +3142,8 @@ c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c 1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday 9 9 9 9 9 9 9 9 9 9 9.0000 9.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 0 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext two tuesday set @arg00='SELECT' ; +@arg00 a from t1 where a=1; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 a from t1 where a=1' at line 1 prepare stmt1 from ' ? a from t1 where a=1 '; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a from t1 where a=1' at line 1 set @arg00=1 ; diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result index 643e12f7e2d..c39621d184f 100644 --- a/mysql-test/r/ps_6bdb.result +++ b/mysql-test/r/ps_6bdb.result @@ -85,6 +85,8 @@ c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c 1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday 9 9 9 9 9 9 9 9 9 9 9.0000 9.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 0 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext two tuesday set @arg00='SELECT' ; +@arg00 a from t1 where a=1; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 a from t1 where a=1' at line 1 prepare stmt1 from ' ? a from t1 where a=1 '; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a from t1 where a=1' at line 1 set @arg00=1 ; diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result index 9fbe67f581b..7c83099311e 100644 --- a/mysql-test/r/ps_7ndb.result +++ b/mysql-test/r/ps_7ndb.result @@ -85,6 +85,8 @@ c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c 1 1 1 1 1 1 1 1 1 1 1.0000 1.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 1 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext one monday 9 9 9 9 9 9 9 9 9 9 9.0000 9.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 0 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext two tuesday set @arg00='SELECT' ; +@arg00 a from t1 where a=1; +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 a from t1 where a=1' at line 1 prepare stmt1 from ' ? a from t1 where a=1 '; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a from t1 where a=1' at line 1 set @arg00=1 ; diff --git a/mysql-test/t/alias.test b/mysql-test/t/alias.test index 2746409c7e5..6546581eef2 100644 --- a/mysql-test/t/alias.test +++ b/mysql-test/t/alias.test @@ -61,9 +61,7 @@ INSERT INTO t1 VALUES (3359361,406,3359361,'Mustermann Musterfrau',7001,'2000-05 INSERT INTO t1 VALUES (3359362,406,3359362,'Mustermann Musterfrau',7001,'2000-05-20','workflow','Auftrag erledigt','Originalvertrag eingegangen und geprüft','','privat',1509984,2145874,'+','','P',1909154,'MobilComSuper92000D1(Akquise)',NULL,NULL,'MS9ND1',327,24,'MobilCom Intern',7003,NULL,'auto',20010202105916,'Mobilfunk','PP','','',''); # This died because we used the field Kundentyp twice ---disable_ps_protocol SELECT ELT(FIELD(kundentyp,'PP','PPA','PG','PGA','FK','FKA','FP','FPA','K','KA','V','VA',''), 'Privat (Private Nutzung)','Privat (Private Nutzung) Sitz im Ausland','Privat (geschaeftliche Nutzung)','Privat (geschaeftliche Nutzung) Sitz im Ausland','Firma (Kapitalgesellschaft)','Firma (Kapitalgesellschaft) Sitz im Ausland','Firma (Personengesellschaft)','Firma (Personengesellschaft) Sitz im Ausland','oeff. rechtl. Koerperschaft','oeff. rechtl. Koerperschaft Sitz im Ausland','Eingetragener Verein','Eingetragener Verein Sitz im Ausland','Typ unbekannt') AS Kundentyp ,kategorie FROM t1 WHERE hdl_nr < 2000000 AND kategorie IN ('Prepaid','Mobilfunk') AND st_klasse = 'Workflow' GROUP BY kundentyp ORDER BY kategorie; ---enable_ps_protocol drop table t1; diff --git a/mysql-test/t/group_by.test b/mysql-test/t/group_by.test index bf557029a55..fb9835c5d7f 100644 --- a/mysql-test/t/group_by.test +++ b/mysql-test/t/group_by.test @@ -596,9 +596,7 @@ drop table t1; CREATE TABLE t1 (n int); INSERT INTO t1 VALUES (1); ---disable_ps_protocol SELECT n+1 AS n FROM t1 GROUP BY n; ---enable_ps_protocol DROP TABLE t1; # @@ -623,11 +621,9 @@ insert into t1 values ('aaa', 'bb1'), ('aaa', 'bb2'); insert into t2 values ('aaa', 'bb1'), ('aaa', 'bb2'); # query with ambiguous column reference 'c2' ---disable_ps_protocol select t1.c1 as c2 from t1, t2 where t1.c2 = t2.c4 group by c2; show warnings; ---enable_ps_protocol # this query has no ambiguity select t1.c1 as c2 from t1, t2 where t1.c2 = t2.c4 diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index 11fbb023963..a1f7e8b4251 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -364,6 +364,15 @@ select 3 from t1 ; --error 1 --exec $MYSQL_TEST < var/log/mysqltest.sql 2>&1 +# +# Missing delimiter until eof +# The comment will be "sucked into" the sleep command since +# delimiter is missing +--system echo "sleep 7" > var/log/mysqltest.sql +--system echo "# Another comment" >> var/log/mysqltest.sql +--error 1 +--exec $MYSQL_TEST < var/log/mysqltest.sql 2>&1 + # # Extra delimiter # diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test index daa83ef0fa4..a30321470ea 100644 --- a/mysql-test/t/union.test +++ b/mysql-test/t/union.test @@ -27,12 +27,9 @@ select 't1',b,count(*) from t1 group by b UNION select 't2',b,count(*) from t2 g (select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by t1.b; explain extended (select a,b from t1 limit 2) union all (select a,b from t2 order by a limit 1) order by b desc; (select sql_calc_found_rows a,b from t1 limit 2) union all (select a,b from t2 order by a) limit 2; -# PS doesn't work correctly with found_rows: to be fixed ---disable_ps_protocol select found_rows(); select sql_calc_found_rows a,b from t1 union all select a,b from t2 limit 2; select found_rows(); ---enable_ps_protocol # # Test some error conditions with UNION @@ -210,27 +207,15 @@ insert into t2 values (3),(4),(5); # Test global limits (SELECT SQL_CALC_FOUND_ROWS * FROM t1) UNION all (SELECT * FROM t2) LIMIT 1; -# PS doesn't work correctly with found_rows: to be fixed ---disable_ps_protocol select found_rows(); ---enable_ps_protocol (SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1) UNION all (SELECT * FROM t2) LIMIT 2; -# PS doesn't work correctly with found_rows: to be fixed ---disable_ps_protocol select found_rows(); ---enable_ps_protocol # Test cases where found_rows() should return number of returned rows (SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1) UNION all (SELECT * FROM t2); -# PS doesn't work correctly with found_rows: to be fixed ---disable_ps_protocol select found_rows(); ---enable_ps_protocol (SELECT SQL_CALC_FOUND_ROWS * FROM t1) UNION all (SELECT * FROM t2 LIMIT 1); -# PS doesn't work correctly with found_rows: to be fixed ---disable_ps_protocol select found_rows(); ---enable_ps_protocol # This used to work in 4.0 but not anymore in 4.1 --error 1064 (SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1) UNION SELECT * FROM t2 LIMIT 1; @@ -238,15 +223,9 @@ select found_rows(); # In these case found_rows() should work SELECT SQL_CALC_FOUND_ROWS * FROM t1 LIMIT 1 UNION all SELECT * FROM t2 LIMIT 2; -# PS doesn't work correctly with found_rows: to be fixed ---disable_ps_protocol select found_rows(); ---disable_ps_protocol SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION all SELECT * FROM t2 LIMIT 2; -# PS doesn't work correctly with found_rows: to be fixed ---disable_ps_protocol select found_rows(); ---disable_ps_protocol # The following examples will not be exact SELECT SQL_CALC_FOUND_ROWS * FROM t1 UNION SELECT * FROM t2 LIMIT 2; From 718839a1c157f89f3112974efe6d14f07d18a0ce Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Thu, 3 Nov 2005 19:00:37 +0100 Subject: [PATCH 02/19] WL#2930 Adding view and cursor 'protocols' to mysqltest - Part2, actually adding the new functionality --- client/mysqltest.c | 353 ++++++++++++++++++++++++++--------- mysql-test/mysql-test-run.pl | 25 +++ 2 files changed, 290 insertions(+), 88 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index b5a0f65f55c..1b24d44bdf3 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -42,7 +42,7 @@ **********************************************************************/ -#define MTEST_VERSION "2.5" +#define MTEST_VERSION "2.6" #include #include @@ -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}; /* ************************************************************************ */ /* @@ -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; @@ -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[]= { @@ -240,6 +248,7 @@ struct connection { MYSQL mysql; char *name; + MYSQL_STMT* stmt; }; typedef struct @@ -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*); @@ -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)); } @@ -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; } @@ -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; @@ -2153,7 +2163,7 @@ int do_connect(struct st_query *q) p= safe_get_param(p, &con_db, "Missing connection db"); /* Port */ - VAR* var_port; + VAR *var_port; p= safe_get_param(p, &con_port_str, 0); if (*con_port_str) { @@ -2223,7 +2233,7 @@ int do_connect(struct st_query *q) if (!mysql_init(&next_con->mysql)) die("Failed on mysql_init()"); if (opt_compress || con_compress) - mysql_options(&next_con->mysql,MYSQL_OPT_COMPRESS,NullS); + mysql_options(&next_con->mysql, MYSQL_OPT_COMPRESS, NullS); mysql_options(&next_con->mysql, MYSQL_OPT_LOCAL_INFILE, 0); mysql_options(&next_con->mysql, MYSQL_SET_CHARSET_NAME, charset_name); @@ -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.", @@ -2776,8 +2795,6 @@ void usage() #include -#include - static my_bool get_one_option(int optid, const struct my_option *opt __attribute__((unused)), @@ -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))) @@ -3237,11 +3255,9 @@ 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); @@ -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 @@ -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)) { @@ -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)) @@ -3526,18 +3543,20 @@ 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= mysql_stmt_init(mysql))) - die("unable to init stmt structure"); - + if(!(stmt= cur_con->stmt)) + { + if (!(stmt= mysql_stmt_init(mysql))) + die("unable to init stmt structure"); + cur_con->stmt= stmt; + } + /* Prepare the query */ @@ -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 */ @@ -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)); } @@ -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); - /* - 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) { + /* + 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 ((res= mysql_stmt_result_metadata(stmt)) != NULL) { /* Take the column count from meta info */ @@ -3612,7 +3656,19 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, append_stmt_result(ds, stmt, fields, num_fields); 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) @@ -3620,23 +3676,26 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, 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 @@ -3653,10 +3712,12 @@ end: 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 @@ -3682,35 +3743,122 @@ 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); + replace_dynstr_append_mem(ds, query, query_len); dynstr_append_mem(ds, delimiter, delimiter_length); 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 + 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) { @@ -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:]]|" @@ -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); } + return 0; } -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); -} - - -static void ps_free_reg(void) +static void free_re(void) { my_regfree(&ps_re); + my_regfree(&sp_re); + my_regfree(&view_re); } /****************************************************************************/ @@ -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; } @@ -3969,7 +4140,7 @@ int main(int argc, char **argv) cur_block= block_stack; cur_block->ok= TRUE; /* Outer block should always be executed */ cur_block->cmd= cmd_none; - + init_dynamic_string(&ds_res, "", 0, 65536); parse_args(argc, argv); @@ -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) @@ -5282,3 +5457,5 @@ FILE *my_popen(const char *cmd, const char *mode __attribute__((unused))) } #endif /* __NETWARE__ or __WIN__*/ + + diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 2ca7e7c5e15..3ab0d016f48 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -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; @@ -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, @@ -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, .... @@ -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 From 39b2fb2b3c314976ea848ad740dc8de7bcad5089 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Thu, 3 Nov 2005 19:32:19 +0100 Subject: [PATCH 03/19] Reapplying patch Check for NULLs only if we don't replace column results, get real results after all checks. (see bug #14254: func_crypt.test fails on FreeBSD with --ps-protocol). Remove two FIXME's --- client/mysqltest.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index a2b2b3477eb..89f164b9a47 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -3043,8 +3043,6 @@ static void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT* stmt, my_bool *is_null; ulong *length; ulonglong num_rows; - - /* FIXME we don't handle vertical display ..... */ uint col_idx, row_idx; /* Allocate array with bind structs, lengths and NULL flags */ @@ -3088,19 +3086,23 @@ static void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT* stmt, /* Read result from each column */ for (col_idx= 0; col_idx < num_fields; col_idx++) { - /* FIXME is string terminated? */ - const char *val= (const char *)bind[col_idx].buffer; - ulonglong len= *bind[col_idx].length; + const char *val; + ulonglong len; if (col_idx < max_replace_column && replace_column[col_idx]) { val= replace_column[col_idx]; len= strlen(val); } - if (*bind[col_idx].is_null) + else if (*bind[col_idx].is_null) { val= "NULL"; len= 4; } + else + { + val= (const char *) bind[col_idx].buffer; + len= *bind[col_idx].length; + } if (!display_result_vertically) { if (col_idx) /* No tab before first col */ From 4f26b443185b820de1d979917f42882930c861f4 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Fri, 4 Nov 2005 12:00:34 +0100 Subject: [PATCH 04/19] Remove trailing whitespace --- client/mysqltest.c | 208 +++++++++++++++++++++++---------------------- 1 file changed, 105 insertions(+), 103 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 89f164b9a47..04ad33bb8bc 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -119,7 +119,7 @@ enum {OPT_MANAGER_USER=256,OPT_MANAGER_HOST,OPT_MANAGER_PASSWD, set to type ERR_EMPTY. When an SQL statement return an error we use this list to check if this is an expected error. */ - + enum match_err_type { ERR_EMPTY= 0, @@ -300,7 +300,7 @@ struct connection* cur_con, *next_con, *cons_end; enum enum_commands { Q_CONNECTION=1, Q_QUERY, -Q_CONNECT, Q_SLEEP, Q_REAL_SLEEP, +Q_CONNECT, Q_SLEEP, Q_REAL_SLEEP, Q_INC, Q_DEC, Q_SOURCE, Q_DISCONNECT, Q_LET, Q_ECHO, @@ -740,14 +740,14 @@ err: /* Check the content of ds against content of file fname - + SYNOPSIS check_result ds - content to be checked fname - name of file to check against - require_option - if set and check fails, the test will be aborted with the special + require_option - if set and check fails, the test will be aborted with the special exit code "not supported test" - + RETURN VALUES error - the function will not return @@ -1645,7 +1645,7 @@ static uint get_errcodes(match_err *to,struct st_query *q) /* SQL error as string */ st_error *e= global_error; char *start= p++; - + for (; *p == '_' || my_isalnum(charset_info, *p); p++) ; for (; e->name; e++) @@ -1919,13 +1919,13 @@ int close_connection(struct st_query *q) SYNOPSIS safe_get_param str - string to get param from - arg - pointer to string where result will be stored + arg - pointer to string where result will be stored msg - Message to display if param is not found if msg is 0 this param is not required and param may be empty - + RETURNS pointer to str after param - + */ char* safe_get_param(char *str, char** arg, const char *msg) @@ -1933,7 +1933,7 @@ char* safe_get_param(char *str, char** arg, const char *msg) DBUG_ENTER("safe_get_param"); if(!*str) { - if (msg) + if (msg) die(msg); *arg= str; DBUG_RETURN(str); @@ -2082,7 +2082,7 @@ int connect_n_handle_errors(struct st_query *q, MYSQL* con, const char* host, *create_conn= 0; goto err; } - else + else { handle_no_error(q); @@ -2528,7 +2528,7 @@ int read_line(char *buf, int size) state= R_Q; } else -state= R_NORMAL; + state= R_NORMAL; break; case R_Q: @@ -2922,9 +2922,9 @@ char* safe_str_append(char *buf, const char *str, int size) } -/* +/* Write the content of str into file - + SYNOPSIS str_to_file fname - name of file to truncate/create and write to @@ -2941,7 +2941,7 @@ static void str_to_file(const char *fname, char *str, int size) fname=buff; } fn_format(buff,fname,"","",4); - + if ((fd = my_open(buff, O_WRONLY | O_CREAT | O_TRUNC, MYF(MY_WME | MY_FFNF))) < 0) die("Could not open %s: errno = %d", buff, errno); @@ -3032,7 +3032,7 @@ static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res) /* - Append all results from ps execution to the dynamic string separated + Append all results from ps execution to the dynamic string separated with '\t'. Values may be converted with 'replace_column' */ @@ -3044,7 +3044,7 @@ static void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT* stmt, ulong *length; ulonglong num_rows; uint col_idx, row_idx; - + /* Allocate array with bind structs, lengths and NULL flags */ bind= (MYSQL_BIND*) my_malloc(num_fields * sizeof(MYSQL_BIND), MYF(MY_WME | MY_FAE | MY_ZEROFILL)); @@ -3052,7 +3052,7 @@ static void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT* stmt, MYF(MY_WME | MY_FAE)); is_null= (my_bool*) my_malloc(num_fields * sizeof(my_bool), MYF(MY_WME | MY_FAE)); - + for (col_idx= 0; col_idx < num_fields; col_idx++) { /* Allocate data for output */ @@ -3062,19 +3062,19 @@ static void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT* stmt, */ uint max_length= max(field[col_idx].max_length + 1, 1024); char *str_data= (char *) my_malloc(max_length, MYF(MY_WME | MY_FAE)); - + bind[col_idx].buffer_type= MYSQL_TYPE_STRING; bind[col_idx].buffer= (char *)str_data; bind[col_idx].buffer_length= max_length; bind[col_idx].is_null= &is_null[col_idx]; bind[col_idx].length= &length[col_idx]; } - + /* Fill in the data into the structures created above */ if (mysql_stmt_bind_result(stmt, bind)) - die("mysql_stmt_bind_result failed: %d: %s", + die("mysql_stmt_bind_result failed: %d: %s", mysql_stmt_errno(stmt), mysql_stmt_error(stmt)); - + /* Read result from each row */ num_rows= mysql_stmt_num_rows(stmt); for (row_idx= 0; row_idx < num_rows; row_idx++) @@ -3082,7 +3082,7 @@ static void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT* stmt, if (mysql_stmt_fetch(stmt)) die("mysql_stmt_fetch failed: %d %s", mysql_stmt_errno(stmt), mysql_stmt_error(stmt)); - + /* Read result from each column */ for (col_idx= 0; col_idx < num_fields; col_idx++) { @@ -3120,13 +3120,13 @@ static void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT* stmt, if (!display_result_vertically) dynstr_append_mem(ds, "\n", 1); } - + if (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA) die("fetch didn't end with MYSQL_NO_DATA from statement: %d %s", mysql_stmt_error(stmt), mysql_stmt_errno(stmt)); - + free_replace_column(); - + for (col_idx= 0; col_idx < num_fields; col_idx++) { /* Free data for output */ @@ -3144,7 +3144,7 @@ static void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT* stmt, */ static void append_metadata(DYNAMIC_STRING *ds, - MYSQL_FIELD *field, + MYSQL_FIELD *field, uint num_fields) { MYSQL_FIELD *field_end; @@ -3217,10 +3217,10 @@ static void append_info(DYNAMIC_STRING* ds, ulong affected_rows, } -/* - Display the table headings with the names tab separated +/* + Display the table headings with the names tab separated */ -static void append_table_headings(DYNAMIC_STRING* ds, +static void append_table_headings(DYNAMIC_STRING* ds, MYSQL_FIELD* field, uint num_fields) { @@ -3253,14 +3253,14 @@ static void append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql) we have not read all results... */ DBUG_ASSERT(!mysql_more_results(mysql)); - + if (mysql_real_query(mysql, "SHOW WARNINGS", 13)) die("Error running query \"SHOW WARNINGS\": %s", mysql_error(mysql)); - + 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); @@ -3271,7 +3271,7 @@ static void append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql) /* Run query using MySQL C API - + SYNPOSIS run_query_normal mysql - mysql handle @@ -3285,8 +3285,8 @@ static void append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql) error - function will not return */ -static void run_query_normal(MYSQL *mysql, struct st_query *command, - int flags, char *query, int query_len, +static void run_query_normal(MYSQL *mysql, struct st_query *command, + int flags, char *query, int query_len, DYNAMIC_STRING *ds) { MYSQL_RES *res= 0; @@ -3297,7 +3297,7 @@ static void run_query_normal(MYSQL *mysql, struct st_query *command, if (flags & QUERY_SEND) { - /* + /* Send the query */ if (mysql_send_query(mysql, query, query_len)) @@ -3310,11 +3310,11 @@ static void run_query_normal(MYSQL *mysql, struct st_query *command, if (!(flags & QUERY_REAP)) DBUG_VOID_RETURN; - + do { /* - When on first result set, call mysql_read_query_result to retrieve + 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)) @@ -3325,8 +3325,8 @@ static void run_query_normal(MYSQL *mysql, struct st_query *command, } - /* - Store the result. If res is NULL, use mysql_field_count to + /* + Store the result. If res is NULL, use mysql_field_count to determine if that was expected */ if (!(res= mysql_store_result(mysql)) && mysql_field_count(mysql)) @@ -3386,7 +3386,7 @@ static void run_query_normal(MYSQL *mysql, struct st_query *command, goto end; } DBUG_ASSERT(err == -1); /* Successful and there are no more results */ - + /* If we come here the query is both executed and read successfully */ handle_no_error(command); @@ -3428,12 +3428,12 @@ static void handle_error(const char *query, struct st_query *q, const char *err_sqlstate, DYNAMIC_STRING *ds) { uint i; - + DBUG_ENTER("handle_error"); if (q->require_file) abort_not_supported_test(); - + if (q->abort_on_error) die("query '%s' failed: %d: %s", query, err_errno, err_error); @@ -3527,7 +3527,7 @@ static void handle_no_error(struct st_query *q) /* Run query using prepared statement C API - + SYNPOSIS run_query_stmt mysql - mysql handle @@ -3540,7 +3540,7 @@ static void handle_no_error(struct st_query *q) error - function will not return */ -static void run_query_stmt(MYSQL *mysql, struct st_query *command, +static void run_query_stmt(MYSQL *mysql, struct st_query *command, char *query, int query_len, DYNAMIC_STRING *ds) { MYSQL_RES *res= NULL; /* Note that here 'res' is meta data result set */ @@ -3548,7 +3548,7 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, DYNAMIC_STRING ds_prepare_warnings; DBUG_ENTER("run_query_stmt"); DBUG_PRINT("query", ("'%-.60s'", query)); - + /* Init a new stmt if it's not alreday one created for this connectoon */ @@ -3558,7 +3558,7 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, die("unable to init stmt structure"); cur_con->stmt= stmt; } - + /* Prepare the query */ @@ -3570,10 +3570,10 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, } /* - Get the warnings from mysql_stmt_prepare and keep them in a - separate string + 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); @@ -3594,7 +3594,7 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, { 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", + die("mysql_stmt_attr_set(STMT_ATTR_CURSOR_TYPE) failed': %d %s", mysql_stmt_errno(stmt), mysql_stmt_error(stmt)); } #endif @@ -3602,7 +3602,7 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, /* Execute the query */ - if (mysql_stmt_execute(stmt)) + if (mysql_stmt_execute(stmt)) { handle_error(query, command, mysql_stmt_errno(stmt), mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds); @@ -3617,7 +3617,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(STMT_ATTR_UPDATE_MAX_LENGTH) failed': %d %s", + die("mysql_stmt_attr_set(STMT_ATTR_UPDATE_MAX_LENGTH) failed': %d %s", mysql_stmt_errno(stmt), mysql_stmt_error(stmt)); } @@ -3635,6 +3635,7 @@ 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 @@ -3642,27 +3643,28 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, statement result set. */ if ((res= mysql_stmt_result_metadata(stmt)) != NULL) + { /* Take the column count from meta info */ MYSQL_FIELD *fields= mysql_fetch_fields(res); uint num_fields= mysql_num_fields(res); - + if (display_metadata) append_metadata(ds, fields, num_fields); - + if (!display_result_vertically) append_table_headings(ds, fields, num_fields); - - append_stmt_result(ds, stmt, fields, num_fields); - + + append_stmt_result(ds, stmt, fields, num_fields); + mysql_free_result(res); /* Free normal result set with meta data */ - } - else + } + else { /* This is a query without resultset */ - + /* Add warnings from prepare to output */ @@ -3672,15 +3674,15 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, 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); @@ -3705,7 +3707,7 @@ end: run_query mysql - mysql handle command - currrent command pointer - + */ static void run_query(MYSQL *mysql, struct st_query *command, int flags) @@ -3735,7 +3737,7 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) } /* - When command->record_file is set the output of _this_ query + When command->record_file is set the output of _this_ query should be compared with an already existing file Create a temporary dynamic string to contain the output from this query. @@ -3748,8 +3750,8 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) else ds= &ds_res; - /* - Log the query into the output buffer + /* + Log the query into the output buffer */ if (!disable_query_log && (flags & QUERY_SEND)) { @@ -3762,13 +3764,13 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) 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 ", + 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)) @@ -3777,7 +3779,7 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) Failed to create the view, this is not fatal just run the query the normal way */ - DBUG_PRINT("view_create_error", + DBUG_PRINT("view_create_error", ("Failed to create view '%s': %d: %s", query_str.str, mysql_errno(mysql), mysql_error(mysql))); } @@ -3787,12 +3789,12 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) Yes, it was possible to create this query as a view */ view_created= 1; - query= (char*)"SELECT * FROM mysqltest_tmp_v"; + query= (char*)"SELECT * FROM mysqltest_tmp_v"; query_len = strlen(query); } dynstr_free(&query_str); - + } if (sp_protocol_enabled && @@ -3801,19 +3803,19 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) { /* Create the query as a stored procedure - Drop first since sp can exist from a failed mysqltest run - */ + Drop first since sp can exist from a failed mysqltest run + */ DYNAMIC_STRING query_str; - init_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); + 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, + 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", @@ -3823,8 +3825,8 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) else { sp_created= 1; - - query= (char*)"CALL mysqltest_tmp_sp()"; + + query= (char*)"CALL mysqltest_tmp_sp()"; query_len = strlen(query); } dynstr_free(&query_str); @@ -3833,7 +3835,7 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) /* Find out how to run this query - Always run with normal C API if it's not a complete + 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 @@ -3845,17 +3847,17 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) 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", + die("Failed to drop view: %d: %s", mysql_errno(mysql), mysql_error(mysql)); } @@ -3871,7 +3873,7 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) else if (command->record_file[0]) { /* - The output from _this_ query should be checked against an already + The output from _this_ query should be checked against an already existing file which has been specified using --require or --result */ check_result(ds, command->record_file, command->require_file); @@ -3891,7 +3893,7 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) static char *re_eprint(int err) { static char epbuf[100]; - size_t len= my_regerror(REG_ITOA|err, (my_regex_t *)NULL, + size_t len= my_regerror(REG_ITOA|err, (my_regex_t *)NULL, epbuf, sizeof(epbuf)); assert(len <= sizeof(epbuf)); return(epbuf); @@ -3905,15 +3907,15 @@ static void init_re_comp(my_regex_t *re, const char* str) { char erbuf[100]; int len= my_regerror(err, re, erbuf, sizeof(erbuf)); - die("error %s, %d/%d `%s'\n", + 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 + /* + Filter for queries that can be run using the MySQL Prepared Statements C API */ const char *ps_re_str = @@ -3930,13 +3932,13 @@ static void init_re(void) "[[:space:]]*UPDATE[[:space:]]+MULTI[[:space:]]|" "[[:space:]]*INSERT[[:space:]]+SELECT[[:space:]])"; - /* - Filter for queries that can be run using the + /* + 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 = @@ -3958,7 +3960,7 @@ static int match_re(my_regex_t *re, char *str) else if (err == REG_NOMATCH) return 0; - { + { char erbuf[100]; int len= my_regerror(err, re, erbuf, sizeof(erbuf)); die("error %s, %d/%d `%s'\n", @@ -4093,7 +4095,7 @@ static void init_var_hash(MYSQL *mysql) { VAR *v; DBUG_ENTER("init_var_hash"); - if (hash_init(&var_hash, charset_info, + if (hash_init(&var_hash, charset_info, 1024, 0, 0, get_var_key, var_free, MYF(0))) die("Variable hash initialization failed"); my_hash_insert(&var_hash, (byte*) var_init(0,"BIG_TEST", 0, @@ -4139,7 +4141,7 @@ int main(int argc, char **argv) cur_block= block_stack; cur_block->ok= TRUE; /* Outer block should always be executed */ cur_block->cmd= cmd_none; - + init_dynamic_string(&ds_res, "", 0, 65536); parse_args(argc, argv); @@ -4486,8 +4488,8 @@ int main(int argc, char **argv) /* No result_file to compare with, print the result to stdout */ printf("%s", ds_res.str); } - } - else + } + else { /* The test didn't produce any output */ } @@ -5440,7 +5442,7 @@ static char *subst_env_var(const char *str) */ #undef popen /* Remove wrapper */ -#ifdef __WIN__ +#ifdef __WIN__ #define popen _popen /* redefine for windows */ #endif From a6031b6425a8ae7f687c12b56913dc07ab793d39 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Fri, 4 Nov 2005 12:15:49 +0100 Subject: [PATCH 05/19] Formatting improved --- client/mysqltest.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 04ad33bb8bc..224985227cd 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -2912,15 +2912,6 @@ int parse_args(int argc, char **argv) return 0; } -char* safe_str_append(char *buf, const char *str, int size) -{ - int i,c ; - for (i = 0; (c = *str++) && i < size - 1; i++) - *buf++ = c; - *buf = 0; - return buf; -} - /* Write the content of str into file @@ -2931,6 +2922,7 @@ char* safe_str_append(char *buf, const char *str, int size) str - content to write to file size - size of content witten to file */ + static void str_to_file(const char *fname, char *str, int size) { int fd; @@ -2938,11 +2930,11 @@ static void str_to_file(const char *fname, char *str, int size) if (!test_if_hard_path(fname)) { strxmov(buff, opt_basedir, fname, NullS); - fname=buff; + fname= buff; } fn_format(buff,fname,"","",4); - if ((fd = my_open(buff, O_WRONLY | O_CREAT | O_TRUNC, + if ((fd= my_open(buff, O_WRONLY | O_CREAT | O_TRUNC, MYF(MY_WME | MY_FFNF))) < 0) die("Could not open %s: errno = %d", buff, errno); if (my_write(fd, (byte*)str, size, MYF(MY_WME|MY_FNABP))) @@ -2950,6 +2942,7 @@ static void str_to_file(const char *fname, char *str, int size) my_close(fd, MYF(0)); } + void dump_result_to_reject_file(const char *record_file, char *buf, int size) { char reject_file[FN_REFLEN]; @@ -2972,6 +2965,7 @@ static void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val, dynstr_append_mem(ds, val, len); } + /* Append zero-terminated string to ds, with optional replace */ static void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val) @@ -3036,8 +3030,8 @@ static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res) with '\t'. Values may be converted with 'replace_column' */ -static void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT* stmt, - MYSQL_FIELD* field, uint num_fields) +static void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt, + MYSQL_FIELD *field, uint num_fields) { MYSQL_BIND *bind; my_bool *is_null; @@ -3198,12 +3192,13 @@ static void append_metadata(DYNAMIC_STRING *ds, } } + /* Append affected row count and other info to output */ -static void append_info(DYNAMIC_STRING* ds, ulong affected_rows, - const char* info) +static void append_info(DYNAMIC_STRING *ds, ulong affected_rows, + const char *info) { char buf[40]; sprintf(buf,"affected rows: %lu\n", affected_rows); @@ -3220,8 +3215,9 @@ static void append_info(DYNAMIC_STRING* ds, ulong affected_rows, /* Display the table headings with the names tab separated */ -static void append_table_headings(DYNAMIC_STRING* ds, - MYSQL_FIELD* field, + +static void append_table_headings(DYNAMIC_STRING *ds, + MYSQL_FIELD *field, uint num_fields) { uint col_idx; From 600a74b0d404e98103c4ddf5a9019e04512f0dcc Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Tue, 6 Dec 2005 21:28:13 +0100 Subject: [PATCH 06/19] WL#2930 - Updated after review --- client/mysqltest.c | 138 +++++++++++++++++--------- mysql-test/include/have_multi_ndb.inc | 8 +- mysql-test/r/init_file.result | 1 + mysql-test/r/mysql_client_test.result | 1 + mysql-test/r/mysqltest.result | 4 + mysql-test/t/init_file.test | 1 + mysql-test/t/mysql_client_test.test | 2 + mysql-test/t/mysqltest.test | 54 +++++++--- 8 files changed, 146 insertions(+), 63 deletions(-) create mode 100644 mysql-test/r/init_file.result create mode 100644 mysql-test/r/mysql_client_test.result diff --git a/client/mysqltest.c b/client/mysqltest.c index 224985227cd..91791145db5 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -628,6 +628,10 @@ static void die(const char *fmt, ...) va_end(args); free_used_memory(); my_end(MY_CHECK_ERROR); + + if (!silent) + printf("not ok\n"); + exit(1); } @@ -3050,11 +3054,7 @@ static void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt, for (col_idx= 0; col_idx < num_fields; col_idx++) { /* Allocate data for output */ - /* - FIXME it may be a bug that for non string/blob types - 'max_length' is 0, should try out 'length' in that case - */ - uint max_length= max(field[col_idx].max_length + 1, 1024); + uint max_length= field[col_idx].max_length + 1; char *str_data= (char *) my_malloc(max_length, MYF(MY_WME | MY_FAE)); bind[col_idx].buffer_type= MYSQL_TYPE_STRING; @@ -3062,6 +3062,11 @@ static void append_stmt_result(DYNAMIC_STRING *ds, MYSQL_STMT *stmt, bind[col_idx].buffer_length= max_length; bind[col_idx].is_null= &is_null[col_idx]; bind[col_idx].length= &length[col_idx]; + + DBUG_PRINT("bind", ("col[%d]: buffer_type: %d, buffer_length: %d", + col_idx, + bind[col_idx].buffer_type, + bind[col_idx].buffer_length)); } /* Fill in the data into the structures created above */ @@ -3197,11 +3202,11 @@ static void append_metadata(DYNAMIC_STRING *ds, Append affected row count and other info to output */ -static void append_info(DYNAMIC_STRING *ds, ulong affected_rows, +static void append_info(DYNAMIC_STRING *ds, ulonglong affected_rows, const char *info) { char buf[40]; - sprintf(buf,"affected rows: %lu\n", affected_rows); + sprintf(buf,"affected rows: %llu\n", affected_rows); dynstr_append(ds, buf); if (info) { @@ -3231,17 +3236,20 @@ static void append_table_headings(DYNAMIC_STRING *ds, } /* - Fetch warnings from server and append to output + Fetch warnings from server and append to ds + + RETURN VALUE + Number of warnings appended to ds */ -static void append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql) +static int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql) { uint count; MYSQL_RES *warn_res; DBUG_ENTER("append_warnings"); if (!(count= mysql_warning_count(mysql))) - DBUG_VOID_RETURN; + DBUG_RETURN(0); /* If one day we will support execution of multi-statements @@ -3257,14 +3265,14 @@ static void append_warnings(DYNAMIC_STRING *ds, MYSQL* 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); - DBUG_VOID_RETURN; + DBUG_RETURN(count); } + /* Run query using MySQL C API @@ -3287,6 +3295,7 @@ static void run_query_normal(MYSQL *mysql, struct st_query *command, { MYSQL_RES *res= 0; int err= 0, counter= 0; + DYNAMIC_STRING ds_warnings; DBUG_ENTER("run_query_normal"); DBUG_PRINT("enter",("flags: %d", flags)); DBUG_PRINT("enter", ("query: '%-.60s'", query)); @@ -3334,7 +3343,7 @@ static void run_query_normal(MYSQL *mysql, struct st_query *command, if (!disable_result_log) { - ulong affected_rows; /* Ok to be undef if 'disable_info' is set */ + ulonglong affected_rows; /* Ok to be undef if 'disable_info' is set */ LINT_INIT(affected_rows); if (res) @@ -3356,7 +3365,7 @@ static void run_query_normal(MYSQL *mysql, struct st_query *command, query to find the warnings */ if (!disable_info) - affected_rows= (ulong)mysql_affected_rows(mysql); + affected_rows= mysql_affected_rows(mysql); /* Add all warnings to the result. We can't do this if we are in @@ -3364,7 +3373,15 @@ static void run_query_normal(MYSQL *mysql, struct st_query *command, this will break protocol. */ if (!disable_warnings && !mysql_more_results(mysql)) - append_warnings(ds, mysql); + { + init_dynamic_string(&ds_warnings, NULL, 0, 256); + if (append_warnings(&ds_warnings, mysql)) + { + dynstr_append_mem(ds, "Warnings:\n", 10); + dynstr_append_mem(ds, ds_warnings.str, ds_warnings.length); + } + dynstr_free(&ds_warnings); + } if (!disable_info) append_info(ds, affected_rows, mysql_info(mysql)); @@ -3542,6 +3559,7 @@ 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; + DYNAMIC_STRING ds_execute_warnings; DBUG_ENTER("run_query_stmt"); DBUG_PRINT("query", ("'%-.60s'", query)); @@ -3562,6 +3580,10 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, { handle_error(query, command, mysql_stmt_errno(stmt), mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds); +#ifndef BUG15518_FIXED + mysql_stmt_close(stmt); + cur_con->stmt= NULL; +#endif goto end; } @@ -3569,10 +3591,10 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, 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); + init_dynamic_string(&ds_prepare_warnings, NULL, 0, 256); + init_dynamic_string(&ds_execute_warnings, NULL, 0, 256); append_warnings(&ds_prepare_warnings, mysql); } @@ -3588,7 +3610,7 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, */ if (cursor_protocol_enabled) { - unsigned long type= CURSOR_TYPE_READ_ONLY; + ulong 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)); @@ -3654,25 +3676,36 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, mysql_free_result(res); /* Free normal result set with meta data */ + /* Clear prepare warnings */ + dynstr_set(&ds_prepare_warnings, NULL); } 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); + { + /* Get the warnings from execute */ + + /* Append warnings to ds - if there are any */ + if (append_warnings(&ds_execute_warnings, mysql) || + ds_prepare_warnings.length) + { + dynstr_append_mem(ds, "Warnings:\n", 10); + if (ds_prepare_warnings.length) + dynstr_append_mem(ds, ds_prepare_warnings.str, + ds_prepare_warnings.length); + if (ds_execute_warnings.length) + dynstr_append_mem(ds, ds_execute_warnings.str, + ds_execute_warnings.length); + } + } if (!disable_info) - append_info(ds, (ulong)mysql_affected_rows(mysql), mysql_info(mysql)); + append_info(ds, mysql_affected_rows(mysql), mysql_info(mysql)); } @@ -3680,7 +3713,10 @@ end: free_replace(); if (!disable_warnings) + { dynstr_free(&ds_prepare_warnings); + dynstr_free(&ds_execute_warnings); + } /* We save the return code (mysql_stmt_errno(stmt)) from the last call sent @@ -3778,6 +3814,10 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) DBUG_PRINT("view_create_error", ("Failed to create view '%s': %d: %s", query_str.str, mysql_errno(mysql), mysql_error(mysql))); + + /* Log error to create view */ + verbose_msg("Failed to create view '%s' %d: %s", query_str.str, + mysql_errno(mysql), mysql_error(mysql)); } else { @@ -3817,6 +3857,11 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) DBUG_PRINT("sp_create_error", ("Failed to create sp '%s': %d: %s", query_str.str, mysql_errno(mysql), mysql_error(mysql))); + + /* Log error to create sp */ + verbose_msg("Failed to create sp '%s' %d: %s", query_str.str, + mysql_errno(mysql), mysql_error(mysql)); + } else { @@ -4446,24 +4491,10 @@ int main(int argc, char **argv) } /* - The whole test has been executed sucessfully + The whole test has been executed _sucessfully_ Time to compare result or save it to record file The entire output from test is now kept in ds_res - */ - - if (!query_executed && result_file && my_stat(result_file, &res_info, 0)) - { - /* - my_stat() successful on result file. Check if we have not run a - single query, but we do have a result file that contains data. - Note that we don't care, if my_stat() fails. For example for - non-existing or non-readable file we assume it's fine to have - no query output from the test file, e.g. regarded as no error. - */ - if (res_info.st_size) - die("No queries executed but result file found!"); - } - + */ if (ds_res.length) { if (result_file) @@ -4475,20 +4506,37 @@ int main(int argc, char **argv) } else { - /* Check that the output from test is equal to result file */ + /* Check that the output from test is equal to result file + - detect missing result file + - detect zero size result file + */ check_result(&ds_res, result_file, 0); } } else { - /* No result_file to compare with, print the result to stdout */ + /* No result_file specified to compare with, print to stdout */ printf("%s", ds_res.str); } } else { - /* The test didn't produce any output */ + die("The test didn't produce any output"); } + + if (!query_executed && result_file && my_stat(result_file, &res_info, 0)) + { + /* + my_stat() successful on result file. Check if we have not run a + single query, but we do have a result file that contains data. + Note that we don't care, if my_stat() fails. For example for + non-existing or non-readable file we assume it's fine to have + no query output from the test file, e.g. regarded as no error. + */ + die("No queries executed but result file found!"); + } + + dynstr_free(&ds_res); if (!got_end_timer) diff --git a/mysql-test/include/have_multi_ndb.inc b/mysql-test/include/have_multi_ndb.inc index ec1a93311fb..45a551274f7 100644 --- a/mysql-test/include/have_multi_ndb.inc +++ b/mysql-test/include/have_multi_ndb.inc @@ -9,8 +9,8 @@ disable_query_log; drop table if exists t1, t2; --enable_warnings flush tables; -@r/have_ndb.require show variables like "have_ndbcluster"; -# @r/server_id.require show variables like "server_id"; +--require r/have_ndb.require +show variables like "have_ndbcluster"; enable_query_log; # Check that server2 has NDB support @@ -20,8 +20,8 @@ disable_query_log; drop table if exists t1, t2; --enable_warnings flush tables; -@r/have_ndb.require show variables like "have_ndbcluster"; -# @r/server_id1.require show variables like "server_id"; +--require r/have_ndb.require +show variables like "have_ndbcluster"; enable_query_log; # Set the default connection to 'server1' diff --git a/mysql-test/r/init_file.result b/mysql-test/r/init_file.result new file mode 100644 index 00000000000..9766475a418 --- /dev/null +++ b/mysql-test/r/init_file.result @@ -0,0 +1 @@ +ok diff --git a/mysql-test/r/mysql_client_test.result b/mysql-test/r/mysql_client_test.result new file mode 100644 index 00000000000..9766475a418 --- /dev/null +++ b/mysql-test/r/mysql_client_test.result @@ -0,0 +1 @@ +ok diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index df4c2091f3b..22c7fb02f00 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -331,6 +331,7 @@ mysqltest: At line 1: Wrong number of arguments to replace_result in 'replace_re mysqltest: At line 1: Wrong number of arguments to replace_result in 'replace_result a;' mysqltest: At line 1: Wrong number of arguments to replace_result in 'replace_result a' mysqltest: At line 1: Wrong number of arguments to replace_result in 'replace_result a ' +OK mysqltest: At line 1: Wrong number of arguments to replace_result in 'replace_result a b c' mysqltest: At line 1: Wrong number of arguments to replace_result in 'replace_result a b c ' select "a" as col1, "c" as col2; @@ -356,6 +357,7 @@ mysqltest: At line 1: Missing connection db mysqltest: At line 1: Could not open connection 'con2': Unknown database 'illegal_db' mysqltest: At line 1: Illegal argument for port: 'illegal_port' mysqltest: At line 1: Illegal option to connect: SMTP +OK mysqltest: In included file "./var/tmp/con.sql": At line 7: Connection limit exhausted - increase MAX_CONS in mysqltest.c mysqltest: In included file "./var/tmp/con.sql": At line 3: connection 'test_con1' not found in connection pool mysqltest: In included file "./var/tmp/con.sql": At line 2: Connection test_con1 already exists @@ -394,3 +396,5 @@ root@localhost -------------------------------------------------------------------------------- this will be executed this will be executed +mysqltest: Result length mismatch +mysqltest: The test didn't produce any output diff --git a/mysql-test/t/init_file.test b/mysql-test/t/init_file.test index de6aca455bd..8b4b788777b 100644 --- a/mysql-test/t/init_file.test +++ b/mysql-test/t/init_file.test @@ -7,3 +7,4 @@ # # End of 4.1 tests +echo ok; diff --git a/mysql-test/t/mysql_client_test.test b/mysql-test/t/mysql_client_test.test index 66b57dd5fb7..9cacb008d09 100644 --- a/mysql-test/t/mysql_client_test.test +++ b/mysql-test/t/mysql_client_test.test @@ -10,3 +10,5 @@ --exec $MYSQL_CLIENT_TEST --getopt-ll-test=25600M # End of 4.1 tests +echo ok; + diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index 26e25af2a8d..f229b5cdc1d 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -368,10 +368,10 @@ select 3 from t1 ; # Missing delimiter until eof # The comment will be "sucked into" the sleep command since # delimiter is missing ---system echo "sleep 7" > var/log/mysqltest.sql ---system echo "# Another comment" >> var/log/mysqltest.sql +--system echo "sleep 7" > var/tmp/mysqltest.sql +--system echo "# Another comment" >> var/tmp/mysqltest.sql --error 1 ---exec $MYSQL_TEST < var/log/mysqltest.sql 2>&1 +--exec $MYSQL_TEST < var/tmp/mysqltest.sql 2>&1 # # Extra delimiter @@ -737,20 +737,20 @@ while ($i) --error 1 --exec echo "{;" | $MYSQL_TEST 2>&1 ---system echo "while (0)" > var/log/mysqltest.sql ---system echo "echo hej;" >> var/log/mysqltest.sql +--system echo "while (0)" > var/tmp/mysqltest.sql +--system echo "echo hej;" >> var/tmp/mysqltest.sql --error 1 ---exec $MYSQL_TEST < var/log/mysqltest.sql 2>&1 +--exec $MYSQL_TEST < var/tmp/mysqltest.sql 2>&1 ---system echo "while (0)" > var/log/mysqltest.sql ---system echo "{echo hej;" >> var/log/mysqltest.sql +--system echo "while (0)" > var/tmp/mysqltest.sql +--system echo "{echo hej;" >> var/tmp/mysqltest.sql --error 1 ---exec $MYSQL_TEST < var/log/mysqltest.sql 2>&1 +--exec $MYSQL_TEST < var/tmp/mysqltest.sql 2>&1 ---system echo "while (0){" > var/log/mysqltest.sql ---system echo "echo hej;" >> var/log/mysqltest.sql +--system echo "while (0){" > var/tmp/mysqltest.sql +--system echo "echo hej;" >> var/tmp/mysqltest.sql --error 1 ---exec $MYSQL_TEST < var/log/mysqltest.sql 2>&1 +--exec $MYSQL_TEST < var/tmp/mysqltest.sql 2>&1 # ---------------------------------------------------------------------------- # Test error messages returned from comments starting with a command @@ -778,7 +778,7 @@ select "a" as col1, "c" as col2; --exec echo "replace_result a;" | $MYSQL_TEST 2>&1 --error 1 --exec echo "replace_result a ;" | $MYSQL_TEST 2>&1 ---exec echo "replace_result a b;" | $MYSQL_TEST 2>&1 +--exec echo "replace_result a b; echo OK;" | $MYSQL_TEST 2>&1 --error 1 --exec echo "--replace_result a b c" | $MYSQL_TEST 2>&1 --error 1 @@ -848,7 +848,7 @@ select "a" as col1, "c" as col2; --exec echo " disconnect test_con1; " >> var/tmp/con.sql --exec echo " dec \$i; " >> var/tmp/con.sql --exec echo "}" >> var/tmp/con.sql ---exec echo "source var/tmp/con.sql;" | $MYSQL_TEST 2>&1 +--exec echo "source var/tmp/con.sql; echo OK;" | $MYSQL_TEST 2>&1 # Repeat connect/disconnect, exceed max number of connections --exec echo "let \$i=200;" > var/tmp/con.sql @@ -954,3 +954,29 @@ select "this will not be executed"; --enable_parsing select "this will be executed"; --enable_query_log + +# +# Test zero length result file. Should not pass +# +--exec touch $MYSQL_TEST_DIR/var/tmp/zero_length_file.result +--exec echo "echo ok;" > $MYSQL_TEST_DIR/var/tmp/query.sql +--error 1 +--exec $MYSQL_TEST -x var/tmp/query.sql -R var/tmp/zero_length_file.result 2>&1 +# +# Test that a test file that does not generate any output fails. +# +--exec echo "let \$i= 1;" > $MYSQL_TEST_DIR/var/tmp/query.sql +--error 1 +--exec $MYSQL_TEST -x var/tmp/query.sql 2>&1 + +# +# Test that mysqltest fails when there are no queries executed +# but a result file exist +# NOTE! This will never happen as long as it's not allowed to have +# test files that does not produce any output +#--exec echo "something" > $MYSQL_TEST_DIR/var/tmp/result_file.result +#--exec echo "let \$i= 1;" > $MYSQL_TEST_DIR/var/tmp/query.sql +#--error 1 +#--exec $MYSQL_TEST -x var/tmp/query.sql -R var/tmp/result_file.result 2>&1 + + From 60806003fb154b2b217ed6316bc0bc7901afc462 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Tue, 6 Dec 2005 21:34:35 +0100 Subject: [PATCH 07/19] Improved valgrinding of mysqltest --- mysql-test/mysql-test-run.sh | 51 ++++++++++++++++++++++++------------ 1 file changed, 34 insertions(+), 17 deletions(-) diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 2133043a587..517ce0420e6 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -110,6 +110,20 @@ wait_for_pid() #$WAIT_PID pid $SLEEP_TIME_FOR_DELETE } +# Check that valgrind is installed +find_valgrind() +{ + FIND_VALGRIND=`which valgrind` # this will print an error if not found + # Give good warning to the user and stop + if [ -z "$FIND_VALGRIND" ] ; then + $ECHO "You need to have the 'valgrind' program in your PATH to run mysql-test-run with option --valgrind. Valgrind's home page is http://valgrind.kde.org ." + exit 1 + fi + # >=2.1.2 requires the --tool option, some versions write to stdout, some to stderr + valgrind --help 2>&1 | grep "\-\-tool" > /dev/null && FIND_VALGRIND="$FIND_VALGRIND --tool=memcheck" + FIND_VALGRIND="$FIND_VALGRIND --alignment=8 --leak-check=yes --num-callers=16 --suppressions=$CWD/valgrind.supp" +} + # No paths below as we can't be sure where the program is! SED=sed @@ -255,7 +269,6 @@ DO_GDB="" MANUAL_GDB="" DO_DDD="" DO_CLIENT_GDB="" -DO_VALGRIND_MYSQL_TEST="" SLEEP_TIME_AFTER_RESTART=1 SLEEP_TIME_FOR_DELETE=10 SLEEP_TIME_FOR_FIRST_MASTER=400 # Enough time to create innodb tables @@ -470,15 +483,8 @@ while test $# -gt 0; do EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --gdb" ;; --valgrind | --valgrind-all) - VALGRIND=`which valgrind` # this will print an error if not found - # Give good warning to the user and stop - if [ -z "$VALGRIND" ] ; then - $ECHO "You need to have the 'valgrind' program in your PATH to run mysql-test-run with option --valgrind. Valgrind's home page is http://valgrind.kde.org ." - exit 1 - fi - # >=2.1.2 requires the --tool option, some versions write to stdout, some to stderr - valgrind --help 2>&1 | grep "\-\-tool" > /dev/null && VALGRIND="$VALGRIND --tool=memcheck" - VALGRIND="$VALGRIND --alignment=8 --leak-check=yes --num-callers=16 --suppressions=$CWD/valgrind.supp" + find_valgrind; + VALGRIND=$FIND_VALGRIND EXTRA_MASTER_MYSQLD_OPT="$EXTRA_MASTER_MYSQLD_OPT --skip-safemalloc --skip-bdb" EXTRA_SLAVE_MYSQLD_OPT="$EXTRA_SLAVE_MYSQLD_OPT --skip-safemalloc --skip-bdb" SLEEP_TIME_AFTER_RESTART=10 @@ -493,8 +499,13 @@ while test $# -gt 0; do TMP=`$ECHO "$1" | $SED -e "s;--valgrind-options=;;"` VALGRIND="$VALGRIND $TMP" ;; - --valgrind-mysqltest) - DO_VALGRIND_MYSQL_TEST=1 + --valgrind-mysqltest | --valgrind-mysqltest-all) + find_valgrind; + VALGRIND_MYSQLTEST=$FIND_VALGRIND + if test "$1" = "--valgrind-mysqltest-all" + then + VALGRIND_MYSQLTEST="$VALGRIND_MYSQLTEST -v --show-reachable=yes" + fi ;; --skip-ndbcluster | --skip-ndb) USE_NDBCLUSTER="" @@ -599,7 +610,7 @@ DASH72=`$ECHO '-------------------------------------------------------'|$CUT -c if [ x$SOURCE_DIST = x1 ] ; then if [ "x$USE_EMBEDDED_SERVER" = "x1" ] ; then if [ -f "$BASEDIR/libmysqld/examples/mysqltest_embedded" ] ; then - MYSQL_TEST="$VALGRIND $BASEDIR/libmysqld/examples/mysqltest_embedded" + MYSQL_TEST="$BASEDIR/libmysqld/examples/mysqltest_embedded" else echo "Fatal error: Cannot find embedded server 'mysqltest_embedded'" 1>&2 exit 1 @@ -733,7 +744,7 @@ else fi if [ "x$USE_EMBEDDED_SERVER" = "x1" ] ; then if [ -f "$CLIENT_BINDIR/mysqltest_embedded" ] ; then - MYSQL_TEST="$VALGRIND $CLIENT_BINDIR/mysqltest_embedded" + MYSQL_TEST="$CLIENT_BINDIR/mysqltest_embedded" else echo "Fatal error: Cannot find embedded server 'mysqltest_embedded'" 1>&2 exit 1 @@ -744,7 +755,7 @@ else MYSQL_CLIENT_TEST="$CLIENT_BINDIR/mysql_client_test_embedded" fi else - MYSQL_TEST="$VALGRIND_MYSQLTEST $CLIENT_BINDIR/mysqltest" + MYSQL_TEST="$CLIENT_BINDIR/mysqltest" MYSQL_CLIENT_TEST="$CLIENT_BINDIR/mysql_client_test" fi fi @@ -759,8 +770,9 @@ then SLAVE_MYSQLD=$MYSQLD fi -if [ x$DO_VALGRIND_MYSQL_TEST = x1 ] ; then - MYSQL_TEST="$VALGRIND $MYSQL_TEST" +# If mysqltest should be valgrinded, add valgrind and options to MYSQL_TEST +if ! [ -z "$VALGRIND_MYSQLTEST" ] ; then + MYSQL_TEST="$VALGRIND_MYSQLTEST $MYSQL_TEST" fi # If we should run all tests cases, we will use a local server for that @@ -829,6 +841,7 @@ GPROF_DIR=$MYSQL_TMP_DIR/gprof GPROF_MASTER=$GPROF_DIR/master.gprof GPROF_SLAVE=$GPROF_DIR/slave.gprof TIMEFILE="$MYSQL_TEST_DIR/var/log/mysqltest-time" +MYSQLTEST_LOG="$MYSQL_TEST_DIR/var/log/mysqltest.log" if [ -n "$DO_CLIENT_GDB" -o -n "$DO_GDB" ] ; then XTERM=`which xterm` fi @@ -1774,6 +1787,10 @@ run_testcase () res=$? + # Save the testcase log to mysqltest log file + echo "CURRENT_TEST: $tname" >> $MYSQLTEST_LOG + cat $TIMEFILE >> $MYSQLTEST_LOG + pname=`$ECHO "$tname "|$CUT -c 1-24` RES="$pname" From d80516aa96d2249134f0d78fce45e08abfb70048 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Wed, 7 Dec 2005 14:52:37 +0100 Subject: [PATCH 08/19] Fix memory leak --- client/mysqltest.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/mysqltest.c b/client/mysqltest.c index 91791145db5..285aa0fe033 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -4015,6 +4015,7 @@ static void free_re(void) my_regfree(&ps_re); my_regfree(&sp_re); my_regfree(&view_re); + my_regex_end(); } /****************************************************************************/ From 58d0d5387ec777e7bb2e7ec8dac93e98ab3f496c Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Wed, 7 Dec 2005 14:54:06 +0100 Subject: [PATCH 09/19] valgrind for mysqltest --- mysql-test/mysql-test-run.sh | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 517ce0420e6..3a8aa8614a2 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -770,11 +770,6 @@ then SLAVE_MYSQLD=$MYSQLD fi -# If mysqltest should be valgrinded, add valgrind and options to MYSQL_TEST -if ! [ -z "$VALGRIND_MYSQLTEST" ] ; then - MYSQL_TEST="$VALGRIND_MYSQLTEST $MYSQL_TEST" -fi - # If we should run all tests cases, we will use a local server for that if [ -z "$1" -a -z "$DO_STRESS" ] @@ -831,7 +826,10 @@ if [ x$USE_TIMER = x1 ] ; then fi MYSQL_TEST_BIN=$MYSQL_TEST MYSQL_TEST="$MYSQL_TEST $MYSQL_TEST_ARGS" + +# Export MYSQL_TEST variable for use from .test files export MYSQL_TEST + GDB_CLIENT_INIT=$MYSQL_TMP_DIR/gdbinit.client GDB_MASTER_INIT=$MYSQL_TMP_DIR/gdbinit.master GDB_SLAVE_INIT=$MYSQL_TMP_DIR/gdbinit.slave @@ -1780,7 +1778,7 @@ run_testcase () $RM -f r/$tname.*reject mysql_test_args="-R $result_file $EXTRA_MYSQL_TEST_OPT" if [ -z "$DO_CLIENT_GDB" ] ; then - `$MYSQL_TEST $mysql_test_args < $tf 2> $TIMEFILE`; + `$VALGRIND_MYSQLTEST $MYSQL_TEST $mysql_test_args < $tf 2> $TIMEFILE`; else do_gdb_test "$mysql_test_args" "$tf" fi From fe2ec19039ddc7e35824967e28feb0e3a648f294 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Thu, 8 Dec 2005 16:48:37 +0100 Subject: [PATCH 10/19] WL#2930 mysqltest++ - Updated after valgrinding --- client/mysqltest.c | 22 +++++++++++++--------- mysql-test/mysql-test-run.sh | 12 ++++++++++++ 2 files changed, 25 insertions(+), 9 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 285aa0fe033..60dfb7a48a7 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -2676,6 +2676,7 @@ int read_query(struct st_query** q_ptr) end: while (*p && my_isspace(charset_info, *p)) p++; + if (!(q->query_buf= q->query= my_strdup(p, MYF(MY_WME)))) die(NullS); @@ -3573,6 +3574,13 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, cur_con->stmt= stmt; } + /* Init dynamic strings for warnings */ + if (!disable_warnings) + { + init_dynamic_string(&ds_prepare_warnings, NULL, 0, 256); + init_dynamic_string(&ds_execute_warnings, NULL, 0, 256); + } + /* Prepare the query */ @@ -3580,10 +3588,6 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, { handle_error(query, command, mysql_stmt_errno(stmt), mysql_stmt_error(stmt), mysql_stmt_sqlstate(stmt), ds); -#ifndef BUG15518_FIXED - mysql_stmt_close(stmt); - cur_con->stmt= NULL; -#endif goto end; } @@ -3592,12 +3596,7 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, separate string */ if (!disable_warnings) - { - init_dynamic_string(&ds_prepare_warnings, NULL, 0, 256); - init_dynamic_string(&ds_execute_warnings, NULL, 0, 256); append_warnings(&ds_prepare_warnings, mysql); - } - /* No need to call mysql_stmt_bind_param() because we have no @@ -3724,6 +3723,10 @@ end: variable then can be used from the test case itself. */ var_set_errno(mysql_stmt_errno(stmt)); +#ifndef BUG15518_FIXED + mysql_stmt_close(stmt); + cur_con->stmt= NULL; +#endif DBUG_VOID_RETURN; } @@ -4050,6 +4053,7 @@ void get_query_type(struct st_query* q) q->type= Q_COMMENT; } else if (q->type == Q_COMMENT_WITH_COMMAND && + q->first_word_len && q->query[q->first_word_len-1] == ';') { /* diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 3a8aa8614a2..3454873bca4 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -1002,6 +1002,18 @@ report_stats () { echo "WARNING: Got errors/warnings while running tests. Please examine" echo "$MY_LOG_DIR/warnings for details." fi + + fi # USE_RUNNING_SERVER + + # Check valgrind errors from mysqltest + if [ ! -z "$VALGRIND_MYSQLTEST" ] + then + if $GREP "ERROR SUMMARY" $MYSQLTEST_LOG | $GREP -v "0 errors" > /dev/null + then + $ECHO "Valgrind detected errors!" + $GREP "ERROR SUMMARY" $MYSQLTEST_LOG | $GREP -v "0 errors" + $ECHO "See $MYSQLTEST_LOG" + fi fi } From 8e199d9ade5d6edf41788162695e5d891a3f8d44 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Fri, 9 Dec 2005 17:52:29 +0100 Subject: [PATCH 11/19] Made it easier to valgrind mysqltest --- mysql-test/mysql-test-run.pl | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index a1d051846ee..17cc470f1c3 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -151,6 +151,7 @@ our $path_client_bindir; our $path_language; our $path_timefile; our $path_manager_log; # Used by mysqldadmin +our $path_mysqltest_log; our $path_slave_load_tmpdir; # What is this?! our $path_my_basedir; our $opt_vardir; # A path but set directly on cmd line @@ -270,6 +271,7 @@ our $opt_user; our $opt_user_test; our $opt_valgrind; +our $opt_valgrind_mysqld; our $opt_valgrind_mysqltest; our $opt_valgrind_all; our $opt_valgrind_options; @@ -742,6 +744,7 @@ sub command_line_setup () { # "somestring" option is name/path of valgrind executable # Take executable path from any of them, if any + $opt_valgrind_mysqld= $opt_valgrind; $opt_valgrind= $opt_valgrind_mysqltest if $opt_valgrind_mysqltest; $opt_valgrind= $opt_valgrind_all if $opt_valgrind_all; @@ -885,6 +888,7 @@ sub command_line_setup () { } $path_timefile= "$opt_vardir/log/mysqltest-time"; + $path_mysqltest_log= "$opt_vardir/log/mysqltest.log"; } @@ -929,7 +933,19 @@ sub executable_setup () { } else { - $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest"); + if ( $opt_valgrind_mysqltest ) + { + # client/mysqltest might be a libtool .sh script, so look for real exe + # to avoid valgrinding bash ;) + $exe_mysqltest= + mtr_exe_exists("$path_client_bindir/.libs/lt-mysqltest", + "$path_client_bindir/.libs/mysqltest", + "$path_client_bindir/mysqltest"); + } + else + { + $exe_mysqltest= mtr_exe_exists("$path_client_bindir/mysqltest"); + } $exe_mysql_client_test= mtr_exe_exists("$glob_basedir/tests/mysql_client_test", "/usr/bin/false"); @@ -1859,6 +1875,11 @@ sub run_testcase ($) { } report_failure_and_restart($tinfo); } + # Save info from this testcase run to mysqltest.log + mtr_tofile($path_mysqltest_log,"CURRENT TEST $tname\n"); + my $testcase_log= mtr_fromfile($path_timefile); + mtr_tofile($path_mysqltest_log, + $testcase_log); } # ---------------------------------------------------------------------- @@ -2019,7 +2040,7 @@ sub mysqld_arguments ($$$$$) { mtr_add_arg($args, "%s--language=%s", $prefix, $path_language); mtr_add_arg($args, "%s--tmpdir=$opt_tmpdir", $prefix); - if ( defined $opt_valgrind ) + if ( defined $opt_valgrind_mysqld ) { mtr_add_arg($args, "%s--skip-safemalloc", $prefix); mtr_add_arg($args, "%s--skip-bdb", $prefix); @@ -2245,7 +2266,7 @@ sub mysqld_start ($$$$) { mtr_init_args(\$args); - if ( defined $opt_valgrind ) + if ( defined $opt_valgrind_mysqld ) { valgrind_arguments($args, \$exe); } @@ -2699,6 +2720,7 @@ sub valgrind_arguments { mtr_add_arg($args, split(' ', $opt_valgrind_options)); } + mtr_add_arg($args, $$exe); $$exe= $opt_valgrind || "valgrind"; @@ -2778,9 +2800,8 @@ Options for coverage, profiling etc gcov FIXME gprof FIXME - valgrind[=EXE] Run the "mysqltest" executable as well as the "mysqld" - server using valgrind, optionally specifying the - executable path/name + valgrind[=EXE] Run the "mysqld" server using valgrind, optionally + specifying the executable path/name valgrind-mysqltest[=EXE] In addition, run the "mysqltest" executable with valgrind valgrind-all[=EXE] Adds verbose flag, and --show-reachable to valgrind valgrind-options=ARGS Extra options to give valgrind From 8aeb3a1fbacd62126e94b02d44229683666f5a49 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Fri, 9 Dec 2005 18:51:45 +0100 Subject: [PATCH 12/19] Fix warnings for running with --view_protocol --- client/mysqltest.c | 35 +++++++++++++++++++++++++---------- 1 file changed, 25 insertions(+), 10 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 60dfb7a48a7..b500c3dbe1a 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -3269,6 +3269,8 @@ static int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql) append_result(ds, warn_res); mysql_free_result(warn_res); + DBUG_PRINT("warnings", ("%s", ds->str)); + DBUG_RETURN(count); } @@ -3292,11 +3294,10 @@ static int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql) static void run_query_normal(MYSQL *mysql, struct st_query *command, int flags, char *query, int query_len, - DYNAMIC_STRING *ds) + DYNAMIC_STRING *ds, DYNAMIC_STRING *ds_warnings) { MYSQL_RES *res= 0; int err= 0, counter= 0; - DYNAMIC_STRING ds_warnings; DBUG_ENTER("run_query_normal"); DBUG_PRINT("enter",("flags: %d", flags)); DBUG_PRINT("enter", ("query: '%-.60s'", query)); @@ -3375,13 +3376,11 @@ static void run_query_normal(MYSQL *mysql, struct st_query *command, */ if (!disable_warnings && !mysql_more_results(mysql)) { - init_dynamic_string(&ds_warnings, NULL, 0, 256); - if (append_warnings(&ds_warnings, mysql)) + if (append_warnings(ds_warnings, mysql) || ds_warnings->length) { dynstr_append_mem(ds, "Warnings:\n", 10); - dynstr_append_mem(ds, ds_warnings.str, ds_warnings.length); + dynstr_append_mem(ds, ds_warnings->str, ds_warnings->length); } - dynstr_free(&ds_warnings); } if (!disable_info) @@ -3555,7 +3554,8 @@ static void handle_no_error(struct st_query *q) */ static void run_query_stmt(MYSQL *mysql, struct st_query *command, - char *query, int query_len, DYNAMIC_STRING *ds) + char *query, int query_len, DYNAMIC_STRING *ds, + DYNAMIC_STRING *ds_warnings) { MYSQL_RES *res= NULL; /* Note that here 'res' is meta data result set */ MYSQL_STMT *stmt; @@ -3691,9 +3691,13 @@ static void run_query_stmt(MYSQL *mysql, struct st_query *command, /* Append warnings to ds - if there are any */ if (append_warnings(&ds_execute_warnings, mysql) || - ds_prepare_warnings.length) + ds_prepare_warnings.length || + ds_warnings->length) { dynstr_append_mem(ds, "Warnings:\n", 10); + if (ds_warnings->length) + dynstr_append_mem(ds, ds_warnings->str, + ds_warnings->length); if (ds_prepare_warnings.length) dynstr_append_mem(ds, ds_prepare_warnings.str, ds_prepare_warnings.length); @@ -3749,12 +3753,15 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) { DYNAMIC_STRING *ds; DYNAMIC_STRING ds_result; + DYNAMIC_STRING ds_warnings; 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)); + init_dynamic_string(&ds_warnings, NULL, 0, 256); + /* Evaluate query if this is an eval command */ @@ -3830,6 +3837,12 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) view_created= 1; query= (char*)"SELECT * FROM mysqltest_tmp_v"; query_len = strlen(query); + + /* + Collect warnings from create of the view that should otherwise + have been produced when the SELECT was executed + */ + append_warnings(&ds_warnings, mysql); } dynstr_free(&query_str); @@ -3888,9 +3901,10 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) if (ps_protocol_enabled && complete_query && match_re(&ps_re, query)) - run_query_stmt(mysql, command, query, query_len, ds); + run_query_stmt(mysql, command, query, query_len, ds, &ds_warnings); else - run_query_normal(mysql, command, flags, query, query_len, ds); + run_query_normal(mysql, command, flags, query, query_len, + ds, &ds_warnings); if (sp_created) { @@ -3923,6 +3937,7 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) check_result(ds, command->record_file, command->require_file); } + dynstr_free(&ds_warnings); if (ds == &ds_result) dynstr_free(&ds_result); if (command->type == Q_EVAL) From 36c86a4df64a01df6cf6dab96415fee1429f3a90 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Tue, 13 Dec 2005 18:07:13 +0100 Subject: [PATCH 13/19] Fix tests after merge Straighten out and comment behaviour for --require and --result in run_query --- client/mysqltest.c | 32 ++++++++++++++++++-------------- mysql-test/r/mysqltest.result | 17 ++++++++--------- mysql-test/t/mysqltest.test | 18 +++++++++--------- 3 files changed, 35 insertions(+), 32 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 135fa370688..3f8b6582eb9 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -3925,22 +3925,26 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) mysql_errno(mysql), mysql_error(mysql)); } - if (record) + if (command->record_file[0]) { - /* Recording in progress */ - if (!command->record_file[0]) - die("Missing result file"); - /* Dump the output from _this_ query to the specified record_file */ - str_to_file(command->record_file, ds->str, ds->length); - } - else if (command->record_file[0]) - { - /* - The output from _this_ query should be checked against an already - existing file which has been specified using --require or --result - */ - check_result(ds, command->record_file, command->require_file); + /* A result file was specified for _this_ query */ + if (record) + { + /* + Recording in progress + Dump the output from _this_ query to the specified record_file + */ + str_to_file(command->record_file, ds->str, ds->length); + + } else { + + /* + The output from _this_ query should be checked against an already + existing file which has been specified using --require or --result + */ + check_result(ds, command->record_file, command->require_file); + } } dynstr_free(&ds_warnings); diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index 8ea3a48e948..2e78f468f93 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -396,12 +396,20 @@ root@localhost -------------------------------------------------------------------------------- this will be executed this will be executed +mysqltest: Result length mismatch +mysqltest: The test didn't produce any output +Failing multi statement query mysqltest: At line 3: query 'create table t1 (a int primary key); insert into t1 values (1); select 'select-me'; insertz 'error query'' failed: 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'insertz 'error query'' at line 1 drop table t1; +mysqltest: At line 3: query 'create table t1 (a int primary key); +insert into t1 values (1); +select 'select-me'; +insertz 'error query'' failed: 1064: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'insertz 'error query'' at line 1 drop table t1; +Multi statement using expected error create table t1 (a int primary key); insert into t1 values (1); select 'select-me'; @@ -410,13 +418,4 @@ select-me select-me ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'insertz error query' at line 1 drop table t1; -create table t1 (a int primary key); -insert into t1 values (1); -select 'select-me'; -insertz error query|||| -select-me -select-me -ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'insertz error query' at line 1 drop table t1; -mysqltest: Result length mismatch -mysqltest: The test didn't produce any output diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index 1d22705fb8e..132a6329178 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -984,7 +984,7 @@ select "this will be executed"; # non-1st queries # -# Failing multi statement query +echo Failing multi statement query; # PS does not support multi statement --exec echo "--disable_ps_protocol" > var/tmp/bug11731.sql --exec echo "delimiter ||||;" >> var/tmp/bug11731.sql @@ -999,14 +999,13 @@ select "this will be executed"; drop table t1; --error 1 ---exec $MYSQL_TEST --record -x $MYSQL_TEST_DIR/var/tmp/bug11731.sql -R $MYSQL_TEST_DIR/var/tmp/bug11731.out -# The .out file should be empty, cat will fail! ---error 1 ---exec cat $MYSQL_TEST_DIR/var/tmp/bug11731.out +--exec $MYSQL_TEST --record -x $MYSQL_TEST_DIR/var/tmp/bug11731.sql -R $MYSQL_TEST_DIR/var/tmp/bug11731.out 2>&1 +# The .out file should be non existent +--exec test ! -e $MYSQL_TEST_DIR/var/tmp/bug11731.out drop table t1; -# Using expected error +echo Multi statement using expected error; # PS does not support multi statement --exec echo "--disable_ps_protocol" > var/tmp/bug11731.sql --exec echo "delimiter ||||;" >> var/tmp/bug11731.sql @@ -1018,11 +1017,12 @@ drop table t1; --exec echo "delimiter ;||||" >> var/tmp/bug11731.sql # These two should work since the error is expected ---exec $MYSQL_TEST -x $MYSQL_TEST_DIR/var/tmp/bug11731.sql 2>&1 +--exec $MYSQL_TEST -x $MYSQL_TEST_DIR/var/tmp/bug11731.sql 2>&1 drop table t1; ---exec $MYSQL_TEST --record -x $MYSQL_TEST_DIR/var/tmp/bug11731.sql -R $MYSQL_TEST_DIR/var/tmp/bug11731.out ---exec cat $MYSQL_TEST_DIR/var/tmp/bug11731.out +--exec $MYSQL_TEST --record -x $MYSQL_TEST_DIR/var/tmp/bug11731.sql -R $MYSQL_TEST_DIR/var/tmp/bug11731.out 2>&1 +# The .out file should exist +--exec test -s $MYSQL_TEST_DIR/var/tmp/bug11731.out drop table t1; From b5d805b2d6e552c07257d5adf4da9737d3a343a3 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Tue, 13 Dec 2005 18:10:53 +0100 Subject: [PATCH 14/19] Remove confusing printout --- client/mysqltest.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 3f8b6582eb9..8938df1944f 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -3500,12 +3500,6 @@ static void handle_error(const char *query, struct st_query *q, q->query, err_sqlstate, q->expected_errno[0].code.sqlstate); } - /* - If we do not abort on error, failure to run the query does not fail the - whole test case. - */ - verbose_msg("query '%s' failed: %d: %s", q->query, err_errno, - err_error); DBUG_VOID_RETURN; } From b38a183d6278a2bf62e35aaa0325c844bdcf664e Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Tue, 13 Dec 2005 18:47:34 +0100 Subject: [PATCH 15/19] Remove confusing printouts from expected to fail "system" commands --- client/mysqltest.c | 12 ++++++++++-- mysql-test/r/mysqltest.result | 1 + mysql-test/t/mysqltest.test | 3 +-- 3 files changed, 12 insertions(+), 4 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 8938df1944f..7ba8dc31405 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -1134,6 +1134,7 @@ static void do_exec(struct st_query *query) } free_replace(); + DBUG_VOID_RETURN; } @@ -1300,10 +1301,13 @@ int do_modify_var(struct st_query *query, const char *name, int do_system(struct st_query *q) { + DYNAMIC_STRING *ds; char *p=q->first_argument; VAR v; var_init(&v, 0, 0, 0, 0); eval_expr(&v, p, 0); /* NULL terminated */ + ds= &ds_res; + if (v.str_val_len) { char expr_buf[1024]; @@ -1316,8 +1320,11 @@ int do_system(struct st_query *q) { if (q->abort_on_error) die("system command '%s' failed", expr_buf); - /* If ! abort_on_error, display message and continue */ - verbose_msg("system command '%s' failed", expr_buf); + + /* If ! abort_on_error, log message and continue */ + dynstr_append(ds, "system command '"); + replace_dynstr_append(ds, expr_buf); + dynstr_append(ds, "' failed\n"); } } else @@ -1582,6 +1589,7 @@ int do_sleep(struct st_query *query, my_bool real_sleep) if (opt_sleep && !real_sleep) sleep_val= opt_sleep; + DBUG_PRINT("info", ("sleep_val: %f", sleep_val)); my_sleep((ulong) (sleep_val * 1000000L)); query->last_argument= sleep_end; return 0; diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index 2e78f468f93..0109436fac9 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -304,6 +304,7 @@ mysqltest: At line 1: End of line junk detected: "1000" mysqltest: At line 1: Missing arguments to system, nothing to do! mysqltest: At line 1: Missing arguments to system, nothing to do! mysqltest: At line 1: system command 'false' failed +system command 'NonExistsinfComamdn 2> /dev/null' failed test test2 test3 diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index 132a6329178..3d851605823 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -689,7 +689,7 @@ system echo "hej" > /dev/null; --exec echo "system false;" | $MYSQL_TEST 2>&1 --disable_abort_on_error -system NonExistsinfComamdn; +system NonExistsinfComamdn 2> /dev/null; --enable_abort_on_error @@ -1026,4 +1026,3 @@ drop table t1; drop table t1; - From 90bbcc9b4ddb1a3a69c1dba7fe6a2fc8d38d5c20 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Tue, 20 Dec 2005 15:34:58 +0100 Subject: [PATCH 16/19] Store the each column from a multi column result set into a separate variable. --- client/mysqltest.c | 68 +++++++++++++++++++++++++++-------- mysql-test/r/mysqltest.result | 19 ++++++++++ mysql-test/t/mysqltest.test | 36 +++++++++++++++++++ 3 files changed, 109 insertions(+), 14 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 7ba8dc31405..e709dc64ef4 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -1137,26 +1137,50 @@ static void do_exec(struct st_query *query) DBUG_VOID_RETURN; } +/* + Set variable from the result of a query -int var_query_set(VAR* v, const char *p, const char** p_end) + SYNOPSIS + var_query_set() + var variable to set from query + query start of query string to execute + query_end end of the query string to execute + + + DESCRIPTION + let @ = `` + + Execute the query and assign the first row of result to var as + a tab separated strings + + Also assign each column of the result set to + variable "$_" + Thus the tab separated output can be read from $ and + and each individual column can be read as $_ + +*/ + +int var_query_set(VAR* var, const char *query, const char** query_end) { - char* end = (char*)((p_end && *p_end) ? *p_end : p + strlen(p)); + char* end = (char*)((query_end && *query_end) ? + *query_end : query + strlen(query)); MYSQL_RES *res; MYSQL_ROW row; MYSQL* mysql = &cur_con->mysql; LINT_INIT(res); - while (end > p && *end != '`') + while (end > query && *end != '`') --end; - if (p == end) + if (query == end) die("Syntax error in query, missing '`'"); - ++p; + ++query; - if (mysql_real_query(mysql, p, (int)(end - p)) || + if (mysql_real_query(mysql, query, (int)(end - query)) || !(res = mysql_store_result(mysql))) { *end = 0; - die("Error running query '%s': %s", p, mysql_error(mysql)); + die("Error running query '%s': %d: %s", query, + mysql_errno(mysql) ,mysql_error(mysql)); } if ((row = mysql_fetch_row(res)) && row[0]) @@ -1169,21 +1193,39 @@ int var_query_set(VAR* v, const char *p, const char** p_end) uint i; ulong *lengths; char *end; + MYSQL_FIELD *fields= mysql_fetch_fields(res); init_dynamic_string(&result, "", 16384, 65536); lengths= mysql_fetch_lengths(res); for (i=0; i < mysql_num_fields(res); i++) { if (row[0]) + { + /* Add to _ */ + uint j; + char var_col_name[MAX_VAR_NAME]; + uint length= snprintf(var_col_name, MAX_VAR_NAME, + "$%s_%s", var->name, fields[i].name); + /* Convert characters not allowed in variable names to '_' */ + for (j= 1; j < length; j++) + { + if (!my_isvar(charset_info,var_col_name[j])) + var_col_name[j]= '_'; + } + var_set(var_col_name, var_col_name + length, + row[i], row[i] + lengths[i]); + + /* Add column to tab separated string */ dynstr_append_mem(&result, row[i], lengths[i]); + } dynstr_append_mem(&result, "\t", 1); } end= result.str + result.length-1; - eval_expr(v, result.str, (const char**) &end); + eval_expr(var, result.str, (const char**) &end); dynstr_free(&result); } else - eval_expr(v, "", 0); + eval_expr(var, "", 0); mysql_free_result(res); return 0; @@ -4129,12 +4171,10 @@ static VAR *var_init(VAR *v, const char *name, int name_len, const char *val, if (!(tmp_var->str_val = my_malloc(val_alloc_len+1, MYF(MY_WME)))) die("Out of memory"); - memcpy(tmp_var->name, name, name_len); + if (name) + strmake(tmp_var->name, name, name_len); if (val) - { - memcpy(tmp_var->str_val, val, val_len); - tmp_var->str_val[val_len]=0; - } + strmake(tmp_var->str_val, val, val_len); tmp_var->name_len = name_len; tmp_var->str_val_len = val_len; tmp_var->alloced_len = val_alloc_len; diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index 0109436fac9..bf3821555cc 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -222,6 +222,25 @@ mysqltest: At line 1: Missing arguments to let mysqltest: At line 1: Missing variable name in let mysqltest: At line 1: Variable name in =hi does not start with '$' mysqltest: At line 1: Missing assignment operator in let +var1 +hi 1 hi there +hi +1 +hi there +var2 +2 + + +var2 again +2 + +2 + +var3 two columns with same name +1 2 3 +2 +2 +3 mysqltest: At line 1: Missing file name in source mysqltest: At line 1: Could not open file ./non_existingFile mysqltest: In included file "./var/tmp/recursive.sql": At line 1: Source directives are nesting too deep diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index 3d851605823..ae28a66c685 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -539,6 +539,42 @@ echo $novar1; --error 1 --exec echo "let hi;" | $MYSQL_TEST 2>&1 +# ---------------------------------------------------------------------------- +# Test to assign let from query +# let $=``; +# ---------------------------------------------------------------------------- + +echo var1; +let $var1= `select "hi" as "Col", 1 as "Column1", "hi there" as Col3`; +echo $var1; +echo $var1_Col; +echo $var1_Column1; +echo $var1_Col3; + +echo var2; +let $var2= `select 2 as "Column num 2"`; +echo $var2; +echo $var2_Column num 2; +echo $var2_Column; + +echo var2 again; +let $var2= `select 2 as "Column num 2"`; +echo $var2; +echo $var2_Column num 2; +echo $var2_Column_num_2; +echo $var2_Column; + +echo var3 two columns with same name; +let $var3= `select 1 as "Col", 2 as "Col", 3 as "var3"`; +echo $var3; +echo $var3_Col; +echo $var3_Col; +echo $var3_var3; + +#echo failing query in let; +#--error 1 +#--exec echo "let $var2= `failing query;`" | $MYSQL_TEST 2>&1 + # ---------------------------------------------------------------------------- # Test source command # ---------------------------------------------------------------------------- From 94d05ebc375041e656fd282ab9ee717ad61ed443 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Tue, 20 Dec 2005 17:06:20 +0100 Subject: [PATCH 17/19] Avoid implicit commits by using a different connection when creating/dropping sp's and views. --- client/mysqltest.c | 74 +++++++++++++++++++++++++++++++++++----------- 1 file changed, 57 insertions(+), 17 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index e709dc64ef4..16ae7702857 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -247,6 +247,8 @@ typedef struct struct connection { MYSQL mysql; + /* Used when creating views and sp, to avoid implicit commit */ + MYSQL* util_mysql; char *name; MYSQL_STMT* stmt; }; @@ -551,6 +553,8 @@ static void close_cons() mysql_stmt_close(next_con->stmt); next_con->stmt= 0; mysql_close(&next_con->mysql); + if (next_con->util_mysql) + mysql_close(next_con->util_mysql); my_free(next_con->name, MYF(MY_ALLOW_ZERO_PTR)); } DBUG_VOID_RETURN; @@ -1948,6 +1952,9 @@ int close_connection(struct st_query *q) } #endif mysql_close(&con->mysql); + if (con->util_mysql) + mysql_close(con->util_mysql); + con->util_mysql= 0; my_free(con->name, MYF(0)); /* When the connection is closed set name to "closed_connection" @@ -2040,16 +2047,15 @@ void init_manager() 0 - success, non-0 - failure */ -int safe_connect(MYSQL* con, const char *host, const char *user, - const char *pass, - const char *db, int port, const char *sock) +int safe_connect(MYSQL* mysql, const char *host, const char *user, + const char *pass, const char *db, int port, const char *sock) { int con_error= 1; my_bool reconnect= 1; int i; for (i= 0; i < MAX_CON_TRIES; ++i) { - if (mysql_real_connect(con, host,user, pass, db, port, sock, + if (mysql_real_connect(mysql, host,user, pass, db, port, sock, CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS)) { con_error= 0; @@ -2061,7 +2067,7 @@ int safe_connect(MYSQL* con, const char *host, const char *user, TODO: change this to 0 in future versions, but the 'kill' test relies on existing behavior */ - mysql_options(con, MYSQL_OPT_RECONNECT, (char *)&reconnect); + mysql_options(mysql, MYSQL_OPT_RECONNECT, (char *)&reconnect); return con_error; } @@ -2305,10 +2311,10 @@ int do_connect(struct st_query *q) con_db= 0; if (q->abort_on_error) { - if ((safe_connect(&next_con->mysql, con_host, con_user, con_pass, - con_db, con_port, con_sock ? con_sock: 0))) - die("Could not open connection '%s': %s", con_name, - mysql_error(&next_con->mysql)); + if (safe_connect(&next_con->mysql, con_host, con_user, con_pass, + con_db, con_port, con_sock ? con_sock: 0)) + die("Could not open connection '%s': %d %s", con_name, + mysql_errno(&next_con->mysql), mysql_error(&next_con->mysql)); } else error= connect_n_handle_errors(q, &next_con->mysql, con_host, con_user, @@ -3785,6 +3791,39 @@ end: } + +/* + Create a util connection if one does not already exists + and use that to run the query + This is done to avoid implict commit when creating/dropping objects such + as view, sp etc. +*/ + +static int util_query(MYSQL* org_mysql, const char* query){ + + MYSQL* mysql; + DBUG_ENTER("util_query"); + + if(!(mysql= cur_con->util_mysql)) + { + DBUG_PRINT("info", ("Creating util_mysql")); + if (!(mysql= mysql_init(mysql))) + die("Failed in mysql_init()"); + + if (safe_connect(mysql, org_mysql->host, org_mysql->user, + org_mysql->passwd, org_mysql->db, org_mysql->port, + org_mysql->unix_socket)) + die("Could not open util connection: %d %s", + mysql_errno(mysql), mysql_error(mysql)); + + cur_con->util_mysql= mysql; + } + + return mysql_query(mysql, query); +} + + + /* Run query @@ -3865,7 +3904,7 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) "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)) + if (util_query(mysql, query_str.str)) { /* Failed to create the view, this is not fatal @@ -3892,7 +3931,7 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) Collect warnings from create of the view that should otherwise have been produced when the SELECT was executed */ - append_warnings(&ds_warnings, mysql); + append_warnings(&ds_warnings, cur_con->util_mysql); } dynstr_free(&query_str); @@ -3909,12 +3948,12 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) */ DYNAMIC_STRING query_str; init_dynamic_string(&query_str, - "DROP PROCEDURE IF EXISTS mysqltest_tmp_sp;\n", + "DROP PROCEDURE IF EXISTS mysqltest_tmp_sp;", query_len+64, 256); - mysql_query(mysql, query_str.str); + util_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)) + if (util_query(mysql, query_str.str)) { /* Failed to create the stored procedure for this query, @@ -3958,13 +3997,13 @@ static void run_query(MYSQL *mysql, struct st_query *command, int flags) if (sp_created) { - if (mysql_query(mysql, "DROP PROCEDURE mysqltest_tmp_sp ")) + if (util_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 ")) + if (util_query(mysql, "DROP VIEW mysqltest_tmp_v ")) die("Failed to drop view: %d: %s", mysql_errno(mysql), mysql_error(mysql)); } @@ -4299,7 +4338,8 @@ int main(int argc, char **argv) die("Out of memory"); if (safe_connect(&cur_con->mysql, host, user, pass, db, port, unix_sock)) - die("Failed in mysql_real_connect(): %s", mysql_error(&cur_con->mysql)); + die("Could not open connection '%s': %d %s", cur_con->name, + mysql_errno(&cur_con->mysql), mysql_error(&cur_con->mysql)); init_var_hash(&cur_con->mysql); From 43a559ac70279dcf06a60ccb74bbb6aaa993b973 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Thu, 29 Dec 2005 09:48:43 +0100 Subject: [PATCH 18/19] Improved error message for failing with wrong error --- client/mysqltest.c | 9 +++++---- mysql-test/r/mysqltest.result | 8 ++++---- 2 files changed, 9 insertions(+), 8 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 16ae7702857..7e7f2699ac7 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -3549,11 +3549,12 @@ static void handle_error(const char *query, struct st_query *q, if (i) { if (q->expected_errno[0].type == ERR_ERRNO) - die("query '%s' failed with wrong errno %d instead of %d...", - q->query, err_errno, q->expected_errno[0].code.errnum); + die("query '%s' failed with wrong errno %d: '%s', instead of %d...", + q->query, err_errno, err_error, q->expected_errno[0].code.errnum); else - die("query '%s' failed with wrong sqlstate %s instead of %s...", - q->query, err_sqlstate, q->expected_errno[0].code.sqlstate); + die("query '%s' failed with wrong sqlstate %s: '%s', instead of %s...", + q->query, err_sqlstate, err_error, + q->expected_errno[0].code.sqlstate); } DBUG_VOID_RETURN; diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index bf3821555cc..2657fb8a409 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -16,7 +16,7 @@ otto mysqltest: At line 1: query 'select otto from (select 1 as otto) as t1' succeeded - should have failed with sqlstate 42S22... select friedrich from (select 1 as otto) as t1; ERROR 42S22: Unknown column 'friedrich' in 'field list' -mysqltest: At line 1: query 'select friedrich from (select 1 as otto) as t1' failed with wrong sqlstate 42S22 instead of 00000... +mysqltest: At line 1: query 'select friedrich from (select 1 as otto) as t1' failed with wrong sqlstate 42S22: 'Unknown column 'friedrich' in 'field list'', instead of 00000... select otto from (select 1 as otto) as t1; otto 1 @@ -133,7 +133,7 @@ ERROR 42S02: Table 'test.t1' doesn't exist select 1146 as "after_!errno_masked_error" ; after_!errno_masked_error 1146 -mysqltest: At line 1: query 'select 3 from t1' failed with wrong errno 1146 instead of 1000... +mysqltest: At line 1: query 'select 3 from t1' failed with wrong errno 1146: 'Table 'test.t1' doesn't exist', instead of 1000... garbage ; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1 select 1064 as "after_--enable_abort_on_error" ; @@ -141,7 +141,7 @@ after_--enable_abort_on_error 1064 select 3 from t1 ; ERROR 42S02: Table 'test.t1' doesn't exist -mysqltest: At line 1: query 'select 3 from t1' failed with wrong errno 1146 instead of 1064... +mysqltest: At line 1: query 'select 3 from t1' failed with wrong errno 1146: 'Table 'test.t1' doesn't exist', instead of 1064... hello hello ;;;;;;;; @@ -374,7 +374,7 @@ mysqltest: At line 1: Missing connection user mysqltest: At line 1: Missing connection user mysqltest: At line 1: Missing connection password mysqltest: At line 1: Missing connection db -mysqltest: At line 1: Could not open connection 'con2': Unknown database 'illegal_db' +mysqltest: At line 1: Could not open connection 'con2': 1049 Unknown database 'illegal_db' mysqltest: At line 1: Illegal argument for port: 'illegal_port' mysqltest: At line 1: Illegal option to connect: SMTP OK From f7ed8e8698276dc1a107627206b04baef6da0c1b Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Mon, 9 Jan 2006 20:19:06 +0100 Subject: [PATCH 19/19] Add simple printout from mysqlslap.test to avoid empty result file --- mysql-test/r/mysqlslap.result | 2 +- mysql-test/t/mysqlslap.test | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/mysqlslap.result b/mysql-test/r/mysqlslap.result index ae38fbe940a..b50dc9aad24 100644 --- a/mysql-test/r/mysqlslap.result +++ b/mysql-test/r/mysqlslap.result @@ -1 +1 @@ -# this test result intentionally blank due to running in silent mode. +Test completed diff --git a/mysql-test/t/mysqlslap.test b/mysql-test/t/mysqlslap.test index c9a53fe6d0a..aaee713b409 100644 --- a/mysql-test/t/mysqlslap.test +++ b/mysql-test/t/mysqlslap.test @@ -6,3 +6,5 @@ --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))" + +echo Test completed;