From 447a11940796a19a05d380278ada083be1bcca9a Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Fri, 15 Jul 2005 17:51:43 +0200 Subject: [PATCH 1/7] BUG#11316 mysqltest, problems when assigning value with '#' to $variable - Fixed problem, only detect comment if the # is on start of line AND starting line of the current command. - Wrote tests for most of the mysqltest commands, added stricter checking of correct syntax. --- client/mysqltest.c | 585 +++++++++++++++++++------ mysql-test/include/mysqltest_while.inc | 137 ++++++ mysql-test/mysql-test-run.pl | 5 + mysql-test/mysql-test-run.sh | 1 + mysql-test/r/mysqltest.result | 121 +++++ mysql-test/r/rpl_flush_log_loop.result | 2 +- mysql-test/t/innodb-deadlock.test | 6 +- mysql-test/t/innodb-lock.test | 2 +- mysql-test/t/mysqltest.test | 386 +++++++++++++++- mysql-test/t/ndb_autodiscover2.test | 2 +- mysql-test/t/rpl_change_master.test | 2 +- mysql-test/t/rpl_deadlock.test | 6 +- mysql-test/t/rpl_drop_temp.test | 2 +- mysql-test/t/rpl_flush_log_loop.test | 4 +- mysql-test/t/rpl_insert_id.test | 2 +- mysql-test/t/rpl_rotate_logs.test | 2 +- mysql-test/t/rpl_until.test | 2 +- 17 files changed, 1124 insertions(+), 143 deletions(-) create mode 100644 mysql-test/include/mysqltest_while.inc diff --git a/client/mysqltest.c b/client/mysqltest.c index b7f4ceb9c20..2455c4adfd3 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -42,7 +42,7 @@ **********************************************************************/ -#define MTEST_VERSION "2.4" +#define MTEST_VERSION "2.5" #include #include @@ -75,7 +75,7 @@ #define LAZY_GUESS_BUF_SIZE 8192 #define INIT_Q_LINES 1024 #define MIN_VAR_ALLOC 32 -#define BLOCK_STACK_DEPTH 32 +#define BLOCK_STACK_DEPTH 16 #define MAX_EXPECTED_ERRORS 10 #define QUERY_SEND 1 #define QUERY_REAP 2 @@ -151,6 +151,8 @@ static char **default_argv; static const char *load_default_groups[]= { "mysqltest","client",0 }; static char line_buffer[MAX_DELIMITER], *line_buffer_pos= line_buffer; +static char* file_name_stack[MAX_INCLUDE_DEPTH]; +static int cur_file_name; static FILE* file_stack[MAX_INCLUDE_DEPTH]; static FILE** cur_file; static FILE** file_stack_end; @@ -307,7 +309,7 @@ const char *command_names[]= "connect", /* the difference between sleep and real_sleep is that sleep will use the delay from command line (--sleep) if there is one. - real_sleep always uses delay from it's argument. + real_sleep always uses delay from mysqltest's command line argument. the logic is that sometimes delays are cpu-dependent (and --sleep can be used to set this delay. real_sleep is used for cpu-independent delays @@ -514,6 +516,9 @@ static void close_files() { if (*cur_file != stdin && *cur_file) my_fclose(*cur_file,MYF(0)); + char* p= file_name_stack[cur_file_name--]= 0; + if (p) + free(p); } DBUG_VOID_RETURN; } @@ -564,6 +569,10 @@ static void die(const char* fmt, ...) if (fmt) { fprintf(stderr, "%s: ", my_progname); + if (*cur_file && cur_file > (file_stack + 1) ) + fprintf(stderr, "In included file \"%s\": ", + file_name_stack[cur_file_name]); + fprintf(stderr, "At line %u: ", start_lineno); vfprintf(stderr, fmt, args); fprintf(stderr, "\n"); fflush(stderr); @@ -809,11 +818,38 @@ int open_file(const char* name) if (*cur_file && cur_file == file_stack_end) die("Source directives are nesting too deep"); - if (!(*(cur_file+1) = my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(MY_WME)))) - die(NullS); - cur_file++; + if (!(*++cur_file = my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(0)))) + die("Could not open file %s", buff); *++lineno=1; + file_name_stack[++cur_file_name]= strdup(buff); + return 0; +} + +/* + Check for unexpected "junk" after the end of query + This is normally caused by missing delimiters +*/ + +int check_eol_junk(const char *eol) +{ + char *p= (char*)eol; + /* Remove all spacing chars except new line */ + while (*p && my_isspace(charset_info,*p) && (*p != '\n')) + p++; + + /* Check for extra delimiter */ + size_t l= strlen(delimiter); + if (*p && strlen(p) >= l && !strncmp(p, delimiter, l) ) + die("Extra delimiter \"%s\" found", delimiter); + + /* Allow trailing # comment */ + if (*p && *p != '#') + { + if (*p == '\n') + die("Missing delimiter"); + die("End of line junk detected: \"%s\"", p); + } return 0; } @@ -844,24 +880,26 @@ int do_wait_for_slave_to_stop(struct st_query* q __attribute__((unused))) break; my_sleep(SLAVE_POLL_INTERVAL); } - return 0; + return check_eol_junk(q->first_argument); } -int do_require_manager(struct st_query* a __attribute__((unused))) +int do_require_manager(struct st_query* q) { if (!manager) abort_not_supported_test(); - return 0; + return check_eol_junk(q->first_argument); } #ifndef EMBEDDED_LIBRARY int do_server_start(struct st_query* q) { + check_eol_junk(q->first_argument); return do_server_op(q,"start"); } int do_server_stop(struct st_query* q) { + check_eol_junk(q->first_argument); return do_server_op(q,"stop"); } @@ -876,7 +914,7 @@ int do_server_op(struct st_query* q,const char* op) com_p=strmov(com_buf,op); com_p=strmov(com_p,"_exec "); if (!*p) - die("Missing server name in server_%s\n",op); + die("Missing server name in server_%s",op); while (*p && !my_isspace(charset_info,*p)) *com_p++= *p++; *com_p++=' '; @@ -892,23 +930,42 @@ int do_server_op(struct st_query* q,const char* op) manager->last_errno); } - return 0; + return check_eol_junk(p); } #endif + +/* + Source and execute the given file + + SYNOPSIS + do_source() + q called command + + DESCRIPTION + source + + Open the file and execute it + +*/ + int do_source(struct st_query* q) { char* p=q->first_argument, *name; if (!*p) - die("Missing file name in source\n"); + die("Missing file name in source"); name = p; while (*p && !my_isspace(charset_info,*p)) p++; - *p = 0; - + if (*p) + { + *p++= 0; + check_eol_junk(p); + } return open_file(name); } + /* Execute given command. @@ -917,18 +974,19 @@ int do_source(struct st_query* q) q called command DESCRIPTION - If one uses --exec command [args] command in .test file - we will execute the command and record its output. + exec + + Execute the text between exec and end of line in a subprocess. + The error code returned from the subprocess is checked against the + expected error array, previously set with the --error command. + It can thus be used to execute a command that shall fail. - RETURN VALUES - 0 ok - 1 error */ static void do_exec(struct st_query* q) { int error; - DYNAMIC_STRING *ds= NULL; /* Assign just to avoid warning */ + DYNAMIC_STRING *ds= NULL; DYNAMIC_STRING ds_tmp; char buf[1024]; FILE *res_file; @@ -938,12 +996,12 @@ static void do_exec(struct st_query* q) while (*cmd && my_isspace(charset_info, *cmd)) cmd++; if (!*cmd) - die("Missing argument in exec\n"); + die("Missing argument in exec"); DBUG_PRINT("info", ("Executing '%s'", cmd)); if (!(res_file= popen(cmd, "r")) && q->abort_on_error) - die("popen() failed\n"); + die("popen(\"%s\", \"r\") failed", cmd); if (disable_result_log) { @@ -969,34 +1027,36 @@ static void do_exec(struct st_query* q) error= pclose(res_file); if (error != 0) { - uint status= WEXITSTATUS(error), i; + uint i, status= WEXITSTATUS(error); my_bool ok= 0; if (q->abort_on_error) - die("At line %u: command \"%s\" failed", start_lineno, cmd); + die("command \"%s\" failed", cmd); DBUG_PRINT("info", ("error: %d, status: %d", error, status)); - for (i=0 ; (uint) i < q->expected_errors ; i++) + for (i=0 ; i < q->expected_errors ; i++) { DBUG_PRINT("info", ("expected error: %d", q->expected_errno[i].code.errnum)); if ((q->expected_errno[i].type == ERR_ERRNO) && (q->expected_errno[i].code.errnum == status)) + { ok= 1; - verbose_msg("At line %u: command \"%s\" failed with expected error: %d", - start_lineno, cmd, status); + verbose_msg("command \"%s\" failed with expected error: %d", + cmd, status); + } } if (!ok) - die("At line: %u: command \"%s\" failed with wrong error: %d", - start_lineno, cmd, status); + die("command \"%s\" failed with wrong error: %d", + cmd, status); } else 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("At line: %u: command \"%s\" succeeded - should have failed with errno %d...", - start_lineno, cmd, q->expected_errno[0].code.errnum); + die("command \"%s\" succeeded - should have failed with errno %d...", + cmd, q->expected_errno[0].code.errnum); } if (!disable_result_log) @@ -1007,7 +1067,7 @@ static void do_exec(struct st_query* q) if (record) { if (!q->record_file[0] && !result_file) - die("At line %u: Missing result file", start_lineno); + die("Missing result file"); if (!result_file) str_to_file(q->record_file, ds->str, ds->length); } @@ -1125,26 +1185,67 @@ int eval_expr(VAR* v, const char* p, const char** p_end) return 1; } + +/* + Increase the value of a variable + + SYNOPSIS + do_inc() + q called command + + DESCRIPTION + inc $var_name + +*/ + int do_inc(struct st_query* q) { char* p=q->first_argument; VAR* v; + if (!*p) + die("Missing arguments to inc"); + if (*p != '$') + die("First argument to inc must be a variable (start with $)"); v = var_get(p, 0, 1, 0); v->int_val++; v->int_dirty = 1; + while (*p && !my_isspace(charset_info,*p)) + p++; + check_eol_junk(p); return 0; } + +/* + Decrease the value of a variable + + SYNOPSIS + do_dec() + q called command + + DESCRIPTION + dec $var_name + +*/ + int do_dec(struct st_query* q) { char* p=q->first_argument; VAR* v; + if (!*p) + die("Missing arguments to dec"); + if (*p != '$') + die("First argument to dec must be a variable (start with $)"); v = var_get(p, 0, 1, 0); v->int_val--; v->int_dirty = 1; + while (*p && !my_isspace(charset_info,*p)) + p++; + check_eol_junk(p); return 0; } + int do_system(struct st_query* q) { char* p=q->first_argument; @@ -1159,26 +1260,63 @@ int do_system(struct st_query* q) memcpy(expr_buf, v.str_val, v.str_val_len); expr_buf[v.str_val_len] = 0; DBUG_PRINT("info", ("running system command '%s'", expr_buf)); - if (system(expr_buf) && q->abort_on_error) - die("system command '%s' failed", expr_buf); + if (system(expr_buf)) + { + 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); + } } + else + die("Missing arguments to system, nothing to do!"); var_free(&v); return 0; } + +/* + Print the content between echo and to result file. + If content is a variable, the variable value will be retrieved + + SYNOPSIS + do_echo() + q called command + + DESCRIPTION + Usage 1: + echo text + Print the text after echo until end of command to result file + + Usage 2: + echo $ + Print the content of the variable to result file + +*/ + int do_echo(struct st_query* q) { char* p=q->first_argument; + DYNAMIC_STRING *ds= NULL; + 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; + eval_expr(&v, p, 0); /* NULL terminated */ if (v.str_val_len) - { - fflush(stdout); - write(1, v.str_val, v.str_val_len); - } - write(1, "\n", 1); + 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); return 0; } @@ -1199,8 +1337,19 @@ int do_sync_with_master2(const char* p) rpl_parse = mysql_rpl_parse_enabled(mysql); mysql_disable_rpl_parse(mysql); - if (*p) - offset = atoi(p); + const char* offset_str= p; + /* Step until end of integer arg and check it */ + while (*p && !my_isspace(charset_info, *p)) + { + if (!my_isdigit(charset_info, *p)) + die("Invalid integer argument \"%s\"", offset_str); + p++; + } + check_eol_junk(p); + + if (*offset_str) + offset = atoi(offset_str); + sprintf(query_buf, "select master_pos_wait('%s', %ld)", master_pos.file, master_pos.pos + offset); @@ -1256,7 +1405,7 @@ int do_save_master_pos() mysql_disable_rpl_parse(mysql); if (mysql_query(mysql, query= "show master status")) - die("At line %u: failed in show master status: %d: %s", start_lineno, + die("failed in show master status: %d: %s", mysql_errno(mysql), mysql_error(mysql)); if (!(last_result =res = mysql_store_result(mysql))) @@ -1275,20 +1424,52 @@ int do_save_master_pos() } +/* + Assign the variable with + + SYNOPSIS + do_let() + q called command + + DESCRIPTION + let $= + + - is the string string found between the $ and = + - is the content between the = and , it may span + multiple line and contain any characters except + - is a string containing of one or more chars, default is ; + + RETURN VALUES + Program will die if error detected +*/ + int do_let(struct st_query* q) { char* p=q->first_argument; char *var_name, *var_name_end, *var_val_start; + + /* Find */ if (!*p) - die("Missing variable name in let\n"); + die("Missing arguments to let"); var_name = p; - while (*p && (*p != '=' || my_isspace(charset_info,*p))) + while (*p && *p != '=' && !my_isspace(charset_info,*p)) p++; var_name_end = p; - if (*p == '=') p++; + if (var_name+1==var_name_end) + die("Missing variable name in let"); + while (*p && (*p != '=' || my_isspace(charset_info,*p))) + p++; + if (*p == '=') + p++; + else + die("Missing assignment operator in let"); + + /* Find start of */ while (*p && my_isspace(charset_info,*p)) p++; var_val_start = p; + + /* Assign var_val to var_name */ return var_set(var_name, var_name_end, var_val_start, q->end); } @@ -1308,65 +1489,109 @@ int var_set_errno(int sql_errno) } -int do_rpl_probe(struct st_query* q __attribute__((unused))) +int do_rpl_probe(struct st_query* q) { DBUG_ENTER("do_rpl_probe"); if (mysql_rpl_probe(&cur_con->mysql)) die("Failed in mysql_rpl_probe(): '%s'", mysql_error(&cur_con->mysql)); + check_eol_junk(q->first_argument); DBUG_RETURN(0); } -int do_enable_rpl_parse(struct st_query* q __attribute__((unused))) +int do_enable_rpl_parse(struct st_query* q) { mysql_enable_rpl_parse(&cur_con->mysql); + check_eol_junk(q->first_argument); return 0; } -int do_disable_rpl_parse(struct st_query* q __attribute__((unused))) +int do_disable_rpl_parse(struct st_query* q) { mysql_disable_rpl_parse(&cur_con->mysql); + check_eol_junk(q->first_argument); return 0; } +/* + Sleep the number of specifed seconds + + SYNOPSIS + do_sleep() + q called command + real_sleep use the value from opt_sleep as number of seconds to sleep + + DESCRIPTION + sleep + real_sleep + +*/ + int do_sleep(struct st_query* q, my_bool real_sleep) { char *p=q->first_argument; while (*p && my_isspace(charset_info,*p)) p++; if (!*p) - die("Missing argument in sleep\n"); + die("Missing argument to sleep"); if (opt_sleep && !real_sleep) my_sleep(opt_sleep * 1000000L); else - my_sleep((ulong) (atof(p) * 1000000L)); - return 0; + { + int err= 0; + double val=1; + const char* val_str= p; + while (*p && !my_isspace(charset_info,*p)) + { + if (!my_isdigit(charset_info, *p) && !my_ispunct(charset_info, *p)) + err= 1; + p++; + } + if (!err) + val= my_strtod(val_str, &p, &err); + if (err) + die("Invalid argument to sleep \"%s\"", q->first_argument); + my_sleep((ulong) (val * 1000000L)); + } + return check_eol_junk(p++); } static void get_file_name(char *filename, struct st_query* q) { - char* p=q->first_argument; - strnmov(filename, p, FN_REFLEN); - /* Remove end space */ - while (p > filename && my_isspace(charset_info,p[-1])) - p--; - p[0]=0; + + + char* p=q->first_argument, *name; + if (!*p) + die("Missing file name argument"); + name = p; + while (*p && !my_isspace(charset_info,*p)) + p++; + if (*p) + { + *p++= 0; + check_eol_junk(p); + } + strmake(filename, name, FN_REFLEN); } static void set_charset(struct st_query* q) { char* charset_name= q->first_argument; - char* tmp; + char* p; if (!charset_name || !*charset_name) - die("Missing charset name in 'character_set'\n"); + die("Missing charset name in 'character_set'"); /* Remove end space */ - tmp= charset_name; - while (*tmp && !my_isspace(charset_info,*tmp)) - tmp++; - *tmp= 0; + p= charset_name; + while (*p && !my_isspace(charset_info,*p)) + p++; + if(*p) + { + *p++= 0; + check_eol_junk(p); + } charset_info= get_charset_by_csname(charset_name,MY_CS_PRIMARY,MYF(MY_WME)); if (!charset_info) @@ -1380,7 +1605,7 @@ static uint get_errcodes(match_err *to,struct st_query* q) DBUG_ENTER("get_errcodes"); if (!*p) - die("Missing argument in %s\n", q->query); + die("Missing argument in %s", q->query); do { @@ -1399,7 +1624,7 @@ static uint get_errcodes(match_err *to,struct st_query* q) long val; p=str2int(p,10,(long) INT_MIN, (long) INT_MAX, &val); if (p == NULL) - die("Invalid argument in %s\n", q->query); + die("Invalid argument in %s", q->query); to[count].code.errnum= (uint) val; to[count].type= ERR_ERRNO; } @@ -1467,7 +1692,7 @@ static char *get_string(char **to_ptr, char **from_ptr, *to++=c; } if (*from != ' ' && *from) - die("Wrong string argument in %s\n", q->query); + die("Wrong string argument in %s", q->query); while (my_isspace(charset_info,*from)) /* Point to next string */ from++; @@ -1513,14 +1738,14 @@ static void get_replace(struct st_query *q) bzero((char*) &to_array,sizeof(to_array)); bzero((char*) &from_array,sizeof(from_array)); if (!*from) - die("Missing argument in %s\n", q->query); + die("Missing argument in %s", q->query); start=buff=my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE)); while (*from) { char *to=buff; to=get_string(&buff, &from, q); if (!*from) - die("Wrong number of arguments to replace in %s\n", q->query); + die("Wrong number of arguments to replace in %s", q->query); insert_pointer_name(&from_array,to); to=get_string(&buff, &from, q); insert_pointer_name(&to_array,to); @@ -1534,7 +1759,7 @@ static void get_replace(struct st_query *q) (uint) from_array.typelib.count, word_end_chars)) || initialize_replace_buffer()) - die("Can't initialize replace from %s\n", q->query); + die("Can't initialize replace from %s", q->query); free_pointer_array(&from_array); free_pointer_array(&to_array); my_free(start, MYF(0)); @@ -1561,11 +1786,16 @@ int select_connection(char *p) DBUG_PRINT("enter",("name: '%s'",p)); if (!*p) - die("Missing connection name in connect\n"); + die("Missing connection name in connect"); name = p; while (*p && !my_isspace(charset_info,*p)) p++; - *p = 0; + + if (*p) + { + *p++= 0; + check_eol_junk(p); + } for (con = cons; con < next_con; con++) { @@ -1587,11 +1817,16 @@ int close_connection(struct st_query* q) DBUG_PRINT("enter",("name: '%s'",p)); if (!*p) - die("Missing connection name in connect\n"); + die("Missing connection name in connect"); name = p; while (*p && !my_isspace(charset_info,*p)) p++; - *p = 0; + + if (*p) + { + *p++= 0; + check_eol_junk(p); + } for (con = cons; con < next_con; con++) { @@ -1723,6 +1958,7 @@ int do_connect(struct st_query* q) con_sock[var_sock->str_val_len] = 0; } } + check_eol_junk(p); if (next_con == cons_end) die("Connection limit exhausted - increase MAX_CONS in mysqltest.c"); @@ -1783,7 +2019,8 @@ int do_done(struct st_query* q) cur_block--; parser.current_line++; } - return 0; + return check_eol_junk(q->first_argument); +; } @@ -1817,6 +2054,15 @@ int do_block(enum enum_commands cmd, struct st_query* q) expr_end = strrchr(expr_start, ')'); if (!expr_end) die("missing ')' in while"); + p= (char*)expr_end+1; + + while (*p && my_isspace(charset_info, *p)) + p++; + if (*p=='{') + die("Missing newline between while and '{'"); + if (*p) + die("Missing '{' after while. Found \"%s\"", p); + var_init(&v,0,0,0,0); eval_expr(&v, ++expr_start, &expr_end); @@ -1877,6 +2123,30 @@ my_bool end_of_query(int c) } +/* + Read one "line" from the file + + SYNOPSIS + read_line + buf buffer for the read line + size size of the buffer i.e max size to read + + DESCRIPTION + This function actually reads several lines an adds them to the + buffer buf. It will continue to read until it finds what it believes + is a complete query. + + Normally that means it will read lines until it reaches the + "delimiter" that marks end of query. Default delimiter is ';' + The function should be smart enough not to detect delimiter's + found inside strings sorrounded with '"' and '\'' escaped strings. + + If the first line in a query starts with '#' or '-' this line is treated + as a comment. A comment is always terminated when end of line '\n' is + reached. + +*/ + int read_line(char* buf, int size) { int c; @@ -1898,9 +2168,23 @@ int read_line(char* buf, int size) if ((*cur_file) != stdin) my_fclose(*cur_file, MYF(0)); cur_file--; + char* p= file_name_stack[cur_file_name--]= 0; + if (p) + free(p); lineno--; + start_lineno= *lineno; if (cur_file == file_stack) + { + /* We're back at the first file, check if + all { have matching } + */ + if (cur_block != block_stack) + { + start_lineno= *(lineno+1); + die("Missing end of block"); + } DBUG_RETURN(1); + } continue; } @@ -1933,7 +2217,8 @@ int read_line(char* buf, int size) } break; case R_LINE_START: - if (c == '#' || c == '-') + /* Only accept start of comment if this is the first line in query */ + if ((*lineno == start_lineno) && (c == '#' || c == '-')) { state = R_COMMENT; } @@ -2044,6 +2329,26 @@ int read_line(char* buf, int size) DBUG_RETURN(feof(*cur_file)); } +/* + Create a query from a set of lines + + SYNOPSIS + q_ptr pointer where to return the new query + + DESCRIPTION + Converts lines returned by read_line into a query, this involves + parsing the first word in the read line to find the query type. + + If the line starts with !$ or !S the query is setup + to expect that result when query is executed. + + A -- comment may contain a valid query as the first word after the + comment start. Thus it's always checked to see if that is the case. + The advantage with this approach is to be able to execute commands + terminated by new line '\n' regardless how many "delimiter" it contain. + + If query starts with @ this will specify a file to .... +*/ static char read_query_buf[MAX_QUERY]; @@ -2409,7 +2714,7 @@ static void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val, { len=(int) replace_strings(glob_replace, &out_buff, &out_length, val); if (len == -1) - die("Out of memory in replace\n"); + die("Out of memory in replace"); val=out_buff; } dynstr_append_mem(ds, val, len); @@ -2541,8 +2846,8 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags) { got_error_on_send= mysql_send_query(mysql, query, query_len); if (got_error_on_send && q->expected_errno[0].type == ERR_EMPTY) - die("At line %u: unable to send query '%s' (mysql_errno=%d , errno=%d)", - start_lineno, query, mysql_errno(mysql), errno); + die("unable to send query '%s' (mysql_errno=%d , errno=%d)", + query, mysql_errno(mysql), errno); } do @@ -2566,7 +2871,7 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags) abort_not_supported_test(); } if (q->abort_on_error) - die("At line %u: query '%s' failed: %d: %s", start_lineno, query, + die("query '%s' failed: %d: %s", query, mysql_errno(mysql), mysql_error(mysql)); else { @@ -2653,7 +2958,7 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags) if (!disable_result_log) { - ulong affected_rows; /* Ok to be undef if 'disable_info' is set */ + ulong affected_rows= 0; if (res) { @@ -2720,7 +3025,7 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags) if (record) { if (!q->record_file[0] && !result_file) - die("At line %u: Missing result file", start_lineno); + die("Missing result file"); if (!result_file) str_to_file(q->record_file, ds->str, ds->length); } @@ -2782,7 +3087,7 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags) may be a new connection. */ if (!(stmt= mysql_stmt_init(mysql))) - die("At line %u: unable init stmt structure"); + die("unable init stmt structure"); if (q->type != Q_EVAL) { @@ -2826,9 +3131,9 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags) { if (q->abort_on_error) { - die("At line %u: unable to prepare statement '%s': " + die("unable to prepare statement '%s': " "%s (mysql_stmt_errno=%d returned=%d)", - start_lineno, query, + query, mysql_stmt_error(stmt), mysql_stmt_errno(stmt), err); } else @@ -2860,9 +3165,9 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags) if (q->abort_on_error) { /* We got an error, unexpected */ - die("At line %u: unable to execute statement '%s': " + die("unable to execute statement '%s': " "%s (mysql_stmt_errno=%d returned=%d)", - start_lineno, query, mysql_stmt_error(stmt), + query, mysql_stmt_error(stmt), mysql_stmt_errno(stmt), got_error_on_execute); } else @@ -2882,9 +3187,9 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags) my_bool one= 1; if (mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, (void*) &one) != 0) - die("At line %u: unable to set stmt attribute " + die("unable to set stmt attribute " "'STMT_ATTR_UPDATE_MAX_LENGTH': %s (returned=%d)", - start_lineno, query, err); + query, err); } /* @@ -2896,9 +3201,9 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags) if (q->abort_on_error) { /* We got an error, unexpected */ - die("At line %u: unable to execute statement '%s': " + die("unable to execute statement '%s': " "%s (mysql_stmt_errno=%d returned=%d)", - start_lineno, query, mysql_stmt_error(stmt), + query, mysql_stmt_error(stmt), mysql_stmt_errno(stmt), got_error_on_execute); } else @@ -2989,18 +3294,18 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags) /* Fill in the data into the structures created above */ if ((err= mysql_stmt_bind_result(stmt, bind)) != 0) - die("At line %u: unable to bind result to statement '%s': " + die("unable to bind result to statement '%s': " "%s (mysql_stmt_errno=%d returned=%d)", - start_lineno, query, + 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("At line %u: unable to fetch all rows from statement '%s': " + die("unable to fetch all rows from statement '%s': " "%s (mysql_stmt_errno=%d returned=%d)", - start_lineno, query, + query, mysql_stmt_error(stmt), mysql_stmt_errno(stmt), err); /* Read result from each column */ @@ -3038,9 +3343,9 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags) } if ((err= mysql_stmt_fetch(stmt)) != MYSQL_NO_DATA) - die("At line %u: fetch didn't end with MYSQL_NO_DATA from statement " + die("fetch didn't end with MYSQL_NO_DATA from statement " "'%s': %s (mysql_stmt_errno=%d returned=%d)", - start_lineno, query, + query, mysql_stmt_error(stmt), mysql_stmt_errno(stmt), err); free_replace_column(); @@ -3077,7 +3382,7 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags) if (record) { if (!q->record_file[0] && !result_file) - die("At line %u: Missing result file", start_lineno); + die("Missing result file"); if (!result_file) str_to_file(q->record_file, ds->str, ds->length); } @@ -3198,7 +3503,7 @@ static int run_query_stmt_handle_error(char *query, struct st_query *q, } if (q->abort_on_error) - die("At line %u: query '%s' failed: %d: %s", start_lineno, query, + die("query '%s' failed: %d: %s", query, mysql_stmt_errno(stmt), mysql_stmt_error(stmt)); else { @@ -3438,7 +3743,7 @@ int main(int argc, char **argv) struct st_query *q; my_bool require_file=0, q_send_flag=0; char save_file[FN_REFLEN]; - MY_INIT(argv[0]); + MY_INIT("mysqltest"); { DBUG_ENTER("main"); DBUG_PROCESS(argv[0]); @@ -3454,15 +3759,16 @@ int main(int argc, char **argv) cur_con = cons; memset(file_stack, 0, sizeof(file_stack)); + memset(file_name_stack, 0, sizeof(file_name_stack)); memset(&master_pos, 0, sizeof(master_pos)); - file_stack_end = file_stack + MAX_INCLUDE_DEPTH; + file_stack_end = file_stack + MAX_INCLUDE_DEPTH - 1; cur_file = file_stack; lineno = lineno_stack; my_init_dynamic_array(&q_lines, sizeof(struct st_query*), INIT_Q_LINES, INIT_Q_LINES); memset(block_stack, 0, sizeof(block_stack)); - block_stack_end= block_stack + BLOCK_STACK_DEPTH; + block_stack_end= block_stack + BLOCK_STACK_DEPTH - 1; cur_block= block_stack; cur_block->ok= TRUE; /* Outer block should always be executed */ cur_block->cmd= Q_UNKNOWN; @@ -3474,7 +3780,10 @@ int main(int argc, char **argv) (char**) embedded_server_groups)) die("Can't initialize MySQL server"); if (cur_file == file_stack) - *++cur_file = stdin; + { + *++cur_file= stdin; + ++cur_file_name; + } *lineno=1; #ifndef EMBEDDED_LIBRARY if (manager_host) @@ -3530,18 +3839,30 @@ int main(int argc, char **argv) case Q_RPL_PROBE: do_rpl_probe(q); break; case Q_ENABLE_RPL_PARSE: do_enable_rpl_parse(q); break; case Q_DISABLE_RPL_PARSE: do_disable_rpl_parse(q); break; - case Q_ENABLE_QUERY_LOG: disable_query_log=0; break; - case Q_DISABLE_QUERY_LOG: disable_query_log=1; break; - case Q_ENABLE_ABORT_ON_ERROR: abort_on_error=1; break; - case Q_DISABLE_ABORT_ON_ERROR: abort_on_error=0; break; - case Q_ENABLE_RESULT_LOG: disable_result_log=0; break; - case Q_DISABLE_RESULT_LOG: disable_result_log=1; break; - case Q_ENABLE_WARNINGS: disable_warnings=0; break; - case Q_DISABLE_WARNINGS: disable_warnings=1; break; - case Q_ENABLE_INFO: disable_info=0; break; - case Q_DISABLE_INFO: disable_info=1; break; - case Q_ENABLE_METADATA: display_metadata=1; break; - case Q_DISABLE_METADATA: display_metadata=0; break; + case Q_ENABLE_QUERY_LOG: + disable_query_log=0; check_eol_junk(q->first_argument); break; + case Q_DISABLE_QUERY_LOG: + disable_query_log=1; check_eol_junk(q->first_argument); break; + case Q_ENABLE_ABORT_ON_ERROR: + abort_on_error=1; check_eol_junk(q->first_argument); break; + case Q_DISABLE_ABORT_ON_ERROR: + abort_on_error=0; check_eol_junk(q->first_argument); break; + case Q_ENABLE_RESULT_LOG: + disable_result_log=0; check_eol_junk(q->first_argument); break; + case Q_DISABLE_RESULT_LOG: + disable_result_log=1; check_eol_junk(q->first_argument); break; + case Q_ENABLE_WARNINGS: + disable_warnings=0; check_eol_junk(q->first_argument); break; + case Q_DISABLE_WARNINGS: + disable_warnings=1; check_eol_junk(q->first_argument); break; + case Q_ENABLE_INFO: + disable_info=0; check_eol_junk(q->first_argument); break; + case Q_DISABLE_INFO: + disable_info=1; check_eol_junk(q->first_argument); break; + case Q_ENABLE_METADATA: + display_metadata=1; check_eol_junk(q->first_argument); break; + case Q_DISABLE_METADATA: + display_metadata=0; check_eol_junk(q->first_argument); break; case Q_SOURCE: do_source(q); break; case Q_SLEEP: do_sleep(q, 0); break; case Q_REAL_SLEEP: do_sleep(q, 1); break; @@ -3558,12 +3879,19 @@ int main(int argc, char **argv) case Q_DELIMITER: strmake(delimiter, q->first_argument, sizeof(delimiter) - 1); delimiter_length= strlen(delimiter); + check_eol_junk(q->first_argument+delimiter_length); break; - case Q_DISPLAY_VERTICAL_RESULTS: display_result_vertically= TRUE; break; - case Q_DISPLAY_HORIZONTAL_RESULTS: - display_result_vertically= FALSE; break; + case Q_DISPLAY_VERTICAL_RESULTS: + display_result_vertically= TRUE; + check_eol_junk(q->first_argument); + break; + case Q_DISPLAY_HORIZONTAL_RESULTS: + display_result_vertically= FALSE; + check_eol_junk(q->first_argument); + break; case Q_LET: do_let(q); break; - case Q_EVAL_RESULT: eval_result = 1; break; + case Q_EVAL_RESULT: + eval_result = 1; check_eol_junk(q->first_argument); break; case Q_EVAL: if (q->query == q->query_buf) { @@ -3677,33 +4005,40 @@ int main(int argc, char **argv) break; case Q_PING: (void) mysql_ping(&cur_con->mysql); + check_eol_junk(q->first_argument); break; - case Q_EXEC: + case Q_EXEC: do_exec(q); break; case Q_START_TIMER: /* Overwrite possible earlier start of timer */ timer_start= timer_now(); + check_eol_junk(q->first_argument); break; case Q_END_TIMER: /* End timer before ending mysqltest */ timer_output(); got_end_timer= TRUE; + check_eol_junk(q->first_argument); break; - case Q_CHARACTER_SET: + case Q_CHARACTER_SET: set_charset(q); break; case Q_DISABLE_PS_PROTOCOL: ps_protocol_enabled= 0; + check_eol_junk(q->first_argument); break; case Q_ENABLE_PS_PROTOCOL: ps_protocol_enabled= ps_protocol; + check_eol_junk(q->first_argument); break; case Q_DISABLE_RECONNECT: cur_con->mysql.reconnect= 0; + check_eol_junk(q->first_argument); break; case Q_ENABLE_RECONNECT: cur_con->mysql.reconnect= 1; + check_eol_junk(q->first_argument); break; default: processed = 0; break; @@ -3724,7 +4059,7 @@ int main(int argc, char **argv) parser.current_line += current_line_inc; } - if (result_file && ds_res.length) + if (result_file && ds_res.length && !error) { if (!record) error |= check_result(&ds_res, result_file, q->require_file); @@ -4584,7 +4919,7 @@ static void get_replace_column(struct st_query *q) free_replace_column(); if (!*from) - die("Missing argument in %s\n", q->query); + die("Missing argument in %s", q->query); /* Allocate a buffer for results */ start=buff=my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE)); @@ -4595,9 +4930,9 @@ static void get_replace_column(struct st_query *q) to= get_string(&buff, &from, q); if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS) - die("Wrong column number to replace_columns in %s\n", q->query); + die("Wrong column number to replace_columns in %s", q->query); if (!*from) - die("Wrong number of arguments to replace in %s\n", q->query); + die("Wrong number of arguments to replace in %s", q->query); to= get_string(&buff, &from, q); my_free(replace_column[column_number-1], MY_ALLOW_ZERO_PTR); replace_column[column_number-1]= my_strdup(to, MYF(MY_WME | MY_FAE)); @@ -4654,7 +4989,7 @@ static char *subst_env_var(const char *str) if (!(subst= getenv(env_var))) { my_free(result, MYF(0)); - die("MYSQLTEST.NLM: Environment variable %s is not defined\n", + die("MYSQLTEST.NLM: Environment variable %s is not defined", env_var); } diff --git a/mysql-test/include/mysqltest_while.inc b/mysql-test/include/mysqltest_while.inc new file mode 100644 index 00000000000..90b05ee2695 --- /dev/null +++ b/mysql-test/include/mysqltest_while.inc @@ -0,0 +1,137 @@ +let $1 = 10; +while ($1) +{ +while ($1) +{ +while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + while ($1) +{ + echo $1; + dec $1; +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} +} diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index 1a31bbee1d5..f54461aa9b1 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -2129,6 +2129,11 @@ sub run_mysqltest ($) { mysqld_arguments($args,'master',0,$tinfo->{'master_opt'},[]); } + # ---------------------------------------------------------------------- + # export MYSQL_TEST variable containing /mysqltest + # ---------------------------------------------------------------------- + $ENV{'MYSQL_TEST'}= "$exe_mysqltest " . join(" ", @$args); + return mtr_run_test($exe,$args,$tinfo->{'path'},"",$path_timefile,""); } diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh index 537840c1d33..3e7a54fdead 100644 --- a/mysql-test/mysql-test-run.sh +++ b/mysql-test/mysql-test-run.sh @@ -714,6 +714,7 @@ if [ x$USE_TIMER = x1 ] ; then fi MYSQL_TEST_BIN=$MYSQL_TEST MYSQL_TEST="$MYSQL_TEST $MYSQL_TEST_ARGS" +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 diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index d75dbd5d00c..3b2828c3c6c 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -7,6 +7,7 @@ otto select otto from (select 1 as otto) as t1; otto 1 +mysqltest: At line 1: query 'select friedrich from (select 1 as otto) as t1' failed: 1054: Unknown column 'friedrich' in 'field list' select friedrich from (select 1 as otto) as t1; ERROR 42S22: Unknown column 'friedrich' in 'field list' select otto from (select 1 as otto) as t1; @@ -15,10 +16,12 @@ otto select otto from (select 1 as otto) as t1; otto 1 +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' 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... select otto from (select 1 as otto) as t1; otto 1 @@ -135,6 +138,8 @@ 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 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" ; @@ -142,3 +147,119 @@ 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: 1146: Table 'test.t1' doesn't exist +hello +hello +;;;;;;;; +# MySQL: -- The +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: At line 1: Extra delimiter ";" found +MySQL +"MySQL" +MySQL: The world''s most popular open source database +"MySQL: The world's most popular open source database" +MySQL: The world''s +most popular open +source database +# MySQL: The world''s +# most popular open +# source database +- MySQL: The world''s +- most popular open +- source database +- MySQL: The world''s +-- most popular open +-- source database +# MySQL: The +--world''s +# most popular +-- open +- source database +"MySQL: The world's most popular; open source database" +"MySQL: The world's most popular ; open source database" +"MySQL: The world's most popular ;open source database" +echo message echo message + +mysqltest: At line 1: Empty variable +sh: -c: line 0: syntax error near unexpected token `;' +sh: -c: line 0: `;' +mysqltest: At line 1: command ";" failed +mysqltest: At line 1: Missing argument in exec +MySQL +"MySQL" +MySQL: The +world''s most +popular open +source database +# MySQL: The +# world''s most +# popular open +# source database +-- MySQL: The +-- world''s most +-- popular open +-- source database +# MySQL: The +- world''s most +-- popular open +# source database +'$message' +"$message" +hej +hej +hej +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=hi does not start with '$' +mysqltest: At line 1: Missing assignment operator in let +mysqltest: At line 1: Missing assignment operator in let +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 +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 +mysqltest: In included file "./var/tmp/error.sql": At line 1: query 'garbage ' 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 'garbage' at line 1 +mysqltest: At line 1: Missing argument to sleep +mysqltest: At line 1: Invalid argument to sleep "abc" +1 +2 +101 +hej +1 +mysqltest: At line 1: Missing arguments to inc +mysqltest: At line 1: First argument to inc must be a variable (start with $) +mysqltest: At line 1: End of line junk detected: "1000" +4 +4 +-1 +-2 +99 +hej +-1 +mysqltest: At line 1: Missing arguments to dec +mysqltest: At line 1: First argument to dec must be a variable (start with $) +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! +sh: NonExistsinfComamdn: command not found +mysqltest: At line 1: system command 'NonExistsinfComamdn' failed +test +test2 +test3 +test4 +1 +mysqltest: In included file "./include/mysqltest_while.inc": At line 32: Nesting too deeply +mysqltest: At line 1: missing '(' in while +mysqltest: At line 1: missing ')' in while +mysqltest: At line 1: Missing '{' after while. Found "dec $i" +mysqltest: At line 1: Stray '}' - end of block before beginning +mysqltest: At line 1: Stray '}' - end of block before beginning +mysqltest: At line 1: query '' failed: 1065: Query was empty +mysqltest: At line 1: Missing '{' after while. Found "echo hej" +mysqltest: At line 3: Missing end of block +mysqltest: At line 1: Missing newline between while and '{' diff --git a/mysql-test/r/rpl_flush_log_loop.result b/mysql-test/r/rpl_flush_log_loop.result index 25177a6bca3..0a2d7e5e72a 100644 --- a/mysql-test/r/rpl_flush_log_loop.result +++ b/mysql-test/r/rpl_flush_log_loop.result @@ -4,10 +4,10 @@ reset master; reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; +stop slave; change master to master_host='127.0.0.1',master_user='root', master_password='',master_port=MASTER_PORT; start slave; -stop slave; change master to master_host='127.0.0.1',master_user='root', master_password='',master_port=SLAVE_PORT; start slave; diff --git a/mysql-test/t/innodb-deadlock.test b/mysql-test/t/innodb-deadlock.test index 7a7f657f35d..a63af1a5132 100644 --- a/mysql-test/t/innodb-deadlock.test +++ b/mysql-test/t/innodb-deadlock.test @@ -25,7 +25,7 @@ set autocommit=0; # The following query should hang because con1 is locking the page --send update t1 set x=2 where id = 0; ---sleep 2; +--sleep 2 connection con1; update t1 set x=1 where id = 0; @@ -63,7 +63,7 @@ set autocommit=0; # The following query should hang because con1 is locking the page --send update t1 set x=2 where id = 0; ---sleep 2; +--sleep 2 connection con1; update t1 set x=1 where id = 0; @@ -97,7 +97,7 @@ update t2 set a=2 where b = 0; select * from t2; --send update t1 set x=2 where id = 0; ---sleep 2; +--sleep 2 connection con1; update t1 set x=1 where id = 0; diff --git a/mysql-test/t/innodb-lock.test b/mysql-test/t/innodb-lock.test index 887a664e262..08f4cf15cc3 100644 --- a/mysql-test/t/innodb-lock.test +++ b/mysql-test/t/innodb-lock.test @@ -39,7 +39,7 @@ set autocommit=0; # The following statement should hang because con1 is locking the page --send lock table t1 write; ---sleep 2; +--sleep 2 connection con1; update t1 set x=1 where id = 0; diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index 0802c18ed6c..6e1b24e1232 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -3,6 +3,24 @@ # # Test of mysqltest itself # +# There are three rules that determines what belong to each command +# 1. A normal command is delimited by the which by default is +# set to ';' +# +# ex: | select * +# | from t1; +# | +# Command: "select * from t1" +# +# 2. Special case is a line that starts with "--", this is a comment +# ended when the new line character is reached. But the first word +# in the comment may contain a valid command, which then will be +# executed. This can be useful when sending commands that +# contains +# +# 3. Special case is also a line that starts with '#' which is treated +# as a comment and will be ended by new line character +# # ============================================================================ # ---------------------------------------------------------------------------- @@ -37,7 +55,9 @@ select otto from (select 1 as otto) as t1; # expectation <> response #--error 0 -#select friedrich from (select 1 as otto) as t1; +#select friedrich from (select 1 as otto) as t1 +--error 1 +--exec echo "select friedrich from (select 1 as otto) as t1;" | $MYSQL_TEST 2>&1 # expectation = response --error 1054 @@ -65,6 +85,9 @@ select otto from (select 1 as otto) as t1; #!S42S22 select otto from (select 1 as otto) as t1; #--error S42S22 #select otto from (select 1 as otto) as t1; +--error 1 +--exec echo "error S42S22; select otto from (select 1 as otto) as t1;" | $MYSQL_TEST 2>&1 + # ---------------------------------------------------------------------------- @@ -80,7 +103,8 @@ select friedrich from (select 1 as otto) as t1; #!S00000 select friedrich from (select 1 as otto) as t1; #--error S00000 #select friedrich from (select 1 as otto) as t1; - +--error 1 +--exec echo "error S00000; select friedrich from (select 1 as otto) as t1;" | $MYSQL_TEST 2>&1 # ---------------------------------------------------------------------------- # test cases for $mysql_errno @@ -262,6 +286,8 @@ eval select $mysql_errno as "after_!errno_masked_error" ; # select 3 from t1 ; # --error 1000 # select 3 from t1 ; +--error 1 +--exec echo "disable_abort_on_error; error 1000; select 3 from t1; error 1000; select 3 from t1;" | $MYSQL_TEST 2>&1 # ---------------------------------------------------------------------------- # Switch the abort on error on and check the effect on $mysql_errno @@ -286,3 +312,359 @@ select 3 from t1 ; #select 3 from t1 ; # #select 3 from t1 ; +--error 1 +--exec echo "disable_abort_on_error; enable_abort_on_error; error 1064; select 3 from t1; select 3 from t1;" | $MYSQL_TEST 2>&1 + + +# ---------------------------------------------------------------------------- +# Test comments +# ---------------------------------------------------------------------------- + +# This is a comment +# This is a ; comment +# This is a -- comment +-- This is also a comment +-- # This is also a comment +-- This is also a ; comment + +# ---------------------------------------------------------------------------- +# Test comments with embedded command +# ---------------------------------------------------------------------------- + +--echo hello +-- echo hello +-- echo ;;;;;;;; + +--echo # MySQL: -- The + +# ---------------------------------------------------------------------------- +# Test detect end of line "junk" +# Most likely causes by a missing delimiter +# ---------------------------------------------------------------------------- + +# Too many parameters to function +--error 1 +--exec echo "sleep 5 6;" | $MYSQL_TEST 2>&1 + +# Too many parameters to function +--error 1 +--exec echo "--sleep 5 6" | $MYSQL_TEST 2>&1 + +# +# Missing delimiter +# The comment will be "sucked into" the sleep command since +# delimiter is missing until after "show status" +--error 1 +--exec echo -e "sleep 4\n # A comment\nshow status;" | $MYSQL_TEST 2>&1 + +# +# Extra delimiter +# +--error 1 +--exec echo "--sleep 4;" | $MYSQL_TEST 2>&1 + + +# Allow trailing # comment +--sleep 1 # Wait for insert delayed to be executed. +--sleep 1 # Wait for insert delayed to be executed. + + +# ---------------------------------------------------------------------------- +# Test echo command +# ---------------------------------------------------------------------------- + +echo MySQL; +echo "MySQL"; +echo MySQL: The world''s most popular open source database; +echo "MySQL: The world's most popular open source database"; + +echo MySQL: The world''s + most popular open + source database; + +echo # MySQL: The world''s +# most popular open +# source database; + +echo - MySQL: The world''s +- most popular open +- source database; + +echo - MySQL: The world''s +-- most popular open +-- source database; + +echo # MySQL: The +--world''s +# most popular +-- open +- source database; + +echo "MySQL: The world's most popular; open source database"; +echo "MySQL: The world's most popular ; open source database"; +echo "MySQL: The world's most popular ;open source database"; +echo echo message echo message; + + +echo ; + +# Illegal use of echo + +--error 1 +--exec echo "echo $;" | $MYSQL_TEST 2>&1 + + +# ---------------------------------------------------------------------------- +# Test exec command +# ---------------------------------------------------------------------------- + +# Illegal use of exec +--error 1 +--exec echo "--exec ;" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "--exec " | $MYSQL_TEST 2>&1 + +# ---------------------------------------------------------------------------- +# Test let command +# ---------------------------------------------------------------------------- + +let $message=MySQL; +echo $message; + +let $message="MySQL"; +echo $message; + +let $message= MySQL: The + world''s most + popular open + source database; +echo $message; + +let $message= # MySQL: The +# world''s most +# popular open +# source database; +echo $message; + +let $message= -- MySQL: The +-- world''s most +-- popular open +-- source database; +echo $message; + +let $message= # MySQL: The +- world''s most +-- popular open +# source database; +echo $message; + +echo '$message'; +echo "$message"; + +let $1=hej; +echo $1; + +let $1 =hej ; +echo $1; + +let $1 = hej; +echo $1; + + +# Test illegal uses of let + +--error 1 +--exec echo "let ;" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "let $=hi;" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "let hi=hi;" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "let $1 hi;" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "let $m hi;" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "let $hi;" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "let $ hi;" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "let =hi;" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "let hi;" | $MYSQL_TEST 2>&1 + +# ---------------------------------------------------------------------------- +# Test source command +# ---------------------------------------------------------------------------- + +# Test illegal uses of source + +--error 1 +--exec echo "source ;" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "source non_existingFile;" | $MYSQL_TEST 2>&1 + +# Too many source +--exec echo "source var/tmp/recursive.sql;" > var/tmp/recursive.sql +--error 1 +--exec echo "source var/tmp/recursive.sql;" | $MYSQL_TEST 2>&1 + +# Source a file with error +--exec echo "garbage ;" > var/tmp/error.sql +--error 1 +--exec echo "source var/tmp/error.sql;" | $MYSQL_TEST 2>&1 + + +# ---------------------------------------------------------------------------- +# Test sleep command +# ---------------------------------------------------------------------------- + +sleep 0.5; +sleep 1; +real_sleep 1; + +# Missing parameter +--error 1 +--exec echo "sleep ;" | $MYSQL_TEST 2>&1 + +# Illegal parameter +--error 1 +--exec echo "sleep abc;" | $MYSQL_TEST 2>&1 + +# ---------------------------------------------------------------------------- +# Test inc +# ---------------------------------------------------------------------------- +inc $i; +echo $i; +inc $i; +echo $i; +let $i=100; +inc $i; +echo $i; + +let $i=hej; +echo $i; +inc $i; +echo $i; + +--error 1 +--exec echo "inc;" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo "inc i;" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo "let \$i=100; inc \$i 1000; echo \$i;" | $MYSQL_TEST 2>&1 + +inc $i; inc $i; inc $i; --echo $i +echo $i; + + +# ---------------------------------------------------------------------------- +# Test dec +# ---------------------------------------------------------------------------- + +dec $d; +echo $d; +dec $d; +echo $d; +let $d=100; +dec $d; +echo $d; + +let $d=hej; +echo $d; +dec $d; +echo $d; + +--error 1 +--exec echo "dec;" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo "dec i;" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo "let \$i=100; dec \$i 1000; echo \$i;" | $MYSQL_TEST 2>&1 + + +# ---------------------------------------------------------------------------- +# Test system +# ---------------------------------------------------------------------------- +system ls > /dev/null; +system echo "hej" > /dev/null; +--system ls > /dev/null +--system echo "hej" > /dev/null; + +--error 1 +--exec echo "system;" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo "system $NONEXISTSINFVAREABLI;" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo "system NonExistsinfComamdn;" | $MYSQL_TEST 2>&1 + +--disable_abort_on_error +system NonExistsinfComamdn; +--enable_abort_on_error + + +# ---------------------------------------------------------------------------- +# Test delimiter +# ---------------------------------------------------------------------------- + +delimiter stop; +echo teststop +delimiter ;stop +echo test2; +--delimiter stop +echo test3stop +--delimiter ; +echo test4; + +# ---------------------------------------------------------------------------- +# Test while, { and } +# ---------------------------------------------------------------------------- + +let $i=1; +while ($i) +{ + echo $i; + dec $i; +} +# One liner +#let $i=1;while ($i){echo $i;dec $i;} + + + +# Exceed max nesting level +--error 1 +--exec echo "source include/mysqltest_while.inc;" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo "while \$i;" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo "while (\$i;" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo "let \$i=1; while (\$i) dec \$i;" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo "};" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo "end;" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo "{;" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo -e "while (0)\necho hej;" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo -e "while (0)\n{echo hej;" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo -e "while (0){\n echo hej;" | $MYSQL_TEST 2>&1 + +# ---------------------------------------------------------------------------- +# TODO Test queries, especially their errormessages... so it's easy to debug +# new scripts and diagnose errors +# ---------------------------------------------------------------------------- + + diff --git a/mysql-test/t/ndb_autodiscover2.test b/mysql-test/t/ndb_autodiscover2.test index 76baa31a2a9..29941085df4 100644 --- a/mysql-test/t/ndb_autodiscover2.test +++ b/mysql-test/t/ndb_autodiscover2.test @@ -6,7 +6,7 @@ # The previous step has simply removed the frm file # from disk, but left the table in NDB # ---sleep 3; +--sleep 3 select * from t9 order by a; # handler_discover should be 1 diff --git a/mysql-test/t/rpl_change_master.test b/mysql-test/t/rpl_change_master.test index e6452b5b619..4bc8843aeec 100644 --- a/mysql-test/t/rpl_change_master.test +++ b/mysql-test/t/rpl_change_master.test @@ -8,7 +8,7 @@ insert into t1 values(1+get_lock("a",15)*0); insert into t1 values(2); save_master_pos; connection slave; ---real_sleep 3; # can't sync_with_master as we should be blocked +--real_sleep 3 # can't sync_with_master as we should be blocked stop slave; select * from t1; --replace_result $MASTER_MYPORT MASTER_MYPORT diff --git a/mysql-test/t/rpl_deadlock.test b/mysql-test/t/rpl_deadlock.test index 9ad6362f7e7..41d06d70ccf 100644 --- a/mysql-test/t/rpl_deadlock.test +++ b/mysql-test/t/rpl_deadlock.test @@ -58,7 +58,7 @@ while ($1) enable_query_log; select * from t1 for update; start slave; ---sleep 3; # hope that slave is blocked now +--sleep 3 # hope that slave is blocked now insert into t2 values(22); # provoke deadlock, slave should be victim commit; sync_with_master; @@ -76,7 +76,7 @@ change master to master_log_pos=401; # the BEGIN log event begin; select * from t2 for update; # hold lock start slave; ---sleep 10; # slave should have blocked, and be retrying +--sleep 10 # slave should have blocked, and be retrying commit; sync_with_master; select * from t1; # check that slave succeeded finally @@ -97,7 +97,7 @@ change master to master_log_pos=401; begin; select * from t2 for update; start slave; ---sleep 10; +--sleep 10 commit; sync_with_master; select * from t1; diff --git a/mysql-test/t/rpl_drop_temp.test b/mysql-test/t/rpl_drop_temp.test index 73d691d9d90..513a0e94940 100644 --- a/mysql-test/t/rpl_drop_temp.test +++ b/mysql-test/t/rpl_drop_temp.test @@ -9,5 +9,5 @@ sync_slave_with_master; connection master; disconnect master; connection slave; ---real_sleep 3; # time for DROP to be written +--real_sleep 3 # time for DROP to be written show status like 'Slave_open_temp_tables'; diff --git a/mysql-test/t/rpl_flush_log_loop.test b/mysql-test/t/rpl_flush_log_loop.test index 74920722868..5b52b0f7cef 100644 --- a/mysql-test/t/rpl_flush_log_loop.test +++ b/mysql-test/t/rpl_flush_log_loop.test @@ -1,15 +1,15 @@ # Testing if "flush logs" command bouncing resulting in logs created in a loop # in case of bi-directional replication -source include/master-slave.inc +source include/master-slave.inc; connection slave; +stop slave; --replace_result $MASTER_MYPORT MASTER_PORT eval change master to master_host='127.0.0.1',master_user='root', master_password='',master_port=$MASTER_MYPORT; start slave; connection master; -stop slave; --replace_result $SLAVE_MYPORT SLAVE_PORT eval change master to master_host='127.0.0.1',master_user='root', master_password='',master_port=$SLAVE_MYPORT; diff --git a/mysql-test/t/rpl_insert_id.test b/mysql-test/t/rpl_insert_id.test index a4506e32963..e2aa5c9b890 100644 --- a/mysql-test/t/rpl_insert_id.test +++ b/mysql-test/t/rpl_insert_id.test @@ -4,7 +4,7 @@ # We also check how the foreign_key_check variable is replicated source include/master-slave.inc; -source include/have_innodb.inc +source include/have_innodb.inc; connection master; create table t1(a int auto_increment, key(a)); create table t2(b int auto_increment, c int, key(b)); diff --git a/mysql-test/t/rpl_rotate_logs.test b/mysql-test/t/rpl_rotate_logs.test index da4d5f0bce1..8d75ce5ce16 100644 --- a/mysql-test/t/rpl_rotate_logs.test +++ b/mysql-test/t/rpl_rotate_logs.test @@ -102,7 +102,7 @@ show master logs; purge binary logs to 'master-bin.000002'; show binary logs; # sleeping 10 seconds or more would make the slave believe connection is down ---real_sleep 1; +--real_sleep 1 purge master logs before now(); show binary logs; insert into t2 values (65); diff --git a/mysql-test/t/rpl_until.test b/mysql-test/t/rpl_until.test index 45b343ace14..9e2675646ab 100644 --- a/mysql-test/t/rpl_until.test +++ b/mysql-test/t/rpl_until.test @@ -60,7 +60,7 @@ stop slave; # this should stop immideately start slave until master_log_file='master-bin.000001', master_log_pos=561; # 2 is not enough when running with valgrind -real_sleep 4 +--real_sleep 4 # here the sql slave thread should be stopped --replace_result $MASTER_MYPORT MASTER_MYPORT bin.000005 bin.000004 bin.000006 bin.000004 bin.000007 bin.000004 --replace_column 1 # 9 # 23 # 33 # From 9ed35f83fa66a15dd87834e67d32fa2150efaf7a Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Tue, 16 Aug 2005 17:10:52 +0200 Subject: [PATCH 2/7] BUG#10267 mysqltest, wrong number of loops when a script is sourced within a loop --- client/mysqltest.c | 8 ++++- mysql-test/r/mysqltest.result | 55 +++++++++++++++++++++++++++++++++++ mysql-test/t/mysqltest.test | 43 +++++++++++++++++++++++++++ 3 files changed, 105 insertions(+), 1 deletion(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 2455c4adfd3..dff91560b81 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -962,7 +962,13 @@ int do_source(struct st_query* q) *p++= 0; check_eol_junk(p); } + /* If this file has already been sourced, dont source it again. + It's already available in the q_lines cache */ + if (parser.current_line < (parser.read_lines - 1)) + return 0; return open_file(name); + + } @@ -2378,7 +2384,7 @@ int read_query(struct st_query** q_ptr) DBUG_PRINT("warning",("too long query")); DBUG_RETURN(1); } - DBUG_PRINT("info", ("query: %s", read_query_buf)); + DBUG_PRINT("info", ("query: %s", read_query_buf)); if (*p == '#') { q->type = Q_COMMENT; diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index 3b2828c3c6c..21c73f2c7bf 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -224,6 +224,61 @@ 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 mysqltest: In included file "./var/tmp/error.sql": At line 1: query 'garbage ' 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 'garbage' at line 1 + +2 = outer loop variable after while +here is the sourced script + +2 = outer loop variable before dec + +1 = outer loop variable after dec + +1 = outer loop variable after while +here is the sourced script + +1 = outer loop variable before dec + +0 = outer loop variable after dec + +2 = outer loop variable after while +here is the sourced script + +2 = outer loop variable before dec + +1 = outer loop variable after dec + +1 = outer loop variable after while +here is the sourced script + +1 = outer loop variable before dec + +0 = outer loop variable after dec + +In loop +here is the sourced script + +In loop +here is the sourced script + +In loop +here is the sourced script + +In loop +here is the sourced script + +In loop +here is the sourced script + +In loop +here is the sourced script + +In loop +here is the sourced script + +In loop +here is the sourced script + +In loop +here is the sourced script mysqltest: At line 1: Missing argument to sleep mysqltest: At line 1: Invalid argument to sleep "abc" 1 diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index 6e1b24e1232..8099510ecd1 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -524,6 +524,49 @@ echo $1; --exec echo "source var/tmp/error.sql;" | $MYSQL_TEST 2>&1 +# Test execution of source in a while loop +--exec echo "echo here is the sourced script;" > var/tmp/sourced.sql +--disable_query_log +let $outer= 2; # Number of outer loops +while ($outer) +{ + eval SELECT '$outer = outer loop variable after while' AS ""; + + --source var/tmp/sourced.sql + + eval SELECT '$outer = outer loop variable before dec' AS ""; + dec $outer; + eval SELECT '$outer = outer loop variable after dec' AS ""; +} + +let $outer= 2; # Number of outer loops +while ($outer) +{ + eval SELECT '$outer = outer loop variable after while' AS ""; + + echo here is the sourced script; + + eval SELECT '$outer = outer loop variable before dec' AS ""; + dec $outer; + eval SELECT '$outer = outer loop variable after dec' AS ""; +} + + +# Test execution of source in a while loop +--exec echo "--source var/tmp/sourced.sql" > var/tmp/sourced1.sql +--disable_abort_on_error +# Sourcing of a file within while loop, sourced file will +# source other file +let $num= 9; +while ($num) +{ + SELECT 'In loop' AS ""; + --source var/tmp/sourced1.sql + dec $num; +} +--enable_abort_on_error; +--enable_query_log + # ---------------------------------------------------------------------------- # Test sleep command # ---------------------------------------------------------------------------- From 2fc6ef3a409a7ace9ba0083882a43fd74e86ccb2 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Wed, 31 Aug 2005 17:16:05 +0200 Subject: [PATCH 3/7] BUG#11316: mysqltest, problems when assigning value with '#' to $variable - Add stricter checking of syntax in mysqltest --- client/mysqltest.c | 863 +++++++++++----------- mysql-test/r/mysqltest.result | 32 +- mysql-test/t/create.test | 2 +- mysql-test/t/create_select_tmp.test | 16 +- mysql-test/t/drop.test | 10 +- mysql-test/t/flush.test | 2 +- mysql-test/t/handler.test | 18 +- mysql-test/t/innodb.test | 2 +- mysql-test/t/mysqltest.test | 63 ++ mysql-test/t/rpl000001.test | 2 +- mysql-test/t/rpl_EE_error.test | 2 +- mysql-test/t/rpl_drop.test | 2 +- mysql-test/t/rpl_error_ignored_table.test | 4 +- mysql-test/t/rpl_loaddata.test | 2 +- 14 files changed, 541 insertions(+), 479 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index dff91560b81..d12eba2c7d1 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -75,7 +75,7 @@ #define LAZY_GUESS_BUF_SIZE 8192 #define INIT_Q_LINES 1024 #define MIN_VAR_ALLOC 32 -#define BLOCK_STACK_DEPTH 16 +#define BLOCK_STACK_DEPTH 32 #define MAX_EXPECTED_ERRORS 10 #define QUERY_SEND 1 #define QUERY_REAP 2 @@ -136,12 +136,12 @@ static uint global_expected_errors; static int record = 0, opt_sleep=0; static char *db = 0, *pass=0; -const char* user = 0, *host = 0, *unix_sock = 0, *opt_basedir="./"; +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 uint start_lineno, *lineno; -const char* manager_user="root",*manager_host=0; +const char *manager_user="root",*manager_host=0; char *manager_pass=0; int manager_port=MYSQL_MANAGER_PORT; int manager_wait_timeout=3; @@ -151,11 +151,16 @@ static char **default_argv; static const char *load_default_groups[]= { "mysqltest","client",0 }; static char line_buffer[MAX_DELIMITER], *line_buffer_pos= line_buffer; -static char* file_name_stack[MAX_INCLUDE_DEPTH]; -static int cur_file_name; -static FILE* file_stack[MAX_INCLUDE_DEPTH]; -static FILE** cur_file; -static FILE** file_stack_end; +typedef struct +{ + FILE* file; + const char *file_name; +} test_file; + +static test_file file_stack[MAX_INCLUDE_DEPTH]; +static test_file* cur_file; +static test_file* file_stack_end; + static uint lineno_stack[MAX_INCLUDE_DEPTH]; static char TMPDIR[FN_REFLEN]; static char delimiter[MAX_DELIMITER]= DEFAULT_DELIMITER; @@ -293,7 +298,7 @@ Q_COMMENT_WITH_COMMAND /* this should really be called command */ struct st_query { - char *query, *query_buf,*first_argument,*end; + char *query, *query_buf,*first_argument,*last_argument,*end; int first_word_len; my_bool abort_on_error, require_file; match_err expected_errno[MAX_EXPECTED_ERRORS]; @@ -401,7 +406,7 @@ 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); -int close_connection(struct st_query* q); +int close_connection(struct st_query*); static void set_charset(struct st_query*); VAR* var_get(const char *var_name, const char** var_name_end, my_bool raw, my_bool ignore_not_existing); @@ -427,9 +432,9 @@ 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); +static void do_eval(DYNAMIC_STRING *query_eval, const char *query); void str_to_file(const char *fname, char *str, int size); -int do_server_op(struct st_query* q,const char *op); +int do_server_op(struct st_query *q,const char *op); struct st_replace *glob_replace; static char *out_buff; @@ -453,9 +458,9 @@ 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 do_eval(DYNAMIC_STRING* query_eval, const char* query) +static void do_eval(DYNAMIC_STRING* query_eval, const char *query) { - const char* p; + const char *p; register char c; register int escaped = 0; VAR* v; @@ -512,13 +517,13 @@ static void close_cons() static void close_files() { DBUG_ENTER("close_files"); - for (; cur_file != file_stack ; cur_file--) + for (; cur_file != (file_stack-1) ; cur_file--) { - if (*cur_file != stdin && *cur_file) - my_fclose(*cur_file,MYF(0)); - char* p= file_name_stack[cur_file_name--]= 0; - if (p) - free(p); + DBUG_PRINT("info", ("file_name: %s", cur_file->file_name)); + if (cur_file->file && cur_file->file != stdin) + my_fclose(cur_file->file, MYF(0)); + my_free((gptr)cur_file->file_name, MYF(MY_ALLOW_ZERO_PTR)); + cur_file->file_name= 0; } DBUG_VOID_RETURN; } @@ -561,17 +566,17 @@ static void free_used_memory() DBUG_VOID_RETURN; } -static void die(const char* fmt, ...) +static void die(const char *fmt, ...) { va_list args; DBUG_ENTER("die"); va_start(args, fmt); if (fmt) { - fprintf(stderr, "%s: ", my_progname); - if (*cur_file && cur_file > (file_stack + 1) ) + fprintf(stderr, "mysqltest: "); + if (cur_file && cur_file != file_stack) fprintf(stderr, "In included file \"%s\": ", - file_name_stack[cur_file_name]); + cur_file->file_name); fprintf(stderr, "At line %u: ", start_lineno); vfprintf(stderr, fmt, args); fprintf(stderr, "\n"); @@ -596,7 +601,7 @@ static void abort_not_supported_test() exit(62); } -static void verbose_msg(const char* fmt, ...) +static void verbose_msg(const char *fmt, ...) { va_list args; DBUG_ENTER("verbose_msg"); @@ -605,7 +610,7 @@ static void verbose_msg(const char* fmt, ...) va_start(args, fmt); - fprintf(stderr, "%s: At line %u: ", my_progname, start_lineno); + fprintf(stderr, "mysqltest: At line %u: ", start_lineno); vfprintf(stderr, fmt, args); fprintf(stderr, "\n"); va_end(args); @@ -615,12 +620,12 @@ static void verbose_msg(const char* fmt, ...) void init_parser() { - parser.current_line = parser.read_lines = 0; - memset(&var_reg,0, sizeof(var_reg)); + parser.current_line= parser.read_lines= 0; + memset(&var_reg, 0, sizeof(var_reg)); } -int dyn_string_cmp(DYNAMIC_STRING* ds, const char* fname) +int dyn_string_cmp(DYNAMIC_STRING* ds, const char *fname) { MY_STAT stat_info; char *tmp, *res_ptr; @@ -686,7 +691,7 @@ err: DBUG_RETURN(res); } -static int check_result(DYNAMIC_STRING* ds, const char* fname, +static int check_result(DYNAMIC_STRING* ds, const char *fname, my_bool require_option) { int error = 0; @@ -714,7 +719,7 @@ static int check_result(DYNAMIC_STRING* ds, const char* fname, } -VAR* var_get(const char* var_name, const char** var_name_end, my_bool raw, +VAR* var_get(const char *var_name, const char** var_name_end, my_bool raw, my_bool ignore_not_existing) { int digit; @@ -727,7 +732,7 @@ VAR* var_get(const char* var_name, const char** var_name_end, my_bool raw, digit = *++var_name - '0'; if (digit < 0 || digit >= 10) { - const char* save_var_name = var_name, *end; + const char *save_var_name = var_name, *end; uint length; end = (var_name_end) ? *var_name_end : 0; while (my_isvar(charset_info,*var_name) && var_name != end) @@ -769,7 +774,7 @@ err: DBUG_RETURN(0); } -static VAR *var_obtain(const char* name, int len) +static VAR *var_obtain(const char *name, int len) { VAR* v; if ((v = (VAR*)hash_search(&var_hash, name, len))) @@ -806,8 +811,10 @@ int var_set(const char *var_name, const char *var_name_end, } -int open_file(const char* name) +int open_file(const char *name) { + DBUG_ENTER("open_file"); + DBUG_PRINT("enter", ("name: %s", name)); char buff[FN_REFLEN]; if (!test_if_hard_path(name)) { @@ -816,13 +823,17 @@ int open_file(const char* name) } fn_format(buff,name,"","",4); - if (*cur_file && cur_file == file_stack_end) + if (cur_file == file_stack_end) die("Source directives are nesting too deep"); - if (!(*++cur_file = my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(0)))) + cur_file++; + if (!(cur_file->file = my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(0)))) + { + cur_file--; die("Could not open file %s", buff); + } + cur_file->file_name= my_strdup(buff, MYF(MY_FAE)); *++lineno=1; - file_name_stack[++cur_file_name]= strdup(buff); - return 0; + DBUG_RETURN(0); } @@ -833,14 +844,15 @@ int open_file(const char* name) int check_eol_junk(const char *eol) { - char *p= (char*)eol; + DBUG_ENTER("check_eol_junk"); + DBUG_PRINT("enter", ("eol: %s", eol)); + const char *p= eol; /* Remove all spacing chars except new line */ - while (*p && my_isspace(charset_info,*p) && (*p != '\n')) + while (*p && my_isspace(charset_info, *p) && (*p != '\n')) p++; /* Check for extra delimiter */ - size_t l= strlen(delimiter); - if (*p && strlen(p) >= l && !strncmp(p, delimiter, l) ) + if (*p && !strncmp(p, delimiter, delimiter_length)) die("Extra delimiter \"%s\" found", delimiter); /* Allow trailing # comment */ @@ -850,12 +862,12 @@ int check_eol_junk(const char *eol) die("Missing delimiter"); die("End of line junk detected: \"%s\"", p); } - return 0; + DBUG_RETURN(0); } /* ugly long name, but we are following the convention */ -int do_wait_for_slave_to_stop(struct st_query* q __attribute__((unused))) +int do_wait_for_slave_to_stop(struct st_query *q __attribute__((unused))) { MYSQL* mysql = &cur_con->mysql; for (;;) @@ -880,57 +892,56 @@ int do_wait_for_slave_to_stop(struct st_query* q __attribute__((unused))) break; my_sleep(SLAVE_POLL_INTERVAL); } - return check_eol_junk(q->first_argument); + return 0; } -int do_require_manager(struct st_query* q) +int do_require_manager(struct st_query *query __attribute__((unused)) ) { if (!manager) abort_not_supported_test(); - return check_eol_junk(q->first_argument); + return 0; } #ifndef EMBEDDED_LIBRARY -int do_server_start(struct st_query* q) +int do_server_start(struct st_query *q) { - check_eol_junk(q->first_argument); - return do_server_op(q,"start"); + return do_server_op(q, "start"); } -int do_server_stop(struct st_query* q) +int do_server_stop(struct st_query *q) { - check_eol_junk(q->first_argument); - return do_server_op(q,"stop"); + return do_server_op(q, "stop"); } -int do_server_op(struct st_query* q,const char* op) +int do_server_op(struct st_query *q, const char *op) { - char* p=q->first_argument; - char com_buf[256],*com_p; + char *p= q->first_argument; + char com_buf[256], *com_p; if (!manager) { die("Manager is not initialized, manager commands are not possible"); } - com_p=strmov(com_buf,op); - com_p=strmov(com_p,"_exec "); + com_p= strmov(com_buf,op); + com_p= strmov(com_p,"_exec "); if (!*p) - die("Missing server name in server_%s",op); - while (*p && !my_isspace(charset_info,*p)) + die("Missing server name in server_%s", op); + while (*p && !my_isspace(charset_info, *p)) *com_p++= *p++; - *com_p++=' '; - com_p=int10_to_str(manager_wait_timeout,com_p,10); - *com_p++ = '\n'; - *com_p=0; - if (mysql_manager_command(manager,com_buf,(int)(com_p-com_buf))) - die("Error in command: %s(%d)",manager->last_error,manager->last_errno); + *com_p++= ' '; + com_p= int10_to_str(manager_wait_timeout, com_p, 10); + *com_p++= '\n'; + *com_p= 0; + if (mysql_manager_command(manager, com_buf, (int)(com_p-com_buf))) + die("Error in command: %s(%d)", manager->last_error, manager->last_errno); while (!manager->eof) { - if (mysql_manager_fetch_line(manager,com_buf,sizeof(com_buf))) + if (mysql_manager_fetch_line(manager, com_buf, sizeof(com_buf))) die("Error fetching result line: %s(%d)", manager->last_error, manager->last_errno); } - return check_eol_junk(p); + q->last_argument= p; + return 0; } #endif @@ -940,7 +951,7 @@ int do_server_op(struct st_query* q,const char* op) SYNOPSIS do_source() - q called command + query called command DESCRIPTION source @@ -949,26 +960,24 @@ int do_server_op(struct st_query* q,const char* op) */ -int do_source(struct st_query* q) +int do_source(struct st_query *query) { - char* p=q->first_argument, *name; + char *p= query->first_argument, *name; if (!*p) die("Missing file name in source"); - name = p; + name= p; while (*p && !my_isspace(charset_info,*p)) p++; if (*p) - { *p++= 0; - check_eol_junk(p); - } - /* If this file has already been sourced, dont source it again. - It's already available in the q_lines cache */ + query->last_argument= p; + /* + If this file has already been sourced, dont source it again. + It's already available in the q_lines cache + */ if (parser.current_line < (parser.read_lines - 1)) return 0; return open_file(name); - - } @@ -977,7 +986,7 @@ int do_source(struct st_query* q) SYNOPSIS do_exec() - q called command + query called command DESCRIPTION exec @@ -989,24 +998,25 @@ int do_source(struct st_query* q) */ -static void do_exec(struct st_query* q) +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= q->first_argument; + char *cmd= query->first_argument; DBUG_ENTER("do_exec"); while (*cmd && my_isspace(charset_info, *cmd)) cmd++; if (!*cmd) die("Missing argument in exec"); + query->last_argument= query->end; DBUG_PRINT("info", ("Executing '%s'", cmd)); - if (!(res_file= popen(cmd, "r")) && q->abort_on_error) + if (!(res_file= popen(cmd, "r")) && query->abort_on_error) die("popen(\"%s\", \"r\") failed", cmd); if (disable_result_log) @@ -1019,7 +1029,7 @@ static void do_exec(struct st_query* q) } else { - if (q->record_file[0]) + if (query->record_file[0]) { init_dynamic_string(&ds_tmp, "", 16384, 65536); ds= &ds_tmp; @@ -1033,20 +1043,20 @@ static void do_exec(struct st_query* q) error= pclose(res_file); if (error != 0) { - uint i, status= WEXITSTATUS(error); + uint status= WEXITSTATUS(error), i; my_bool ok= 0; - if (q->abort_on_error) + if (query->abort_on_error) die("command \"%s\" failed", cmd); DBUG_PRINT("info", ("error: %d, status: %d", error, status)); - for (i=0 ; i < q->expected_errors ; i++) + for (i= 0; i < query->expected_errors; i++) { DBUG_PRINT("info", ("expected error: %d", - q->expected_errno[i].code.errnum)); - if ((q->expected_errno[i].type == ERR_ERRNO) && - (q->expected_errno[i].code.errnum == status)) + query->expected_errno[i].code.errnum)); + if ((query->expected_errno[i].type == ERR_ERRNO) && + (query->expected_errno[i].code.errnum == status)) { ok= 1; verbose_msg("command \"%s\" failed with expected error: %d", @@ -1057,12 +1067,12 @@ static void do_exec(struct st_query* q) die("command \"%s\" failed with wrong error: %d", cmd, status); } - else if (q->expected_errno[0].type == ERR_ERRNO && - q->expected_errno[0].code.errnum != 0) + else if (query->expected_errno[0].type == ERR_ERRNO && + query->expected_errno[0].code.errnum != 0) { /* Error code we wanted was != 0, i.e. not an expected success */ die("command \"%s\" succeeded - should have failed with errno %d...", - cmd, q->expected_errno[0].code.errnum); + cmd, query->expected_errno[0].code.errnum); } if (!disable_result_log) @@ -1072,14 +1082,14 @@ static void do_exec(struct st_query* q) if (record) { - if (!q->record_file[0] && !result_file) + if (!query->record_file[0] && !result_file) die("Missing result file"); if (!result_file) - str_to_file(q->record_file, ds->str, ds->length); + str_to_file(query->record_file, ds->str, ds->length); } - else if (q->record_file[0]) + else if (query->record_file[0]) { - error= check_result(ds, q->record_file, q->require_file); + error= check_result(ds, query->record_file, query->require_file); } if (ds == &ds_tmp) dynstr_free(&ds_tmp); @@ -1087,7 +1097,7 @@ static void do_exec(struct st_query* q) } -int var_query_set(VAR* v, const char* p, const char** p_end) +int var_query_set(VAR* v, const char *p, const char** p_end) { char* end = (char*)((p_end && *p_end) ? *p_end : p + strlen(p)); MYSQL_RES *res; @@ -1150,7 +1160,7 @@ void var_copy(VAR* dest, VAR* src) memcpy(dest->str_val,src->str_val,src->str_val_len+1); } -int eval_expr(VAR* v, const char* p, const char** p_end) +int eval_expr(VAR* v, const char *p, const char** p_end) { VAR* vp; if (*p == '$') @@ -1192,69 +1202,57 @@ int eval_expr(VAR* v, const char* p, const char** p_end) } +enum enum_operator +{ + DO_DEC, + DO_INC +}; + /* - Increase the value of a variable + Decrease or increase the value of a variable SYNOPSIS - do_inc() - q called command + do_modify_var() + query called command + name human readable name of operator + operator operation to perform on the var DESCRIPTION + dec $var_name inc $var_name */ -int do_inc(struct st_query* q) +int do_modify_var(struct st_query *query, const char *name, + enum enum_operator operator) { - char* p=q->first_argument; + char *p= query->first_argument; VAR* v; if (!*p) - die("Missing arguments to inc"); + die("Missing arguments to %s", name); if (*p != '$') - die("First argument to inc must be a variable (start with $)"); - v = var_get(p, 0, 1, 0); - v->int_val++; - v->int_dirty = 1; - while (*p && !my_isspace(charset_info,*p)) - p++; - check_eol_junk(p); + die("First argument to %s must be a variable (start with $)", name); + v= var_get(p, &p, 1, 0); + switch (operator){ + case DO_DEC: + v->int_val--; + break; + case DO_INC: + v->int_val++; + break; + default: + die("Invalid operator to do_operator"); + break; + } + v->int_dirty= 1; + query->last_argument= ++p; return 0; } -/* - Decrease the value of a variable - - SYNOPSIS - do_dec() - q called command - - DESCRIPTION - dec $var_name - -*/ - -int do_dec(struct st_query* q) +int do_system(struct st_query *q) { - char* p=q->first_argument; - VAR* v; - if (!*p) - die("Missing arguments to dec"); - if (*p != '$') - die("First argument to dec must be a variable (start with $)"); - v = var_get(p, 0, 1, 0); - v->int_val--; - v->int_dirty = 1; - while (*p && !my_isspace(charset_info,*p)) - p++; - check_eol_junk(p); - return 0; -} - - -int do_system(struct st_query* q) -{ - char* p=q->first_argument; + char *p=q->first_argument; VAR v; var_init(&v, 0, 0, 0, 0); eval_expr(&v, p, 0); /* NULL terminated */ @@ -1277,6 +1275,7 @@ int do_system(struct st_query* q) else die("Missing arguments to system, nothing to do!"); var_free(&v); + q->last_argument= q->end; return 0; } @@ -1300,10 +1299,10 @@ int do_system(struct st_query* q) */ -int do_echo(struct st_query* q) +int do_echo(struct st_query *q) { - char* p=q->first_argument; - DYNAMIC_STRING *ds= NULL; + char *p= q->first_argument; + DYNAMIC_STRING *ds; DYNAMIC_STRING ds_tmp; VAR v; var_init(&v,0,0,0,0); @@ -1311,7 +1310,7 @@ int do_echo(struct st_query* q) if (q->record_file[0]) { init_dynamic_string(&ds_tmp, "", 256, 512); - ds = &ds_tmp; + ds= &ds_tmp; } else ds= &ds_res; @@ -1323,40 +1322,27 @@ int do_echo(struct st_query* q) var_free(&v); if (ds == &ds_tmp) dynstr_free(&ds_tmp); + q->last_argument= q->end; return 0; } -int do_sync_with_master2(const char* p) +int do_sync_with_master2(long offset) { MYSQL_RES* res; MYSQL_ROW row; - MYSQL* mysql = &cur_con->mysql; + MYSQL* mysql= &cur_con->mysql; char query_buf[FN_REFLEN+128]; - int offset= 0, tries= 0; + int tries= 0; int rpl_parse; if (!master_pos.file[0]) { die("Line %u: Calling 'sync_with_master' without calling 'save_master_pos'", start_lineno); } - rpl_parse = mysql_rpl_parse_enabled(mysql); + rpl_parse= mysql_rpl_parse_enabled(mysql); mysql_disable_rpl_parse(mysql); - const char* offset_str= p; - /* Step until end of integer arg and check it */ - while (*p && !my_isspace(charset_info, *p)) - { - if (!my_isdigit(charset_info, *p)) - die("Invalid integer argument \"%s\"", offset_str); - p++; - } - check_eol_junk(p); - - if (*offset_str) - offset = atoi(offset_str); - - sprintf(query_buf, "select master_pos_wait('%s', %ld)", master_pos.file, master_pos.pos + offset); @@ -1366,10 +1352,10 @@ wait_for_position: die("line %u: failed in %s: %d: %s", start_lineno, query_buf, mysql_errno(mysql), mysql_error(mysql)); - if (!(last_result = res = mysql_store_result(mysql))) + if (!(last_result= res= mysql_store_result(mysql))) die("line %u: mysql_store_result() returned NULL for '%s'", start_lineno, query_buf); - if (!(row = mysql_fetch_row(res))) + if (!(row= mysql_fetch_row(res))) die("line %u: empty result in %s", start_lineno, query_buf); if (!row[0]) { @@ -1394,9 +1380,23 @@ wait_for_position: return 0; } -int do_sync_with_master(struct st_query* q) +int do_sync_with_master(struct st_query *query) { - return do_sync_with_master2(q->first_argument); + long offset= 0; + char *p= query->first_argument; + const char *offset_start= p; + const char *offset_end= query->end; + int error; + if (*offset_start) + { + for (; my_isdigit(charset_info, *p); p++) + offset = offset * 10 + *p - '0'; + + if(*p && !my_isspace(charset_info, *p)) + die("Invalid integer argument \"%s\"", offset_start); + query->last_argument= p; + } + return do_sync_with_master2(offset); } int do_save_master_pos() @@ -1435,7 +1435,7 @@ int do_save_master_pos() SYNOPSIS do_let() - q called command + query called command DESCRIPTION let $= @@ -1449,34 +1449,32 @@ int do_save_master_pos() Program will die if error detected */ -int do_let(struct st_query* q) +int do_let(struct st_query *query) { - char* p=q->first_argument; + char *p= query->first_argument; char *var_name, *var_name_end, *var_val_start; /* Find */ if (!*p) die("Missing arguments to let"); - var_name = p; - while (*p && *p != '=' && !my_isspace(charset_info,*p)) + var_name= p; + while (*p && (*p != '=') && !my_isspace(charset_info,*p)) p++; - var_name_end = p; - if (var_name+1==var_name_end) + var_name_end= p; + if (var_name+1 == var_name_end) die("Missing variable name in let"); - while (*p && (*p != '=' || my_isspace(charset_info,*p))) + while (my_isspace(charset_info,*p)) p++; - if (*p == '=') - p++; - else + if (*p++ != '=') die("Missing assignment operator in let"); /* Find start of */ while (*p && my_isspace(charset_info,*p)) p++; - var_val_start = p; - + var_val_start= p; + query->last_argument= query->end; /* Assign var_val to var_name */ - return var_set(var_name, var_name_end, var_val_start, q->end); + return var_set(var_name, var_name_end, var_val_start, query->end); } @@ -1495,28 +1493,25 @@ int var_set_errno(int sql_errno) } -int do_rpl_probe(struct st_query* q) +int do_rpl_probe(struct st_query *query __attribute__((unused))) { DBUG_ENTER("do_rpl_probe"); if (mysql_rpl_probe(&cur_con->mysql)) die("Failed in mysql_rpl_probe(): '%s'", mysql_error(&cur_con->mysql)); - check_eol_junk(q->first_argument); DBUG_RETURN(0); } -int do_enable_rpl_parse(struct st_query* q) +int do_enable_rpl_parse(struct st_query *query __attribute__((unused))) { mysql_enable_rpl_parse(&cur_con->mysql); - check_eol_junk(q->first_argument); return 0; } -int do_disable_rpl_parse(struct st_query* q) +int do_disable_rpl_parse(struct st_query *query __attribute__((unused))) { mysql_disable_rpl_parse(&cur_con->mysql); - check_eol_junk(q->first_argument); return 0; } @@ -1535,57 +1530,52 @@ int do_disable_rpl_parse(struct st_query* q) */ -int do_sleep(struct st_query* q, my_bool real_sleep) +int do_sleep(struct st_query *query, my_bool real_sleep) { - char *p=q->first_argument; - while (*p && my_isspace(charset_info,*p)) + int error= 0; + char *p= query->first_argument; + char *sleep_start, *sleep_end= query->end; + double sleep_val; + + while (my_isspace(charset_info, *p)) p++; if (!*p) die("Missing argument to sleep"); + sleep_start= p; + /* Check that arg starts with a digit, not handled by my_strtod */ + if (!my_isdigit(charset_info, *sleep_start)) + die("Invalid argument to sleep \"%s\"", query->first_argument); + sleep_val= my_strtod(sleep_start, &sleep_end, &error); + if (error) + die("Invalid argument to sleep \"%s\"", query->first_argument); + + /* Fixed sleep time selected by --sleep option */ if (opt_sleep && !real_sleep) - my_sleep(opt_sleep * 1000000L); - else - { - int err= 0; - double val=1; - const char* val_str= p; - while (*p && !my_isspace(charset_info,*p)) - { - if (!my_isdigit(charset_info, *p) && !my_ispunct(charset_info, *p)) - err= 1; - p++; - } - if (!err) - val= my_strtod(val_str, &p, &err); - if (err) - die("Invalid argument to sleep \"%s\"", q->first_argument); - my_sleep((ulong) (val * 1000000L)); - } - return check_eol_junk(p++); + sleep_val= opt_sleep; + + my_sleep((ulong) (sleep_val * 1000000L)); + query->last_argument= sleep_end; + return 0; } -static void get_file_name(char *filename, struct st_query* q) +static void get_file_name(char *filename, struct st_query *q) { - - - char* p=q->first_argument, *name; + char *p= q->first_argument, *name; if (!*p) die("Missing file name argument"); - name = p; + name= p; while (*p && !my_isspace(charset_info,*p)) p++; if (*p) - { *p++= 0; - check_eol_junk(p); - } + q->last_argument= p; strmake(filename, name, FN_REFLEN); } -static void set_charset(struct st_query* q) +static void set_charset(struct st_query *q) { - char* charset_name= q->first_argument; - char* p; + char *charset_name= q->first_argument; + char *p; if (!charset_name || !*charset_name) die("Missing charset name in 'character_set'"); @@ -1594,19 +1584,16 @@ static void set_charset(struct st_query* q) while (*p && !my_isspace(charset_info,*p)) p++; if(*p) - { *p++= 0; - check_eol_junk(p); - } - + q->last_argument= p; charset_info= get_charset_by_csname(charset_name,MY_CS_PRIMARY,MYF(MY_WME)); if (!charset_info) abort_not_supported_test(); } -static uint get_errcodes(match_err *to,struct st_query* q) +static uint get_errcodes(match_err *to,struct st_query *q) { - char* p= q->first_argument; + char *p= q->first_argument; uint count= 0; DBUG_ENTER("get_errcodes"); @@ -1636,7 +1623,7 @@ static uint get_errcodes(match_err *to,struct st_query* q) } count++; } while (*(p++) == ','); - + q->last_argument= (p - 1); to[count].type= ERR_EMPTY; /* End of data */ DBUG_RETURN(count); } @@ -1650,7 +1637,7 @@ static uint get_errcodes(match_err *to,struct st_query* q) static char *get_string(char **to_ptr, char **from_ptr, - struct st_query* q) + struct st_query *q) { reg1 char c,sep; char *to= *to_ptr, *from= *from_ptr, *start=to; @@ -1733,7 +1720,7 @@ static char *get_string(char **to_ptr, char **from_ptr, static void get_replace(struct st_query *q) { uint i; - char *from=q->first_argument; + char *from= q->first_argument; char *buff,*start; char word_end_chars[256],*pos; POINTER_ARRAY to_array,from_array; @@ -1751,7 +1738,7 @@ static void get_replace(struct st_query *q) char *to=buff; to=get_string(&buff, &from, q); if (!*from) - die("Wrong number of arguments to replace in %s", q->query); + die("Wrong number of arguments to replace_result in '%s'", q->query); insert_pointer_name(&from_array,to); to=get_string(&buff, &from, q); insert_pointer_name(&to_array,to); @@ -1765,10 +1752,11 @@ static void get_replace(struct st_query *q) (uint) from_array.typelib.count, word_end_chars)) || initialize_replace_buffer()) - die("Can't initialize replace from %s", q->query); + die("Can't initialize replace from '%s'", q->query); free_pointer_array(&from_array); free_pointer_array(&to_array); my_free(start, MYF(0)); + q->last_argument= q->end; DBUG_VOID_RETURN; } @@ -1784,30 +1772,18 @@ void free_replace() DBUG_VOID_RETURN; } -int select_connection(char *p) + +int select_connection_name(const char *name) { - char* name; struct connection *con; - DBUG_ENTER("select_connection"); - DBUG_PRINT("enter",("name: '%s'",p)); + DBUG_ENTER("select_connection2"); + DBUG_PRINT("enter",("name: '%s'", name)); - if (!*p) - die("Missing connection name in connect"); - name = p; - while (*p && !my_isspace(charset_info,*p)) - p++; - - if (*p) - { - *p++= 0; - check_eol_junk(p); - } - - for (con = cons; con < next_con; con++) + for (con= cons; con < next_con; con++) { if (!strcmp(con->name, name)) { - cur_con = con; + cur_con= con; DBUG_RETURN(0); } } @@ -1815,26 +1791,42 @@ int select_connection(char *p) DBUG_RETURN(1); /* Never reached */ } -int close_connection(struct st_query* q) + +int select_connection(struct st_query *query) { - char* p=q->first_argument, *name; + char *name; + char *p= query->first_argument; + DBUG_ENTER("select_connection"); + + if (!*p) + die("Missing connection name in connect"); + name= p; + while (*p && !my_isspace(charset_info,*p)) + p++; + if (*p) + *p++= 0; + query->last_argument= p; + return select_connection_name(name); +} + + +int close_connection(struct st_query *q) +{ + char *p= q->first_argument, *name; struct connection *con; DBUG_ENTER("close_connection"); DBUG_PRINT("enter",("name: '%s'",p)); if (!*p) die("Missing connection name in connect"); - name = p; + name= p; while (*p && !my_isspace(charset_info,*p)) p++; if (*p) - { *p++= 0; - check_eol_junk(p); - } - - for (con = cons; con < next_con; con++) + q->last_argument= p; + for (con= cons; con < next_con; con++) { if (!strcmp(con->name, name)) { @@ -1864,21 +1856,21 @@ int close_connection(struct st_query* q) ) are delimiters/terminators */ -char* safe_get_param(char* str, char** arg, const char* msg) +char* safe_get_param(char *str, char** arg, const char *msg) { DBUG_ENTER("safe_get_param"); while (*str && my_isspace(charset_info,*str)) str++; - *arg = str; + *arg= str; for (; *str && *str != ',' && *str != ')' ; str++) { if (my_isspace(charset_info,*str)) - *str = 0; + *str= 0; } if (!*str) die(msg); - *str++ = 0; + *str++= 0; DBUG_RETURN(str); } @@ -1895,9 +1887,9 @@ void init_manager() } #endif -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* con, const char *host, const char *user, + const char *pass, + const char *db, int port, const char *sock) { int con_error = 1; int i; @@ -1915,14 +1907,14 @@ int safe_connect(MYSQL* con, const char* host, const char* user, } -int do_connect(struct st_query* q) +int do_connect(struct st_query *q) { - char* con_name, *con_user,*con_pass, *con_host, *con_port_str, + char *con_name, *con_user,*con_pass, *con_host, *con_port_str, *con_db, *con_sock; - char* p=q->first_argument; + char *p= q->first_argument; char buff[FN_REFLEN]; int con_port; - int free_con_sock = 0; + int free_con_sock= 0; DBUG_ENTER("do_connect"); DBUG_PRINT("enter",("connect: %s",p)); @@ -1930,41 +1922,41 @@ int do_connect(struct st_query* q) if (*p != '(') die("Syntax error in connect - expected '(' found '%c'", *p); p++; - p = safe_get_param(p, &con_name, "missing connection name"); - p = safe_get_param(p, &con_host, "missing connection host"); - p = safe_get_param(p, &con_user, "missing connection user"); - p = safe_get_param(p, &con_pass, "missing connection password"); - p = safe_get_param(p, &con_db, "missing connection db"); + p= safe_get_param(p, &con_name, "missing connection name"); + p= safe_get_param(p, &con_host, "missing connection host"); + p= safe_get_param(p, &con_user, "missing connection user"); + p= safe_get_param(p, &con_pass, "missing connection password"); + p= safe_get_param(p, &con_db, "missing connection db"); if (!*p || *p == ';') /* Default port and sock */ { - con_port=port; - con_sock=(char*) unix_sock; + con_port= port; + con_sock= (char*) unix_sock; } else { VAR* var_port, *var_sock; - p = safe_get_param(p, &con_port_str, "missing connection port"); + p= safe_get_param(p, &con_port_str, "missing connection port"); if (*con_port_str == '$') { - if (!(var_port = var_get(con_port_str, 0, 0, 0))) + if (!(var_port= var_get(con_port_str, 0, 0, 0))) die("Unknown variable '%s'", con_port_str+1); - con_port = var_port->int_val; + con_port= var_port->int_val; } else - con_port=atoi(con_port_str); - p = safe_get_param(p, &con_sock, "missing connection socket"); + con_port= atoi(con_port_str); + p= safe_get_param(p, &con_sock, "missing connection socket"); if (*con_sock == '$') { - if (!(var_sock = var_get(con_sock, 0, 0, 0))) + if (!(var_sock= var_get(con_sock, 0, 0, 0))) die("Unknown variable '%s'", con_sock+1); - if (!(con_sock = (char*)my_malloc(var_sock->str_val_len+1, MYF(0)))) + if (!(con_sock= (char*)my_malloc(var_sock->str_val_len+1, MYF(0)))) die("Out of memory"); - free_con_sock = 1; + free_con_sock= 1; memcpy(con_sock, var_sock->str_val, var_sock->str_val_len); - con_sock[var_sock->str_val_len] = 0; + con_sock[var_sock->str_val_len]= 0; } } - check_eol_junk(p); + q->last_argument= p; if (next_con == cons_end) die("Connection limit exhausted - increase MAX_CONS in mysqltest.c"); @@ -1984,33 +1976,34 @@ int do_connect(struct st_query* q) if (con_sock && !free_con_sock && *con_sock && *con_sock != FN_LIBCHAR) con_sock=fn_format(buff, con_sock, TMPDIR, "",0); if (!con_db[0]) - con_db=db; + con_db= db; /* Special database to allow one to connect without a database name */ if (con_db && !strcmp(con_db,"*NO-ONE*")) - con_db=0; + con_db= 0; 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 (!(next_con->name = my_strdup(con_name, MYF(MY_WME)))) + if (!(next_con->name= my_strdup(con_name, MYF(MY_WME)))) die(NullS); - cur_con = next_con++; + cur_con= next_con++; if (free_con_sock) my_free(con_sock, MYF(MY_WME)); DBUG_RETURN(0); } -int do_done(struct st_query* q) +int do_done(struct st_query *q) { - /* Dummy statement to eliminate compiler warning */ - q->type = Q_END_BLOCK; - /* Check if empty block stack */ if (cur_block == block_stack) + { + if (*q->query != '}') + die("Stray 'end' command - end of block before beginning"); die("Stray '}' - end of block before beginning"); + } /* Test if inner block has been executed */ if (cur_block->ok && cur_block->cmd == Q_WHILE) @@ -2025,16 +2018,16 @@ int do_done(struct st_query* q) cur_block--; parser.current_line++; } - return check_eol_junk(q->first_argument); -; + return 0; } -int do_block(enum enum_commands cmd, struct st_query* q) +int do_block(enum enum_commands cmd, struct st_query *q) { - char* p=q->first_argument; - const char* expr_start, *expr_end; + char *p= q->first_argument; + const char *expr_start, *expr_end; VAR v; + const char *cmd_name= (cmd == Q_WHILE ? "while" : "if"); /* Check stack overflow */ if (cur_block == block_stack_end) @@ -2054,20 +2047,20 @@ int do_block(enum enum_commands cmd, struct st_query* q) } /* Parse and evaluate test expression */ - expr_start = strchr(p, '('); + expr_start= strchr(p, '('); if (!expr_start) - die("missing '(' in while"); - expr_end = strrchr(expr_start, ')'); + die("missing '(' in %s", cmd_name); + expr_end= strrchr(expr_start, ')'); if (!expr_end) - die("missing ')' in while"); + die("missing ')' in %s", cmd_name); p= (char*)expr_end+1; while (*p && my_isspace(charset_info, *p)) p++; - if (*p=='{') - die("Missing newline between while and '{'"); + if (*p == '{') + die("Missing newline between %s and '{'", cmd_name); if (*p) - die("Missing '{' after while. Found \"%s\"", p); + die("Missing '{' after %s. Found \"%s\"", cmd_name, p); var_init(&v,0,0,0,0); eval_expr(&v, ++expr_start, &expr_end); @@ -2114,7 +2107,7 @@ my_bool end_of_query(int c) return 0; for (i= 1; i < delimiter_length && - (c= my_getc(*cur_file)) == *(delimiter + i); + (c= my_getc(cur_file->file)) == *(delimiter + i); i++) tmp[i]= c; @@ -2153,10 +2146,10 @@ my_bool end_of_query(int c) */ -int read_line(char* buf, int size) +int read_line(char *buf, int size) { int c; - char* p= buf, *buf_end= buf + size - 1; + char *p= buf, *buf_end= buf + size - 1; int no_save= 0; enum {R_NORMAL, R_Q1, R_ESC_Q_Q1, R_ESC_Q_Q2, R_ESC_SLASH_Q1, R_ESC_SLASH_Q2, @@ -2167,16 +2160,14 @@ int read_line(char* buf, int size) for (; p < buf_end ;) { no_save= 0; - c= my_getc(*cur_file); - if (feof(*cur_file)) + c= my_getc(cur_file->file); + if (feof(cur_file->file)) { found_eof: - if ((*cur_file) != stdin) - my_fclose(*cur_file, MYF(0)); - cur_file--; - char* p= file_name_stack[cur_file_name--]= 0; - if (p) - free(p); + if (cur_file->file != stdin) + my_fclose(cur_file->file, MYF(0)); + my_free((gptr)cur_file->file_name, MYF(MY_ALLOW_ZERO_PTR)); + cur_file->file_name= 0; lineno--; start_lineno= *lineno; if (cur_file == file_stack) @@ -2191,6 +2182,7 @@ int read_line(char* buf, int size) } DBUG_RETURN(1); } + cur_file--; continue; } @@ -2313,9 +2305,9 @@ int read_line(char* buf, int size) for (i= 1; i < charlen; i++) { - if (feof(*cur_file)) + if (feof(cur_file->file)) goto found_eof; /* FIXME: could we just break here?! */ - c= my_getc(*cur_file); + c= my_getc(cur_file->file); *p++ = c; } if (! my_ismbchar(charset_info, mb_start, p)) @@ -2332,13 +2324,14 @@ int read_line(char* buf, int size) } } *p= 0; /* Always end with \0 */ - DBUG_RETURN(feof(*cur_file)); + DBUG_RETURN(feof(cur_file->file)); } /* Create a query from a set of lines SYNOPSIS + read_query() q_ptr pointer where to return the new query DESCRIPTION @@ -2360,7 +2353,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, *p1; struct st_query* q; DBUG_ENTER("read_query"); @@ -2377,7 +2370,7 @@ int read_query(struct st_query** q_ptr) q->require_file= 0; q->first_word_len= 0; - q->type = Q_UNKNOWN; + q->type= Q_UNKNOWN; q->query_buf= q->query= 0; if (read_line(read_query_buf, sizeof(read_query_buf))) { @@ -2387,7 +2380,7 @@ int read_query(struct st_query** q_ptr) DBUG_PRINT("info", ("query: %s", read_query_buf)); if (*p == '#') { - q->type = Q_COMMENT; + q->type= Q_COMMENT; /* This goto is to avoid losing the "expected error" info. */ goto end; } @@ -2414,10 +2407,10 @@ int read_query(struct st_query** q_ptr) p++; for (; my_isdigit(charset_info, *p); p++) expected_errno = expected_errno * 10 + *p - '0'; - q->expected_errno[0].code.errnum = expected_errno; + q->expected_errno[0].code.errnum= expected_errno; q->expected_errno[0].type= ERR_ERRNO; q->expected_errno[1].type= ERR_EMPTY; - q->expected_errors=1; + q->expected_errors= 1; } else if (*p == 'S') /* SQLSTATE */ { @@ -2428,10 +2421,9 @@ int read_query(struct st_query** q_ptr) q->expected_errno[0].code.sqlstate[i]= '\0'; q->expected_errno[0].type= ERR_SQLSTATE; q->expected_errno[1].type= ERR_EMPTY; - q->expected_errors=1; + q->expected_errors= 1; } } - while (*p && my_isspace(charset_info, *p)) p++ ; if (*p == '@') @@ -2590,7 +2582,9 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)), argument= buff; } fn_format(buff, argument, "", "", 4); - if (!(*++cur_file = my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(MY_WME)))) + DBUG_ASSERT(cur_file->file == 0); + if (!(cur_file->file= + my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(MY_WME)))) die("Could not open %s: errno = %d", argument, errno); break; } @@ -2676,7 +2670,7 @@ int parse_args(int argc, char **argv) return 0; } -char* safe_str_append(char* buf, const char* str, int size) +char* safe_str_append(char *buf, const char *str, int size) { int i,c ; for (i = 0; (c = *str++) && i < size - 1; i++) @@ -2685,7 +2679,7 @@ char* safe_str_append(char* buf, const char* str, int size) return buf; } -void str_to_file(const char* fname, char* str, int size) +void str_to_file(const char *fname, char *str, int size) { int fd; char buff[FN_REFLEN]; @@ -2704,7 +2698,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 reject_dump(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); @@ -2879,68 +2873,61 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags) if (q->abort_on_error) die("query '%s' failed: %d: %s", query, mysql_errno(mysql), mysql_error(mysql)); - else + + for (i=0 ; (uint) i < q->expected_errors ; i++) { - for (i=0 ; (uint) i < q->expected_errors ; i++) - { - if (((q->expected_errno[i].type == ERR_ERRNO) && - (q->expected_errno[i].code.errnum == mysql_errno(mysql))) || - ((q->expected_errno[i].type == ERR_SQLSTATE) && - (strcmp(q->expected_errno[i].code.sqlstate,mysql_sqlstate(mysql)) == 0))) - { - if (i == 0 && q->expected_errors == 1) - { - /* Only log error if there is one possible error */ - dynstr_append_mem(ds,"ERROR ",6); - replace_dynstr_append_mem(ds, mysql_sqlstate(mysql), - strlen(mysql_sqlstate(mysql))); - dynstr_append_mem(ds, ": ", 2); - replace_dynstr_append_mem(ds,mysql_error(mysql), - strlen(mysql_error(mysql))); - 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"); - goto end; /* Ok */ - } - } - DBUG_PRINT("info",("i: %d expected_errors: %d", i, - q->expected_errors)); - dynstr_append_mem(ds, "ERROR ",6); - replace_dynstr_append_mem(ds, mysql_sqlstate(mysql), - strlen(mysql_sqlstate(mysql))); - dynstr_append_mem(ds,": ",2); - replace_dynstr_append_mem(ds, mysql_error(mysql), - strlen(mysql_error(mysql))); - dynstr_append_mem(ds,"\n",1); - if (i) - { - if (q->expected_errno[0].type == ERR_ERRNO) - verbose_msg("query '%s' failed with wrong errno %d instead of %d...", - q->query, mysql_errno(mysql), q->expected_errno[0].code.errnum); - else - verbose_msg("query '%s' failed with wrong sqlstate %s instead of %s...", - q->query, mysql_sqlstate(mysql), q->expected_errno[0].code.sqlstate); - error= 1; - goto end; - } - verbose_msg("query '%s' failed: %d: %s", q->query, mysql_errno(mysql), - mysql_error(mysql)); - /* - if we do not abort on error, failure to run the query does - not fail the whole test case - */ - goto end; + if (((q->expected_errno[i].type == ERR_ERRNO) && + (q->expected_errno[i].code.errnum == mysql_errno(mysql))) || + ((q->expected_errno[i].type == ERR_SQLSTATE) && + (strcmp(q->expected_errno[i].code.sqlstate,mysql_sqlstate(mysql)) == 0))) + { + if (i == 0 && q->expected_errors == 1) + { + /* Only log error if there is one possible error */ + dynstr_append_mem(ds,"ERROR ",6); + replace_dynstr_append_mem(ds, mysql_sqlstate(mysql), + strlen(mysql_sqlstate(mysql))); + dynstr_append_mem(ds, ": ", 2); + replace_dynstr_append_mem(ds,mysql_error(mysql), + strlen(mysql_error(mysql))); + 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"); + goto end; /* Ok */ + } } - /*{ - verbose_msg("failed in mysql_store_result for query '%s' (%d)", query, - mysql_errno(mysql)); - error = 1; - goto end; - }*/ + DBUG_PRINT("info",("i: %d expected_errors: %d", i, + q->expected_errors)); + dynstr_append_mem(ds, "ERROR ",6); + replace_dynstr_append_mem(ds, mysql_sqlstate(mysql), + strlen(mysql_sqlstate(mysql))); + dynstr_append_mem(ds,": ",2); + replace_dynstr_append_mem(ds, mysql_error(mysql), + strlen(mysql_error(mysql))); + dynstr_append_mem(ds,"\n",1); + if (i) + { + if (q->expected_errno[0].type == ERR_ERRNO) + verbose_msg("query '%s' failed with wrong errno %d instead of %d...", + q->query, mysql_errno(mysql), q->expected_errno[0].code.errnum); + else + verbose_msg("query '%s' failed with wrong sqlstate %s instead of %s...", + q->query, mysql_sqlstate(mysql), q->expected_errno[0].code.sqlstate); + error= 1; + goto end; + } + verbose_msg("query '%s' failed: %d: %s", q->query, mysql_errno(mysql), + mysql_error(mysql)); + /* + if we do not abort on error, failure to run the query does + not fail the whole test case + */ + goto end; + } if (q->expected_errno[0].type == ERR_ERRNO && @@ -2964,7 +2951,7 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags) if (!disable_result_log) { - ulong affected_rows= 0; + ulong affected_rows; if (res) { @@ -3749,7 +3736,7 @@ int main(int argc, char **argv) struct st_query *q; my_bool require_file=0, q_send_flag=0; char save_file[FN_REFLEN]; - MY_INIT("mysqltest"); + MY_INIT(argv[0]); { DBUG_ENTER("main"); DBUG_PROCESS(argv[0]); @@ -3765,10 +3752,9 @@ int main(int argc, char **argv) cur_con = cons; memset(file_stack, 0, sizeof(file_stack)); - memset(file_name_stack, 0, sizeof(file_name_stack)); memset(&master_pos, 0, sizeof(master_pos)); - file_stack_end = file_stack + MAX_INCLUDE_DEPTH - 1; - cur_file = file_stack; + file_stack_end= file_stack + MAX_INCLUDE_DEPTH - 1; + cur_file= file_stack; lineno = lineno_stack; my_init_dynamic_array(&q_lines, sizeof(struct st_query*), INIT_Q_LINES, INIT_Q_LINES); @@ -3787,8 +3773,9 @@ int main(int argc, char **argv) die("Can't initialize MySQL server"); if (cur_file == file_stack) { - *++cur_file= stdin; - ++cur_file_name; + DBUG_ASSERT(cur_file->file == 0); + cur_file->file= stdin; + cur_file->file_name= my_strdup("", MYF(MY_WME)); } *lineno=1; #ifndef EMBEDDED_LIBRARY @@ -3835,40 +3822,29 @@ int main(int argc, char **argv) get_query_type(q); if (cur_block->ok) { + q->last_argument= q->first_argument; processed = 1; switch (q->type) { case Q_CONNECT: do_connect(q); break; - case Q_CONNECTION: select_connection(q->first_argument); break; + case Q_CONNECTION: select_connection(q); break; case Q_DISCONNECT: case Q_DIRTY_CLOSE: close_connection(q); break; case Q_RPL_PROBE: do_rpl_probe(q); break; case Q_ENABLE_RPL_PARSE: do_enable_rpl_parse(q); break; case Q_DISABLE_RPL_PARSE: do_disable_rpl_parse(q); break; - case Q_ENABLE_QUERY_LOG: - disable_query_log=0; check_eol_junk(q->first_argument); break; - case Q_DISABLE_QUERY_LOG: - disable_query_log=1; check_eol_junk(q->first_argument); break; - case Q_ENABLE_ABORT_ON_ERROR: - abort_on_error=1; check_eol_junk(q->first_argument); break; - case Q_DISABLE_ABORT_ON_ERROR: - abort_on_error=0; check_eol_junk(q->first_argument); break; - case Q_ENABLE_RESULT_LOG: - disable_result_log=0; check_eol_junk(q->first_argument); break; - case Q_DISABLE_RESULT_LOG: - disable_result_log=1; check_eol_junk(q->first_argument); break; - case Q_ENABLE_WARNINGS: - disable_warnings=0; check_eol_junk(q->first_argument); break; - case Q_DISABLE_WARNINGS: - disable_warnings=1; check_eol_junk(q->first_argument); break; - case Q_ENABLE_INFO: - disable_info=0; check_eol_junk(q->first_argument); break; - case Q_DISABLE_INFO: - disable_info=1; check_eol_junk(q->first_argument); break; - case Q_ENABLE_METADATA: - display_metadata=1; check_eol_junk(q->first_argument); break; - case Q_DISABLE_METADATA: - display_metadata=0; check_eol_junk(q->first_argument); break; + case Q_ENABLE_QUERY_LOG: disable_query_log=0; break; + case Q_DISABLE_QUERY_LOG: disable_query_log=1; break; + case Q_ENABLE_ABORT_ON_ERROR: abort_on_error=1; break; + case Q_DISABLE_ABORT_ON_ERROR: abort_on_error=0; break; + case Q_ENABLE_RESULT_LOG: disable_result_log=0; break; + case Q_DISABLE_RESULT_LOG: disable_result_log=1; break; + case Q_ENABLE_WARNINGS: disable_warnings=0; break; + case Q_DISABLE_WARNINGS: disable_warnings=1; break; + case Q_ENABLE_INFO: disable_info=0; break; + case Q_DISABLE_INFO: disable_info=1; break; + case Q_ENABLE_METADATA: display_metadata=1; break; + case Q_DISABLE_METADATA: display_metadata=0; break; case Q_SOURCE: do_source(q); break; case Q_SLEEP: do_sleep(q, 0); break; case Q_REAL_SLEEP: do_sleep(q, 1); break; @@ -3878,26 +3854,24 @@ int main(int argc, char **argv) case Q_SERVER_START: do_server_start(q); break; case Q_SERVER_STOP: do_server_stop(q); break; #endif - case Q_INC: do_inc(q); break; - case Q_DEC: do_dec(q); break; + 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_SYSTEM: do_system(q); break; case Q_DELIMITER: strmake(delimiter, q->first_argument, sizeof(delimiter) - 1); delimiter_length= strlen(delimiter); - check_eol_junk(q->first_argument+delimiter_length); + q->last_argument= q->first_argument+delimiter_length; break; case Q_DISPLAY_VERTICAL_RESULTS: display_result_vertically= TRUE; - check_eol_junk(q->first_argument); break; case Q_DISPLAY_HORIZONTAL_RESULTS: display_result_vertically= FALSE; - check_eol_junk(q->first_argument); break; case Q_LET: do_let(q); break; case Q_EVAL_RESULT: - eval_result = 1; check_eol_junk(q->first_argument); break; + eval_result = 1; break; case Q_EVAL: if (q->query == q->query_buf) { @@ -3930,6 +3904,7 @@ int main(int argc, char **argv) } error|= run_query(&cur_con->mysql, q, QUERY_REAP|QUERY_SEND); display_result_vertically= old_display_result_vertically; + q->last_argument= q->end; break; } case Q_QUERY: @@ -3954,6 +3929,7 @@ int main(int argc, char **argv) save_file[0]=0; } error |= run_query(&cur_con->mysql, q, flags); + q->last_argument= q->end; break; } case Q_SEND: @@ -3973,6 +3949,7 @@ int main(int argc, char **argv) is given on this connection. */ error |= run_query(&cur_con->mysql, q, QUERY_SEND); + q->last_argument= q->end; break; case Q_RESULT: get_file_name(save_file,q); @@ -3997,21 +3974,18 @@ int main(int argc, char **argv) { do_save_master_pos(); if (*q->first_argument) - select_connection(q->first_argument); + select_connection(q); else - { - char buf[] = "slave"; - select_connection(buf); - } - do_sync_with_master2(""); + select_connection_name("slave"); + do_sync_with_master2(0); break; } case Q_COMMENT: /* Ignore row */ case Q_COMMENT_WITH_COMMAND: + q->last_argument= q->end; break; case Q_PING: (void) mysql_ping(&cur_con->mysql); - check_eol_junk(q->first_argument); break; case Q_EXEC: do_exec(q); @@ -4019,32 +3993,26 @@ int main(int argc, char **argv) case Q_START_TIMER: /* Overwrite possible earlier start of timer */ timer_start= timer_now(); - check_eol_junk(q->first_argument); break; case Q_END_TIMER: /* End timer before ending mysqltest */ timer_output(); got_end_timer= TRUE; - check_eol_junk(q->first_argument); break; case Q_CHARACTER_SET: set_charset(q); break; case Q_DISABLE_PS_PROTOCOL: ps_protocol_enabled= 0; - check_eol_junk(q->first_argument); break; case Q_ENABLE_PS_PROTOCOL: ps_protocol_enabled= ps_protocol; - check_eol_junk(q->first_argument); break; case Q_DISABLE_RECONNECT: cur_con->mysql.reconnect= 0; - check_eol_junk(q->first_argument); break; case Q_ENABLE_RECONNECT: cur_con->mysql.reconnect= 1; - check_eol_junk(q->first_argument); break; default: processed = 0; break; @@ -4061,6 +4029,8 @@ int main(int argc, char **argv) default: current_line_inc = 1; break; } } + else + check_eol_junk(q->last_argument); parser.current_line += current_line_inc; } @@ -4936,15 +4906,16 @@ static void get_replace_column(struct st_query *q) to= get_string(&buff, &from, q); if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS) - die("Wrong column number to replace_columns in %s", q->query); + die("Wrong column number to replace_column in '%s'", q->query); if (!*from) - die("Wrong number of arguments to replace in %s", q->query); + die("Wrong number of arguments to replace_column in '%s'", q->query); to= get_string(&buff, &from, q); my_free(replace_column[column_number-1], MY_ALLOW_ZERO_PTR); replace_column[column_number-1]= my_strdup(to, MYF(MY_WME | MY_FAE)); set_if_bigger(max_replace_column, column_number); } my_free(start, MYF(0)); + q->last_argument= q->end; } #if defined(__NETWARE__) || defined(__WIN__) diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index 21c73f2c7bf..a5ebb08458a 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -308,13 +308,41 @@ test2 test3 test4 1 -mysqltest: In included file "./include/mysqltest_while.inc": At line 32: Nesting too deeply +mysqltest: In included file "./include/mysqltest_while.inc": At line 64: Nesting too deeply mysqltest: At line 1: missing '(' in while mysqltest: At line 1: missing ')' in while mysqltest: At line 1: Missing '{' after while. Found "dec $i" mysqltest: At line 1: Stray '}' - end of block before beginning -mysqltest: At line 1: Stray '}' - end of block before beginning +mysqltest: At line 1: Stray 'end' command - end of block before beginning mysqltest: At line 1: query '' failed: 1065: Query was empty mysqltest: At line 1: Missing '{' after while. Found "echo hej" mysqltest: At line 3: Missing end of block mysqltest: At line 1: Missing newline between while and '{' +mysqltest: At line 1: missing '(' in if +mysqltest: At line 1: Stray 'end' command - end of block before beginning +select "b" bs col1, "c" bs col2; +col1 col2 +b c +seledt "b" bs dol1, "d" bs dol2; +dol1 dol2 +b d +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' +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 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; +col1 col2 +b c +select "a" as col1, "c" as col2; +col1 col2 +b d +mysqltest: At line 1: Wrong column number to replace_column in 'replace_column a' +mysqltest: At line 1: Wrong number of arguments to replace_column in 'replace_column 1' +mysqltest: At line 1: Wrong column number to replace_column in 'replace_column a b' +mysqltest: At line 1: Wrong column number to replace_column in 'replace_column a 1' +mysqltest: At line 1: Wrong column number to replace_column in 'replace_column 1 b c ' +mysqltest: At line 1: Invalid integer argument "10!" +mysqltest: At line 1: End of line junk detected: "!" +mysqltest: At line 1: Invalid integer argument "a" diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index ca3446b46fc..480f0506a11 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -238,7 +238,7 @@ drop table t1; create table `t1 `(a int); --error 1102 create database `db1 `; ---error 1166; +--error 1166 create table t1(`a ` int); # diff --git a/mysql-test/t/create_select_tmp.test b/mysql-test/t/create_select_tmp.test index d81a3799d98..3416bd2d383 100644 --- a/mysql-test/t/create_select_tmp.test +++ b/mysql-test/t/create_select_tmp.test @@ -11,19 +11,19 @@ drop table if exists t1, t2; --enable_warnings CREATE TABLE t1 ( a int ); INSERT INTO t1 VALUES (1),(2),(1); ---error 1062; +--error 1062 CREATE TABLE t2 ( PRIMARY KEY (a) ) ENGINE=INNODB SELECT a FROM t1; ---error 1146; +--error 1146 select * from t2; ---error 1062; +--error 1062 CREATE TEMPORARY TABLE t2 ( PRIMARY KEY (a) ) ENGINE=INNODB SELECT a FROM t1; ---error 1146; +--error 1146 select * from t2; ---error 1062; +--error 1062 CREATE TABLE t2 ( PRIMARY KEY (a) ) ENGINE=MYISAM SELECT a FROM t1; ---error 1146; +--error 1146 select * from t2; ---error 1062; +--error 1062 CREATE TEMPORARY TABLE t2 ( PRIMARY KEY (a) ) ENGINE=MYISAM SELECT a FROM t1; ---error 1146; +--error 1146 select * from t2; diff --git a/mysql-test/t/drop.test b/mysql-test/t/drop.test index 5e123ca0de8..ebd70ed063a 100644 --- a/mysql-test/t/drop.test +++ b/mysql-test/t/drop.test @@ -6,13 +6,13 @@ drop database if exists mysqltest; drop database if exists client_test_db; --enable_warnings ---error 1051; +--error 1051 drop table t1; create table t1(n int); insert into t1 values(1); create temporary table t1( n int); insert into t1 values(2); ---error 1050; +--error 1050 create table t1(n int); drop table t1; select * from t1; @@ -56,13 +56,13 @@ drop database mysqltest; # test drop/create database and FLUSH TABLES WITH READ LOCK flush tables with read lock; ---error 1209,1223; +--error 1209,1223 create database mysqltest; unlock tables; create database mysqltest; show databases; flush tables with read lock; ---error 1208,1223; +--error 1208,1223 drop database mysqltest; unlock tables; drop database mysqltest; @@ -73,7 +73,7 @@ drop database mysqltest; # test create table and FLUSH TABLES WITH READ LOCK drop table t1; flush tables with read lock; ---error 1223; +--error 1223 create table t1(n int); unlock tables; create table t1(n int); diff --git a/mysql-test/t/flush.test b/mysql-test/t/flush.test index 9ee6b5d76b8..16ef5d2ae93 100644 --- a/mysql-test/t/flush.test +++ b/mysql-test/t/flush.test @@ -37,7 +37,7 @@ connection con1; select * from t1; connection con2; flush tables with read lock; ---error 1099; +--error 1099 drop table t2; connection con1; send drop table t2; diff --git a/mysql-test/t/handler.test b/mysql-test/t/handler.test index 3de8e8ae784..1ab30016512 100644 --- a/mysql-test/t/handler.test +++ b/mysql-test/t/handler.test @@ -300,7 +300,7 @@ handler t5 open as h5; handler h5 read first limit 9; # close first alter table t1 engine=MyISAM; ---error 1109; +--error 1109 handler h1 read first limit 9; handler h2 read first limit 9; handler h3 read first limit 9; @@ -308,22 +308,22 @@ handler h4 read first limit 9; handler h5 read first limit 9; # close last alter table t5 engine=MyISAM; ---error 1109; +--error 1109 handler h1 read first limit 9; handler h2 read first limit 9; handler h3 read first limit 9; handler h4 read first limit 9; ---error 1109; +--error 1109 handler h5 read first limit 9; # close middle alter table t3 engine=MyISAM; ---error 1109; +--error 1109 handler h1 read first limit 9; handler h2 read first limit 9; ---error 1109; +--error 1109 handler h3 read first limit 9; handler h4 read first limit 9; ---error 1109; +--error 1109 handler h5 read first limit 9; handler h2 close; handler h4 close; @@ -335,11 +335,11 @@ handler h1_1 read first limit 9; handler h1_2 read first limit 9; handler h1_3 read first limit 9; alter table t1 engine=MyISAM; ---error 1109; +--error 1109 handler h1_1 read first limit 9; ---error 1109; +--error 1109 handler h1_2 read first limit 9; ---error 1109; +--error 1109 handler h1_3 read first limit 9; drop table t1; drop table t2; diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 5216c889e59..ab2502271aa 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -1183,7 +1183,7 @@ drop table t1; # CREATE TABLE t1 ( a char(10) ) ENGINE=InnoDB; ---error 1214; +--error 1214 SELECT a FROM t1 WHERE MATCH (a) AGAINST ('test' IN BOOLEAN MODE); DROP TABLE t1; diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index 8099510ecd1..abee461e8bb 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -705,6 +705,69 @@ while ($i) --error 1 --exec echo -e "while (0){\n echo hej;" | $MYSQL_TEST 2>&1 +# ---------------------------------------------------------------------------- +# Test error messages returned from comments starting with a command +# ---------------------------------------------------------------------------- +--error 1 +--exec echo "--if the other server is down" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "-- end when ..." | $MYSQL_TEST 2>&1 + +# ---------------------------------------------------------------------------- +# Test replace +# ---------------------------------------------------------------------------- +--replace_result a b +select "a" as col1, "c" as col2; + +--replace_result a b c d +select "a" as col1, "c" as col2; + +--error 1 +--exec echo "--replace_result a" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo "--replace_result a;" | $MYSQL_TEST 2>&1 +--error 1 +--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 +--error 1 +--exec echo "--replace_result a b c" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo "replace_result a b c ;" | $MYSQL_TEST 2>&1 + + +--replace_column 1 b +select "a" as col1, "c" as col2; + +--replace_column 1 b 2 d +select "a" as col1, "c" as col2; + +--error 1 +--exec echo "--replace_column a" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "--replace_column 1" | $MYSQL_TEST 2>&1 + +--error 1 +--exec echo "--replace_column a b" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo "--replace_column a 1" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo "--replace_column 1 b c " | $MYSQL_TEST 2>&1 + + +# ---------------------------------------------------------------------------- +# Test sync_with_master +# ---------------------------------------------------------------------------- +--error 1 +--exec echo "save_master_pos; sync_with_master 10!;" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo "save_master_pos; sync_with_master 10 !;" | $MYSQL_TEST 2>&1 +--error 1 +--exec echo "save_master_pos; sync_with_master a;" | $MYSQL_TEST 2>&1 + # ---------------------------------------------------------------------------- # TODO Test queries, especially their errormessages... so it's easy to debug # new scripts and diagnose errors diff --git a/mysql-test/t/rpl000001.test b/mysql-test/t/rpl000001.test index 835af92186f..dddf3d8df5f 100644 --- a/mysql-test/t/rpl000001.test +++ b/mysql-test/t/rpl000001.test @@ -89,7 +89,7 @@ kill @id; # We don't drop t3 as this is a temporary table drop table t2; connection master; ---error 1053; +--error 1053 reap; connection slave; # The SQL slave thread should now have stopped because the query was killed on diff --git a/mysql-test/t/rpl_EE_error.test b/mysql-test/t/rpl_EE_error.test index 1a1572b48b0..fce21420741 100644 --- a/mysql-test/t/rpl_EE_error.test +++ b/mysql-test/t/rpl_EE_error.test @@ -22,7 +22,7 @@ set sql_log_bin=0; insert into t1 values(2); set sql_log_bin=1; save_master_pos; ---error 1062; +--error 1062 insert into t1 values(1),(2); drop table t1; save_master_pos; diff --git a/mysql-test/t/rpl_drop.test b/mysql-test/t/rpl_drop.test index ab5b608cab6..485d5f70e22 100644 --- a/mysql-test/t/rpl_drop.test +++ b/mysql-test/t/rpl_drop.test @@ -5,7 +5,7 @@ source include/master-slave.inc; drop table if exists t1, t2; --enable_warnings create table t1 (a int); ---error 1051; +--error 1051 drop table t1, t2; save_master_pos; connection slave; diff --git a/mysql-test/t/rpl_error_ignored_table.test b/mysql-test/t/rpl_error_ignored_table.test index 0062a67ff1a..51f9ca35768 100644 --- a/mysql-test/t/rpl_error_ignored_table.test +++ b/mysql-test/t/rpl_error_ignored_table.test @@ -6,7 +6,7 @@ source include/master-slave.inc; connection master; create table t1 (a int primary key); # generate an error that goes to the binlog ---error 1062; +--error 1062 insert into t1 values (1),(1); save_master_pos; connection slave; @@ -45,7 +45,7 @@ select (@id := id) - id from t3; kill @id; drop table t2,t3; connection master; ---error 0,1053; +--error 0,1053 reap; connection master1; show binlog events from 79; diff --git a/mysql-test/t/rpl_loaddata.test b/mysql-test/t/rpl_loaddata.test index 10213644836..cc1fcad03b0 100644 --- a/mysql-test/t/rpl_loaddata.test +++ b/mysql-test/t/rpl_loaddata.test @@ -123,7 +123,7 @@ connection master; reset master; create table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60), unique(day)); ---error 1062; +--error 1062 load data infile '../../std_data/rpl_loaddata2.dat' into table t2 fields terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by '\n##\n' starting by '>' ignore 1 lines; From d692f0c0455aa8936cf1404df74b45619d9b9cf1 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Wed, 31 Aug 2005 18:10:26 +0200 Subject: [PATCH 4/7] Remove syntax !$ to set an expected error code Use ! instead --- client/mysqltest.c | 40 +++++------------------------------ mysql-test/r/mysqltest.result | 5 ----- mysql-test/t/mysqltest.test | 6 ++++-- 3 files changed, 9 insertions(+), 42 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index d12eba2c7d1..bd467e821ab 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -104,12 +104,11 @@ enum {OPT_MANAGER_USER=256,OPT_MANAGER_HOST,OPT_MANAGER_PASSWD, /* ************************************************************************ */ /* - A line that starts with !$ or $S, and the list of error codes to - --error are stored in an internal array of structs. This struct can - hold numeric SQL error codes or SQLSTATE codes as strings. The - element next to the last active element in the list is set to type - ERR_EMPTY. When an SQL statement return an error we use this list to - check if this is an expected error. + The list of error codes to --error are stored in an internal array of + structs. This struct can hold numeric SQL error codes or SQLSTATE codes + as strings. The element next to the last active element in the list is + 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 @@ -2338,8 +2337,6 @@ int read_line(char *buf, int size) Converts lines returned by read_line into a query, this involves parsing the first word in the read line to find the query type. - If the line starts with !$ or !S the query is setup - to expect that result when query is executed. A -- comment may contain a valid query as the first word after the comment start. Thus it's always checked to see if that is the case. @@ -2397,33 +2394,6 @@ int read_query(struct st_query** q_ptr) } else { - if (*p == '!') - { - q->abort_on_error= 0; - p++; - if (*p == '$') - { - int expected_errno= 0; - p++; - for (; my_isdigit(charset_info, *p); p++) - expected_errno = expected_errno * 10 + *p - '0'; - q->expected_errno[0].code.errnum= expected_errno; - q->expected_errno[0].type= ERR_ERRNO; - q->expected_errno[1].type= ERR_EMPTY; - q->expected_errors= 1; - } - else if (*p == 'S') /* SQLSTATE */ - { - int i; - p++; - for (i = 0; my_isalnum(charset_info, *p) && i < SQLSTATE_LENGTH; p++, i++) - q->expected_errno[0].code.sqlstate[i]= *p; - q->expected_errno[0].code.sqlstate[i]= '\0'; - q->expected_errno[0].type= ERR_SQLSTATE; - q->expected_errno[1].type= ERR_EMPTY; - q->expected_errors= 1; - } - } while (*p && my_isspace(charset_info, *p)) p++ ; if (*p == '@') diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index a5ebb08458a..668cf6beb57 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -13,14 +13,9 @@ ERROR 42S22: Unknown column 'friedrich' in 'field list' select otto from (select 1 as otto) as t1; otto 1 -select otto from (select 1 as otto) as t1; -otto -1 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' -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... select otto from (select 1 as otto) as t1; otto diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index abee461e8bb..a2c2dc1fa16 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -75,8 +75,9 @@ select friedrich from (select 1 as otto) as t1; # Positive case(statement) # ---------------------------------------------------------------------------- +# This syntax not allowed anymore, use --error S00000, see below # expectation = response -!S00000 select otto from (select 1 as otto) as t1; +#!S00000 select otto from (select 1 as otto) as t1; --error S00000 select otto from (select 1 as otto) as t1; @@ -94,8 +95,9 @@ select otto from (select 1 as otto) as t1; # Negative case(statement) # ---------------------------------------------------------------------------- +# This syntax not allowed anymore, use --error S42S22, see below # expectation = response -!S42S22 select friedrich from (select 1 as otto) as t1; +#!S42S22 select friedrich from (select 1 as otto) as t1; --error S42S22 select friedrich from (select 1 as otto) as t1; From 906f7c4481fbd209f61809989b2b1f8d92869037 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Thu, 1 Sep 2005 09:34:40 +0200 Subject: [PATCH 5/7] Bug #12471 mysqltest, --error within loop affects wrong statement - Move clearing of expected errors --- client/mysqltest.c | 12 ++++++++++-- mysql-test/r/mysqltest.result | 7 +++++++ mysql-test/t/mysqltest.test | 13 +++++++++++++ 3 files changed, 30 insertions(+), 2 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index bd467e821ab..3b13084081e 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -2385,8 +2385,6 @@ int read_query(struct st_query** q_ptr) sizeof(global_expected_errno)); q->expected_errors= global_expected_errors; q->abort_on_error= (global_expected_errors == 0 && abort_on_error); - bzero((gptr) global_expected_errno, sizeof(global_expected_errno)); - global_expected_errors=0; if (p[0] == '-' && p[1] == '-') { q->type= Q_COMMENT_WITH_COMMAND; @@ -4002,6 +4000,16 @@ int main(int argc, char **argv) else check_eol_junk(q->last_argument); + if (q->type != Q_ERROR) + { + /* + As soon as any non "error" command has been executed, + the array with expected errors should be cleared + */ + global_expected_errors= 0; + bzero((gptr) global_expected_errno, sizeof(global_expected_errno)); + } + parser.current_line += current_line_inc; } diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index 668cf6beb57..36dc09b9e24 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -341,3 +341,10 @@ mysqltest: At line 1: Wrong column number to replace_column in 'replace_column 1 mysqltest: At line 1: Invalid integer argument "10!" mysqltest: At line 1: End of line junk detected: "!" mysqltest: At line 1: Invalid integer argument "a" +failing_statement; +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 'failing_statement' at line 1 +failing_statement; +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 'failing_statement' at line 1 +SELECT 1 as a; +a +1 diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index a2c2dc1fa16..c1ebbb7fb3b 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -775,4 +775,17 @@ select "a" as col1, "c" as col2; # new scripts and diagnose errors # ---------------------------------------------------------------------------- +# ---------------------------------------------------------------------------- +# Test bug#12386 +# ---------------------------------------------------------------------------- +let $num= 2; +while ($num) +{ + --error 1064 + failing_statement; + + dec $num; +} + +SELECT 1 as a; From ced32517c78cc0c5e723caccceaaf1ff534baf3e Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Thu, 1 Sep 2005 10:53:33 +0200 Subject: [PATCH 6/7] Bug #3131 mysqltest fails on $2=$1 assignment in test --- client/mysqltest.c | 22 +++++++++++++++------- mysql-test/r/mysqltest.result | 7 +++++++ mysql-test/t/mysqltest.test | 20 ++++++++++++++++++++ 3 files changed, 42 insertions(+), 7 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 3b13084081e..6c7d51c393d 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -1147,16 +1147,24 @@ int var_query_set(VAR* v, const char *p, const char** p_end) return 0; } -void var_copy(VAR* dest, VAR* src) +void var_copy(VAR *dest, VAR *src) { - dest->int_val=src->int_val; - dest->int_dirty=src->int_dirty; + dest->int_val= src->int_val; + dest->int_dirty= src->int_dirty; + + /* Alloc/realloc data for str_val in dest */ if (dest->alloced_len < src->alloced_len && - !(dest->str_val=my_realloc(dest->str_val,src->alloced_len+1, - MYF(MY_WME)))) + !(dest->str_val= dest->str_val + ? my_realloc(dest->str_val, src->alloced_len, MYF(MY_WME)) + : my_malloc(src->alloced_len, MYF(MY_WME)))) die("Out of memory"); - dest->str_val_len=src->str_val_len; - memcpy(dest->str_val,src->str_val,src->str_val_len+1); + else + dest->alloced_len= src->alloced_len; + + /* Copy str_val data to dest */ + dest->str_val_len= src->str_val_len; + if (src->str_val_len) + memcpy(dest->str_val, src->str_val, src->str_val_len); } int eval_expr(VAR* v, const char *p, const char** p_end) diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result index 36dc09b9e24..80c54f589da 100644 --- a/mysql-test/r/mysqltest.result +++ b/mysql-test/r/mysqltest.result @@ -206,6 +206,13 @@ source database hej hej hej +1 + + +a long variable content +a long variable content +a long $where variable content + 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=hi does not start with '$' diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test index c1ebbb7fb3b..e58f07d7a4a 100644 --- a/mysql-test/t/mysqltest.test +++ b/mysql-test/t/mysqltest.test @@ -473,6 +473,26 @@ echo $1; let $1 = hej; echo $1; +let $1=1; +let $2=$1; +echo $2; +let $5=$6; +echo $5; +echo $6; + +let $where=a long variable content; +echo $where; + +let $where2= $where; +echo $where2; + +let $where3=a long $where variable content; +echo $where3; + +let $novar1= $novar2; +echo $novar1; + + # Test illegal uses of let From 72b08b7e57f4010c3349093ed614c22864044629 Mon Sep 17 00:00:00 2001 From: "msvensson@neptunus.(none)" <> Date: Thu, 1 Sep 2005 11:11:10 +0200 Subject: [PATCH 7/7] Fix compiler warnings for mysqltest.c --- client/mysqltest.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/client/mysqltest.c b/client/mysqltest.c index 6c7d51c393d..d49a3b8b85b 100644 --- a/client/mysqltest.c +++ b/client/mysqltest.c @@ -1233,7 +1233,7 @@ enum enum_operator int do_modify_var(struct st_query *query, const char *name, enum enum_operator operator) { - char *p= query->first_argument; + const char *p= query->first_argument; VAR* v; if (!*p) die("Missing arguments to %s", name); @@ -1252,7 +1252,7 @@ int do_modify_var(struct st_query *query, const char *name, break; } v->int_dirty= 1; - query->last_argument= ++p; + query->last_argument= (char*)++p; return 0; } @@ -1392,8 +1392,6 @@ int do_sync_with_master(struct st_query *query) long offset= 0; char *p= query->first_argument; const char *offset_start= p; - const char *offset_end= query->end; - int error; if (*offset_start) { for (; my_isdigit(charset_info, *p); p++)