Commit d57a0e52 authored by unknown's avatar unknown

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:
  Updated mysql test to do stricter checking of syntax. For example when the number 
  of arguments to a command is known, everything else is "junk" => die. 
  Better checking of argument types.
  Added better debug printouts.
  Added improved printouts when wrong syntax is detected.
  Fix two bugs where mysqltest could not detect end of comamnd properly, as described in bug#11316
  Fix segfault when performing too many source commands.
  Fix segfault when doing too many while loop levels.
  Add printout of line number in die
  Remove lineno and \n in all strings passed to die function.
  Decrese BLOCK_STACK_DEPTH from 32 to 16, does any test use more than 1 level?
mysql-test/mysql-test-run.pl:
  export MYSQL_TEST environment variable, used from msyqltest.test
mysql-test/mysql-test-run.sh:
  export MYSQL_TEST environment variable, used from msyqltest.test
mysql-test/r/mysqltest.result:
  Updated test results
mysql-test/r/rpl_flush_log_loop.result:
  Updated test result.
  Approved by lars
mysql-test/t/innodb-deadlock.test:
  Correct wrong syntax
  Superfluos ;
mysql-test/t/innodb-lock.test:
  Correct wrong syntax
  Superfluos ;
mysql-test/t/mysqltest.test:
  Add several new tests  for mysqltest.
  Foxus on detecting wrong syntax in test files.
  Use exec with expected error to execute test scripts that will kill mysqltest
  Change some negative test that were previously commented out to use the above method.
mysql-test/t/ndb_autodiscover2.test:
  Correct wrong syntax
  Superfluos ;
mysql-test/t/rpl_change_master.test:
  Correct wrong syntax
  Superfluos ;
mysql-test/t/rpl_deadlock.test:
  Correct wrong syntax
  Superfluos ;
mysql-test/t/rpl_drop_temp.test:
  Correct wrong syntax
  Superfluos ;
mysql-test/t/rpl_flush_log_loop.test:
  Fix after detecting wrong syntax, missing ;
  Discussed with lars.
mysql-test/t/rpl_insert_id.test:
  Missing ;
mysql-test/t/rpl_rotate_logs.test:
  Correct wrong syntax
  Superfluos ;
mysql-test/t/rpl_until.test:
  Missing delimiter
mysql-test/include/mysqltest_while.inc:
  New file to test too many while levels
parent 3d2814d6
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
**********************************************************************/ **********************************************************************/
#define MTEST_VERSION "2.4" #define MTEST_VERSION "2.5"
#include <my_global.h> #include <my_global.h>
#include <mysql_embed.h> #include <mysql_embed.h>
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
#define LAZY_GUESS_BUF_SIZE 8192 #define LAZY_GUESS_BUF_SIZE 8192
#define INIT_Q_LINES 1024 #define INIT_Q_LINES 1024
#define MIN_VAR_ALLOC 32 #define MIN_VAR_ALLOC 32
#define BLOCK_STACK_DEPTH 32 #define BLOCK_STACK_DEPTH 16
#define MAX_EXPECTED_ERRORS 10 #define MAX_EXPECTED_ERRORS 10
#define QUERY_SEND 1 #define QUERY_SEND 1
#define QUERY_REAP 2 #define QUERY_REAP 2
...@@ -151,6 +151,8 @@ static char **default_argv; ...@@ -151,6 +151,8 @@ static char **default_argv;
static const char *load_default_groups[]= { "mysqltest","client",0 }; static const char *load_default_groups[]= { "mysqltest","client",0 };
static char line_buffer[MAX_DELIMITER], *line_buffer_pos= line_buffer; 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* file_stack[MAX_INCLUDE_DEPTH];
static FILE** cur_file; static FILE** cur_file;
static FILE** file_stack_end; static FILE** file_stack_end;
...@@ -307,7 +309,7 @@ const char *command_names[]= ...@@ -307,7 +309,7 @@ const char *command_names[]=
"connect", "connect",
/* the difference between sleep and real_sleep is that sleep will use /* the difference between sleep and real_sleep is that sleep will use
the delay from command line (--sleep) if there is one. 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 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 can be used to set this delay. real_sleep is used for cpu-independent
delays delays
...@@ -514,6 +516,9 @@ static void close_files() ...@@ -514,6 +516,9 @@ static void close_files()
{ {
if (*cur_file != stdin && *cur_file) if (*cur_file != stdin && *cur_file)
my_fclose(*cur_file,MYF(0)); my_fclose(*cur_file,MYF(0));
char* p= file_name_stack[cur_file_name--]= 0;
if (p)
free(p);
} }
DBUG_VOID_RETURN; DBUG_VOID_RETURN;
} }
...@@ -564,6 +569,10 @@ static void die(const char* fmt, ...) ...@@ -564,6 +569,10 @@ static void die(const char* fmt, ...)
if (fmt) if (fmt)
{ {
fprintf(stderr, "%s: ", my_progname); 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); vfprintf(stderr, fmt, args);
fprintf(stderr, "\n"); fprintf(stderr, "\n");
fflush(stderr); fflush(stderr);
...@@ -809,11 +818,38 @@ int open_file(const char* name) ...@@ -809,11 +818,38 @@ int open_file(const char* name)
if (*cur_file && cur_file == file_stack_end) if (*cur_file && cur_file == file_stack_end)
die("Source directives are nesting too deep"); die("Source directives are nesting too deep");
if (!(*(cur_file+1) = my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(MY_WME)))) if (!(*++cur_file = my_fopen(buff, O_RDONLY | FILE_BINARY, MYF(0))))
die(NullS); die("Could not open file %s", buff);
cur_file++;
*++lineno=1; *++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; return 0;
} }
...@@ -844,24 +880,26 @@ int do_wait_for_slave_to_stop(struct st_query* q __attribute__((unused))) ...@@ -844,24 +880,26 @@ int do_wait_for_slave_to_stop(struct st_query* q __attribute__((unused)))
break; break;
my_sleep(SLAVE_POLL_INTERVAL); 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) if (!manager)
abort_not_supported_test(); abort_not_supported_test();
return 0; return check_eol_junk(q->first_argument);
} }
#ifndef EMBEDDED_LIBRARY #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");
} }
...@@ -876,7 +914,7 @@ int do_server_op(struct st_query* q,const char* op) ...@@ -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_buf,op);
com_p=strmov(com_p,"_exec "); com_p=strmov(com_p,"_exec ");
if (!*p) 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)) while (*p && !my_isspace(charset_info,*p))
*com_p++= *p++; *com_p++= *p++;
*com_p++=' '; *com_p++=' ';
...@@ -892,23 +930,42 @@ int do_server_op(struct st_query* q,const char* op) ...@@ -892,23 +930,42 @@ int do_server_op(struct st_query* q,const char* op)
manager->last_errno); manager->last_errno);
} }
return 0; return check_eol_junk(p);
} }
#endif #endif
/*
Source and execute the given file
SYNOPSIS
do_source()
q called command
DESCRIPTION
source <file_name>
Open the file <file_name> and execute it
*/
int do_source(struct st_query* q) int do_source(struct st_query* q)
{ {
char* p=q->first_argument, *name; char* p=q->first_argument, *name;
if (!*p) if (!*p)
die("Missing file name in source\n"); die("Missing file name in source");
name = p; name = p;
while (*p && !my_isspace(charset_info,*p)) while (*p && !my_isspace(charset_info,*p))
p++; p++;
*p = 0; if (*p)
{
*p++= 0;
check_eol_junk(p);
}
return open_file(name); return open_file(name);
} }
/* /*
Execute given command. Execute given command.
...@@ -917,18 +974,19 @@ int do_source(struct st_query* q) ...@@ -917,18 +974,19 @@ int do_source(struct st_query* q)
q called command q called command
DESCRIPTION DESCRIPTION
If one uses --exec command [args] command in .test file exec <command>
we will execute the command and record its output.
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) static void do_exec(struct st_query* q)
{ {
int error; int error;
DYNAMIC_STRING *ds= NULL; /* Assign just to avoid warning */ DYNAMIC_STRING *ds= NULL;
DYNAMIC_STRING ds_tmp; DYNAMIC_STRING ds_tmp;
char buf[1024]; char buf[1024];
FILE *res_file; FILE *res_file;
...@@ -938,12 +996,12 @@ static void do_exec(struct st_query* q) ...@@ -938,12 +996,12 @@ static void do_exec(struct st_query* q)
while (*cmd && my_isspace(charset_info, *cmd)) while (*cmd && my_isspace(charset_info, *cmd))
cmd++; cmd++;
if (!*cmd) if (!*cmd)
die("Missing argument in exec\n"); die("Missing argument in exec");
DBUG_PRINT("info", ("Executing '%s'", cmd)); DBUG_PRINT("info", ("Executing '%s'", cmd));
if (!(res_file= popen(cmd, "r")) && q->abort_on_error) if (!(res_file= popen(cmd, "r")) && q->abort_on_error)
die("popen() failed\n"); die("popen(\"%s\", \"r\") failed", cmd);
if (disable_result_log) if (disable_result_log)
{ {
...@@ -969,34 +1027,36 @@ static void do_exec(struct st_query* q) ...@@ -969,34 +1027,36 @@ static void do_exec(struct st_query* q)
error= pclose(res_file); error= pclose(res_file);
if (error != 0) if (error != 0)
{ {
uint status= WEXITSTATUS(error), i; uint i, status= WEXITSTATUS(error);
my_bool ok= 0; my_bool ok= 0;
if (q->abort_on_error) if (q->abort_on_error)
die("At line %u: command \"%s\" failed", start_lineno, cmd); die("command \"%s\" failed", cmd);
DBUG_PRINT("info", DBUG_PRINT("info",
("error: %d, status: %d", error, status)); ("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", DBUG_PRINT("info", ("expected error: %d",
q->expected_errno[i].code.errnum)); q->expected_errno[i].code.errnum));
if ((q->expected_errno[i].type == ERR_ERRNO) && if ((q->expected_errno[i].type == ERR_ERRNO) &&
(q->expected_errno[i].code.errnum == status)) (q->expected_errno[i].code.errnum == status))
{
ok= 1; ok= 1;
verbose_msg("At line %u: command \"%s\" failed with expected error: %d", verbose_msg("command \"%s\" failed with expected error: %d",
start_lineno, cmd, status); cmd, status);
}
} }
if (!ok) if (!ok)
die("At line: %u: command \"%s\" failed with wrong error: %d", die("command \"%s\" failed with wrong error: %d",
start_lineno, cmd, status); cmd, status);
} }
else if (q->expected_errno[0].type == ERR_ERRNO && else if (q->expected_errno[0].type == ERR_ERRNO &&
q->expected_errno[0].code.errnum != 0) q->expected_errno[0].code.errnum != 0)
{ {
/* Error code we wanted was != 0, i.e. not an expected success */ /* 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...", die("command \"%s\" succeeded - should have failed with errno %d...",
start_lineno, cmd, q->expected_errno[0].code.errnum); cmd, q->expected_errno[0].code.errnum);
} }
if (!disable_result_log) if (!disable_result_log)
...@@ -1007,7 +1067,7 @@ static void do_exec(struct st_query* q) ...@@ -1007,7 +1067,7 @@ static void do_exec(struct st_query* q)
if (record) if (record)
{ {
if (!q->record_file[0] && !result_file) if (!q->record_file[0] && !result_file)
die("At line %u: Missing result file", start_lineno); die("Missing result file");
if (!result_file) if (!result_file)
str_to_file(q->record_file, ds->str, ds->length); 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) ...@@ -1125,26 +1185,67 @@ int eval_expr(VAR* v, const char* p, const char** p_end)
return 1; 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) int do_inc(struct st_query* q)
{ {
char* p=q->first_argument; char* p=q->first_argument;
VAR* v; 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 = var_get(p, 0, 1, 0);
v->int_val++; v->int_val++;
v->int_dirty = 1; v->int_dirty = 1;
while (*p && !my_isspace(charset_info,*p))
p++;
check_eol_junk(p);
return 0; 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_dec(struct st_query* q)
{ {
char* p=q->first_argument; char* p=q->first_argument;
VAR* v; 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 = var_get(p, 0, 1, 0);
v->int_val--; v->int_val--;
v->int_dirty = 1; v->int_dirty = 1;
while (*p && !my_isspace(charset_info,*p))
p++;
check_eol_junk(p);
return 0; return 0;
} }
int do_system(struct st_query* q) int do_system(struct st_query* q)
{ {
char* p=q->first_argument; char* p=q->first_argument;
...@@ -1159,26 +1260,63 @@ int do_system(struct st_query* q) ...@@ -1159,26 +1260,63 @@ int do_system(struct st_query* q)
memcpy(expr_buf, v.str_val, v.str_val_len); memcpy(expr_buf, v.str_val, v.str_val_len);
expr_buf[v.str_val_len] = 0; expr_buf[v.str_val_len] = 0;
DBUG_PRINT("info", ("running system command '%s'", expr_buf)); DBUG_PRINT("info", ("running system command '%s'", expr_buf));
if (system(expr_buf) && q->abort_on_error) if (system(expr_buf))
{
if (q->abort_on_error)
die("system command '%s' failed", expr_buf); 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); var_free(&v);
return 0; return 0;
} }
/*
Print the content between echo and <delimiter> 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 $<var_name>
Print the content of the variable <var_name> to result file
*/
int do_echo(struct st_query* q) int do_echo(struct st_query* q)
{ {
char* p=q->first_argument; char* p=q->first_argument;
DYNAMIC_STRING *ds= NULL;
DYNAMIC_STRING ds_tmp;
VAR v; VAR v;
var_init(&v,0,0,0,0); var_init(&v,0,0,0,0);
eval_expr(&v, p, 0); /* NULL terminated */
if (v.str_val_len) if (q->record_file[0])
{ {
fflush(stdout); init_dynamic_string(&ds_tmp, "", 256, 512);
write(1, v.str_val, v.str_val_len); ds = &ds_tmp;
} }
write(1, "\n", 1); else
ds= &ds_res;
eval_expr(&v, p, 0); /* NULL terminated */
if (v.str_val_len)
dynstr_append_mem(ds, v.str_val, v.str_val_len);
dynstr_append_mem(ds, "\n", 1);
var_free(&v); var_free(&v);
if (ds == &ds_tmp)
dynstr_free(&ds_tmp);
return 0; return 0;
} }
...@@ -1199,8 +1337,19 @@ int do_sync_with_master2(const char* p) ...@@ -1199,8 +1337,19 @@ int do_sync_with_master2(const char* p)
rpl_parse = mysql_rpl_parse_enabled(mysql); rpl_parse = mysql_rpl_parse_enabled(mysql);
mysql_disable_rpl_parse(mysql); mysql_disable_rpl_parse(mysql);
if (*p) const char* offset_str= p;
offset = atoi(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, sprintf(query_buf, "select master_pos_wait('%s', %ld)", master_pos.file,
master_pos.pos + offset); master_pos.pos + offset);
...@@ -1256,7 +1405,7 @@ int do_save_master_pos() ...@@ -1256,7 +1405,7 @@ int do_save_master_pos()
mysql_disable_rpl_parse(mysql); mysql_disable_rpl_parse(mysql);
if (mysql_query(mysql, query= "show master status")) 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)); mysql_errno(mysql), mysql_error(mysql));
if (!(last_result =res = mysql_store_result(mysql))) if (!(last_result =res = mysql_store_result(mysql)))
...@@ -1275,20 +1424,52 @@ int do_save_master_pos() ...@@ -1275,20 +1424,52 @@ int do_save_master_pos()
} }
/*
Assign the variable <var_name> with <var_val>
SYNOPSIS
do_let()
q called command
DESCRIPTION
let $<var_name>=<var_val><delimiter>
<var_name> - is the string string found between the $ and =
<var_val> - is the content between the = and <delimiter>, it may span
multiple line and contain any characters except <delimiter>
<delimiter> - 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) int do_let(struct st_query* q)
{ {
char* p=q->first_argument; char* p=q->first_argument;
char *var_name, *var_name_end, *var_val_start; char *var_name, *var_name_end, *var_val_start;
/* Find <var_name> */
if (!*p) if (!*p)
die("Missing variable name in let\n"); die("Missing arguments to let");
var_name = p; var_name = p;
while (*p && (*p != '=' || my_isspace(charset_info,*p))) while (*p && *p != '=' && !my_isspace(charset_info,*p))
p++; p++;
var_name_end = 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 <var_val> */
while (*p && my_isspace(charset_info,*p)) while (*p && my_isspace(charset_info,*p))
p++; p++;
var_val_start = p; var_val_start = p;
/* 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, q->end);
} }
...@@ -1308,65 +1489,109 @@ int var_set_errno(int sql_errno) ...@@ -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"); DBUG_ENTER("do_rpl_probe");
if (mysql_rpl_probe(&cur_con->mysql)) if (mysql_rpl_probe(&cur_con->mysql))
die("Failed in mysql_rpl_probe(): '%s'", mysql_error(&cur_con->mysql)); die("Failed in mysql_rpl_probe(): '%s'", mysql_error(&cur_con->mysql));
check_eol_junk(q->first_argument);
DBUG_RETURN(0); 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); mysql_enable_rpl_parse(&cur_con->mysql);
check_eol_junk(q->first_argument);
return 0; 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); mysql_disable_rpl_parse(&cur_con->mysql);
check_eol_junk(q->first_argument);
return 0; 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 <seconds>
real_sleep
*/
int do_sleep(struct st_query* q, my_bool real_sleep) int do_sleep(struct st_query* q, my_bool real_sleep)
{ {
char *p=q->first_argument; char *p=q->first_argument;
while (*p && my_isspace(charset_info,*p)) while (*p && my_isspace(charset_info,*p))
p++; p++;
if (!*p) if (!*p)
die("Missing argument in sleep\n"); die("Missing argument to sleep");
if (opt_sleep && !real_sleep) if (opt_sleep && !real_sleep)
my_sleep(opt_sleep * 1000000L); my_sleep(opt_sleep * 1000000L);
else 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) static void get_file_name(char *filename, struct st_query* q)
{ {
char* p=q->first_argument;
strnmov(filename, p, FN_REFLEN);
/* Remove end space */ char* p=q->first_argument, *name;
while (p > filename && my_isspace(charset_info,p[-1])) if (!*p)
p--; die("Missing file name argument");
p[0]=0; 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) static void set_charset(struct st_query* q)
{ {
char* charset_name= q->first_argument; char* charset_name= q->first_argument;
char* tmp; char* p;
if (!charset_name || !*charset_name) if (!charset_name || !*charset_name)
die("Missing charset name in 'character_set'\n"); die("Missing charset name in 'character_set'");
/* Remove end space */ /* Remove end space */
tmp= charset_name; p= charset_name;
while (*tmp && !my_isspace(charset_info,*tmp)) while (*p && !my_isspace(charset_info,*p))
tmp++; p++;
*tmp= 0; if(*p)
{
*p++= 0;
check_eol_junk(p);
}
charset_info= get_charset_by_csname(charset_name,MY_CS_PRIMARY,MYF(MY_WME)); charset_info= get_charset_by_csname(charset_name,MY_CS_PRIMARY,MYF(MY_WME));
if (!charset_info) if (!charset_info)
...@@ -1380,7 +1605,7 @@ static uint get_errcodes(match_err *to,struct st_query* q) ...@@ -1380,7 +1605,7 @@ static uint get_errcodes(match_err *to,struct st_query* q)
DBUG_ENTER("get_errcodes"); DBUG_ENTER("get_errcodes");
if (!*p) if (!*p)
die("Missing argument in %s\n", q->query); die("Missing argument in %s", q->query);
do do
{ {
...@@ -1399,7 +1624,7 @@ static uint get_errcodes(match_err *to,struct st_query* q) ...@@ -1399,7 +1624,7 @@ static uint get_errcodes(match_err *to,struct st_query* q)
long val; long val;
p=str2int(p,10,(long) INT_MIN, (long) INT_MAX, &val); p=str2int(p,10,(long) INT_MIN, (long) INT_MAX, &val);
if (p == NULL) 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].code.errnum= (uint) val;
to[count].type= ERR_ERRNO; to[count].type= ERR_ERRNO;
} }
...@@ -1467,7 +1692,7 @@ static char *get_string(char **to_ptr, char **from_ptr, ...@@ -1467,7 +1692,7 @@ static char *get_string(char **to_ptr, char **from_ptr,
*to++=c; *to++=c;
} }
if (*from != ' ' && *from) 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 */ while (my_isspace(charset_info,*from)) /* Point to next string */
from++; from++;
...@@ -1513,14 +1738,14 @@ static void get_replace(struct st_query *q) ...@@ -1513,14 +1738,14 @@ static void get_replace(struct st_query *q)
bzero((char*) &to_array,sizeof(to_array)); bzero((char*) &to_array,sizeof(to_array));
bzero((char*) &from_array,sizeof(from_array)); bzero((char*) &from_array,sizeof(from_array));
if (!*from) 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)); start=buff=my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE));
while (*from) while (*from)
{ {
char *to=buff; char *to=buff;
to=get_string(&buff, &from, q); to=get_string(&buff, &from, q);
if (!*from) 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); insert_pointer_name(&from_array,to);
to=get_string(&buff, &from, q); to=get_string(&buff, &from, q);
insert_pointer_name(&to_array,to); insert_pointer_name(&to_array,to);
...@@ -1534,7 +1759,7 @@ static void get_replace(struct st_query *q) ...@@ -1534,7 +1759,7 @@ static void get_replace(struct st_query *q)
(uint) from_array.typelib.count, (uint) from_array.typelib.count,
word_end_chars)) || word_end_chars)) ||
initialize_replace_buffer()) 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(&from_array);
free_pointer_array(&to_array); free_pointer_array(&to_array);
my_free(start, MYF(0)); my_free(start, MYF(0));
...@@ -1561,11 +1786,16 @@ int select_connection(char *p) ...@@ -1561,11 +1786,16 @@ int select_connection(char *p)
DBUG_PRINT("enter",("name: '%s'",p)); DBUG_PRINT("enter",("name: '%s'",p));
if (!*p) if (!*p)
die("Missing connection name in connect\n"); die("Missing connection name in connect");
name = p; name = p;
while (*p && !my_isspace(charset_info,*p)) while (*p && !my_isspace(charset_info,*p))
p++; p++;
*p = 0;
if (*p)
{
*p++= 0;
check_eol_junk(p);
}
for (con = cons; con < next_con; con++) for (con = cons; con < next_con; con++)
{ {
...@@ -1587,11 +1817,16 @@ int close_connection(struct st_query* q) ...@@ -1587,11 +1817,16 @@ int close_connection(struct st_query* q)
DBUG_PRINT("enter",("name: '%s'",p)); DBUG_PRINT("enter",("name: '%s'",p));
if (!*p) if (!*p)
die("Missing connection name in connect\n"); die("Missing connection name in connect");
name = p; name = p;
while (*p && !my_isspace(charset_info,*p)) while (*p && !my_isspace(charset_info,*p))
p++; p++;
*p = 0;
if (*p)
{
*p++= 0;
check_eol_junk(p);
}
for (con = cons; con < next_con; con++) for (con = cons; con < next_con; con++)
{ {
...@@ -1723,6 +1958,7 @@ int do_connect(struct st_query* q) ...@@ -1723,6 +1958,7 @@ int do_connect(struct st_query* q)
con_sock[var_sock->str_val_len] = 0; con_sock[var_sock->str_val_len] = 0;
} }
} }
check_eol_junk(p);
if (next_con == cons_end) if (next_con == cons_end)
die("Connection limit exhausted - increase MAX_CONS in mysqltest.c"); die("Connection limit exhausted - increase MAX_CONS in mysqltest.c");
...@@ -1783,7 +2019,8 @@ int do_done(struct st_query* q) ...@@ -1783,7 +2019,8 @@ int do_done(struct st_query* q)
cur_block--; cur_block--;
parser.current_line++; 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) ...@@ -1817,6 +2054,15 @@ int do_block(enum enum_commands cmd, struct st_query* q)
expr_end = strrchr(expr_start, ')'); expr_end = strrchr(expr_start, ')');
if (!expr_end) if (!expr_end)
die("missing ')' in while"); 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); var_init(&v,0,0,0,0);
eval_expr(&v, ++expr_start, &expr_end); eval_expr(&v, ++expr_start, &expr_end);
...@@ -1877,6 +2123,30 @@ my_bool end_of_query(int c) ...@@ -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 read_line(char* buf, int size)
{ {
int c; int c;
...@@ -1898,9 +2168,23 @@ int read_line(char* buf, int size) ...@@ -1898,9 +2168,23 @@ int read_line(char* buf, int size)
if ((*cur_file) != stdin) if ((*cur_file) != stdin)
my_fclose(*cur_file, MYF(0)); my_fclose(*cur_file, MYF(0));
cur_file--; cur_file--;
char* p= file_name_stack[cur_file_name--]= 0;
if (p)
free(p);
lineno--; lineno--;
start_lineno= *lineno;
if (cur_file == file_stack) 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); DBUG_RETURN(1);
}
continue; continue;
} }
...@@ -1933,7 +2217,8 @@ int read_line(char* buf, int size) ...@@ -1933,7 +2217,8 @@ int read_line(char* buf, int size)
} }
break; break;
case R_LINE_START: 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; state = R_COMMENT;
} }
...@@ -2044,6 +2329,26 @@ int read_line(char* buf, int size) ...@@ -2044,6 +2329,26 @@ int read_line(char* buf, int size)
DBUG_RETURN(feof(*cur_file)); 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 !$<num> or !S<alphanum> 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 @<file_name> this will specify a file to ....
*/
static char read_query_buf[MAX_QUERY]; static char read_query_buf[MAX_QUERY];
...@@ -2409,7 +2714,7 @@ static void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val, ...@@ -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); len=(int) replace_strings(glob_replace, &out_buff, &out_length, val);
if (len == -1) if (len == -1)
die("Out of memory in replace\n"); die("Out of memory in replace");
val=out_buff; val=out_buff;
} }
dynstr_append_mem(ds, val, len); dynstr_append_mem(ds, val, len);
...@@ -2541,8 +2846,8 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags) ...@@ -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); got_error_on_send= mysql_send_query(mysql, query, query_len);
if (got_error_on_send && q->expected_errno[0].type == ERR_EMPTY) 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)", die("unable to send query '%s' (mysql_errno=%d , errno=%d)",
start_lineno, query, mysql_errno(mysql), errno); query, mysql_errno(mysql), errno);
} }
do do
...@@ -2566,7 +2871,7 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags) ...@@ -2566,7 +2871,7 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags)
abort_not_supported_test(); abort_not_supported_test();
} }
if (q->abort_on_error) 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)); mysql_errno(mysql), mysql_error(mysql));
else else
{ {
...@@ -2653,7 +2958,7 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags) ...@@ -2653,7 +2958,7 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags)
if (!disable_result_log) if (!disable_result_log)
{ {
ulong affected_rows; /* Ok to be undef if 'disable_info' is set */ ulong affected_rows= 0;
if (res) if (res)
{ {
...@@ -2720,7 +3025,7 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags) ...@@ -2720,7 +3025,7 @@ static int run_query_normal(MYSQL* mysql, struct st_query* q, int flags)
if (record) if (record)
{ {
if (!q->record_file[0] && !result_file) if (!q->record_file[0] && !result_file)
die("At line %u: Missing result file", start_lineno); die("Missing result file");
if (!result_file) if (!result_file)
str_to_file(q->record_file, ds->str, ds->length); 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) ...@@ -2782,7 +3087,7 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags)
may be a new connection. may be a new connection.
*/ */
if (!(stmt= mysql_stmt_init(mysql))) if (!(stmt= mysql_stmt_init(mysql)))
die("At line %u: unable init stmt structure"); die("unable init stmt structure");
if (q->type != Q_EVAL) if (q->type != Q_EVAL)
{ {
...@@ -2826,9 +3131,9 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags) ...@@ -2826,9 +3131,9 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags)
{ {
if (q->abort_on_error) 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)", "%s (mysql_stmt_errno=%d returned=%d)",
start_lineno, query, query,
mysql_stmt_error(stmt), mysql_stmt_errno(stmt), err); mysql_stmt_error(stmt), mysql_stmt_errno(stmt), err);
} }
else else
...@@ -2860,9 +3165,9 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags) ...@@ -2860,9 +3165,9 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags)
if (q->abort_on_error) if (q->abort_on_error)
{ {
/* We got an error, unexpected */ /* 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)", "%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); mysql_stmt_errno(stmt), got_error_on_execute);
} }
else else
...@@ -2882,9 +3187,9 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags) ...@@ -2882,9 +3187,9 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags)
my_bool one= 1; my_bool one= 1;
if (mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH, if (mysql_stmt_attr_set(stmt, STMT_ATTR_UPDATE_MAX_LENGTH,
(void*) &one) != 0) (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)", "'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) ...@@ -2896,9 +3201,9 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags)
if (q->abort_on_error) if (q->abort_on_error)
{ {
/* We got an error, unexpected */ /* 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)", "%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); mysql_stmt_errno(stmt), got_error_on_execute);
} }
else else
...@@ -2989,18 +3294,18 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags) ...@@ -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 */ /* Fill in the data into the structures created above */
if ((err= mysql_stmt_bind_result(stmt, bind)) != 0) 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)", "%s (mysql_stmt_errno=%d returned=%d)",
start_lineno, query, query,
mysql_stmt_error(stmt), mysql_stmt_errno(stmt), err); mysql_stmt_error(stmt), mysql_stmt_errno(stmt), err);
/* Read result from each row */ /* Read result from each row */
for (row_idx= 0; row_idx < num_rows; row_idx++) for (row_idx= 0; row_idx < num_rows; row_idx++)
{ {
if ((err= mysql_stmt_fetch(stmt)) != 0) 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)", "%s (mysql_stmt_errno=%d returned=%d)",
start_lineno, query, query,
mysql_stmt_error(stmt), mysql_stmt_errno(stmt), err); mysql_stmt_error(stmt), mysql_stmt_errno(stmt), err);
/* Read result from each column */ /* Read result from each column */
...@@ -3038,9 +3343,9 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags) ...@@ -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) 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)", "'%s': %s (mysql_stmt_errno=%d returned=%d)",
start_lineno, query, query,
mysql_stmt_error(stmt), mysql_stmt_errno(stmt), err); mysql_stmt_error(stmt), mysql_stmt_errno(stmt), err);
free_replace_column(); free_replace_column();
...@@ -3077,7 +3382,7 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags) ...@@ -3077,7 +3382,7 @@ static int run_query_stmt(MYSQL *mysql, struct st_query *q, int flags)
if (record) if (record)
{ {
if (!q->record_file[0] && !result_file) if (!q->record_file[0] && !result_file)
die("At line %u: Missing result file", start_lineno); die("Missing result file");
if (!result_file) if (!result_file)
str_to_file(q->record_file, ds->str, ds->length); 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, ...@@ -3198,7 +3503,7 @@ static int run_query_stmt_handle_error(char *query, struct st_query *q,
} }
if (q->abort_on_error) 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)); mysql_stmt_errno(stmt), mysql_stmt_error(stmt));
else else
{ {
...@@ -3438,7 +3743,7 @@ int main(int argc, char **argv) ...@@ -3438,7 +3743,7 @@ int main(int argc, char **argv)
struct st_query *q; struct st_query *q;
my_bool require_file=0, q_send_flag=0; my_bool require_file=0, q_send_flag=0;
char save_file[FN_REFLEN]; char save_file[FN_REFLEN];
MY_INIT(argv[0]); MY_INIT("mysqltest");
{ {
DBUG_ENTER("main"); DBUG_ENTER("main");
DBUG_PROCESS(argv[0]); DBUG_PROCESS(argv[0]);
...@@ -3454,15 +3759,16 @@ int main(int argc, char **argv) ...@@ -3454,15 +3759,16 @@ int main(int argc, char **argv)
cur_con = cons; cur_con = cons;
memset(file_stack, 0, sizeof(file_stack)); memset(file_stack, 0, sizeof(file_stack));
memset(file_name_stack, 0, sizeof(file_name_stack));
memset(&master_pos, 0, sizeof(master_pos)); 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; cur_file = file_stack;
lineno = lineno_stack; lineno = lineno_stack;
my_init_dynamic_array(&q_lines, sizeof(struct st_query*), INIT_Q_LINES, my_init_dynamic_array(&q_lines, sizeof(struct st_query*), INIT_Q_LINES,
INIT_Q_LINES); INIT_Q_LINES);
memset(block_stack, 0, sizeof(block_stack)); 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= block_stack;
cur_block->ok= TRUE; /* Outer block should always be executed */ cur_block->ok= TRUE; /* Outer block should always be executed */
cur_block->cmd= Q_UNKNOWN; cur_block->cmd= Q_UNKNOWN;
...@@ -3474,7 +3780,10 @@ int main(int argc, char **argv) ...@@ -3474,7 +3780,10 @@ int main(int argc, char **argv)
(char**) embedded_server_groups)) (char**) embedded_server_groups))
die("Can't initialize MySQL server"); die("Can't initialize MySQL server");
if (cur_file == file_stack) if (cur_file == file_stack)
*++cur_file = stdin; {
*++cur_file= stdin;
++cur_file_name;
}
*lineno=1; *lineno=1;
#ifndef EMBEDDED_LIBRARY #ifndef EMBEDDED_LIBRARY
if (manager_host) if (manager_host)
...@@ -3530,18 +3839,30 @@ int main(int argc, char **argv) ...@@ -3530,18 +3839,30 @@ int main(int argc, char **argv)
case Q_RPL_PROBE: do_rpl_probe(q); break; case Q_RPL_PROBE: do_rpl_probe(q); break;
case Q_ENABLE_RPL_PARSE: do_enable_rpl_parse(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_DISABLE_RPL_PARSE: do_disable_rpl_parse(q); break;
case Q_ENABLE_QUERY_LOG: disable_query_log=0; break; case Q_ENABLE_QUERY_LOG:
case Q_DISABLE_QUERY_LOG: disable_query_log=1; break; disable_query_log=0; check_eol_junk(q->first_argument); break;
case Q_ENABLE_ABORT_ON_ERROR: abort_on_error=1; break; case Q_DISABLE_QUERY_LOG:
case Q_DISABLE_ABORT_ON_ERROR: abort_on_error=0; break; disable_query_log=1; check_eol_junk(q->first_argument); break;
case Q_ENABLE_RESULT_LOG: disable_result_log=0; break; case Q_ENABLE_ABORT_ON_ERROR:
case Q_DISABLE_RESULT_LOG: disable_result_log=1; break; abort_on_error=1; check_eol_junk(q->first_argument); break;
case Q_ENABLE_WARNINGS: disable_warnings=0; break; case Q_DISABLE_ABORT_ON_ERROR:
case Q_DISABLE_WARNINGS: disable_warnings=1; break; abort_on_error=0; check_eol_junk(q->first_argument); break;
case Q_ENABLE_INFO: disable_info=0; break; case Q_ENABLE_RESULT_LOG:
case Q_DISABLE_INFO: disable_info=1; break; disable_result_log=0; check_eol_junk(q->first_argument); break;
case Q_ENABLE_METADATA: display_metadata=1; break; case Q_DISABLE_RESULT_LOG:
case Q_DISABLE_METADATA: display_metadata=0; break; 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_SOURCE: do_source(q); break;
case Q_SLEEP: do_sleep(q, 0); break; case Q_SLEEP: do_sleep(q, 0); break;
case Q_REAL_SLEEP: do_sleep(q, 1); break; case Q_REAL_SLEEP: do_sleep(q, 1); break;
...@@ -3558,12 +3879,19 @@ int main(int argc, char **argv) ...@@ -3558,12 +3879,19 @@ int main(int argc, char **argv)
case Q_DELIMITER: case Q_DELIMITER:
strmake(delimiter, q->first_argument, sizeof(delimiter) - 1); strmake(delimiter, q->first_argument, sizeof(delimiter) - 1);
delimiter_length= strlen(delimiter); delimiter_length= strlen(delimiter);
check_eol_junk(q->first_argument+delimiter_length);
break;
case Q_DISPLAY_VERTICAL_RESULTS:
display_result_vertically= TRUE;
check_eol_junk(q->first_argument);
break; break;
case Q_DISPLAY_VERTICAL_RESULTS: display_result_vertically= TRUE; break;
case Q_DISPLAY_HORIZONTAL_RESULTS: case Q_DISPLAY_HORIZONTAL_RESULTS:
display_result_vertically= FALSE; break; display_result_vertically= FALSE;
check_eol_junk(q->first_argument);
break;
case Q_LET: do_let(q); 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: case Q_EVAL:
if (q->query == q->query_buf) if (q->query == q->query_buf)
{ {
...@@ -3677,6 +4005,7 @@ int main(int argc, char **argv) ...@@ -3677,6 +4005,7 @@ int main(int argc, char **argv)
break; break;
case Q_PING: case Q_PING:
(void) mysql_ping(&cur_con->mysql); (void) mysql_ping(&cur_con->mysql);
check_eol_junk(q->first_argument);
break; break;
case Q_EXEC: case Q_EXEC:
do_exec(q); do_exec(q);
...@@ -3684,26 +4013,32 @@ int main(int argc, char **argv) ...@@ -3684,26 +4013,32 @@ int main(int argc, char **argv)
case Q_START_TIMER: case Q_START_TIMER:
/* Overwrite possible earlier start of timer */ /* Overwrite possible earlier start of timer */
timer_start= timer_now(); timer_start= timer_now();
check_eol_junk(q->first_argument);
break; break;
case Q_END_TIMER: case Q_END_TIMER:
/* End timer before ending mysqltest */ /* End timer before ending mysqltest */
timer_output(); timer_output();
got_end_timer= TRUE; got_end_timer= TRUE;
check_eol_junk(q->first_argument);
break; break;
case Q_CHARACTER_SET: case Q_CHARACTER_SET:
set_charset(q); set_charset(q);
break; break;
case Q_DISABLE_PS_PROTOCOL: case Q_DISABLE_PS_PROTOCOL:
ps_protocol_enabled= 0; ps_protocol_enabled= 0;
check_eol_junk(q->first_argument);
break; break;
case Q_ENABLE_PS_PROTOCOL: case Q_ENABLE_PS_PROTOCOL:
ps_protocol_enabled= ps_protocol; ps_protocol_enabled= ps_protocol;
check_eol_junk(q->first_argument);
break; break;
case Q_DISABLE_RECONNECT: case Q_DISABLE_RECONNECT:
cur_con->mysql.reconnect= 0; cur_con->mysql.reconnect= 0;
check_eol_junk(q->first_argument);
break; break;
case Q_ENABLE_RECONNECT: case Q_ENABLE_RECONNECT:
cur_con->mysql.reconnect= 1; cur_con->mysql.reconnect= 1;
check_eol_junk(q->first_argument);
break; break;
default: processed = 0; break; default: processed = 0; break;
...@@ -3724,7 +4059,7 @@ int main(int argc, char **argv) ...@@ -3724,7 +4059,7 @@ int main(int argc, char **argv)
parser.current_line += current_line_inc; parser.current_line += current_line_inc;
} }
if (result_file && ds_res.length) if (result_file && ds_res.length && !error)
{ {
if (!record) if (!record)
error |= check_result(&ds_res, result_file, q->require_file); error |= check_result(&ds_res, result_file, q->require_file);
...@@ -4584,7 +4919,7 @@ static void get_replace_column(struct st_query *q) ...@@ -4584,7 +4919,7 @@ static void get_replace_column(struct st_query *q)
free_replace_column(); free_replace_column();
if (!*from) if (!*from)
die("Missing argument in %s\n", q->query); die("Missing argument in %s", q->query);
/* Allocate a buffer for results */ /* Allocate a buffer for results */
start=buff=my_malloc(strlen(from)+1,MYF(MY_WME | MY_FAE)); 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) ...@@ -4595,9 +4930,9 @@ static void get_replace_column(struct st_query *q)
to= get_string(&buff, &from, q); to= get_string(&buff, &from, q);
if (!(column_number= atoi(to)) || column_number > MAX_COLUMNS) 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) 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); to= get_string(&buff, &from, q);
my_free(replace_column[column_number-1], MY_ALLOW_ZERO_PTR); my_free(replace_column[column_number-1], MY_ALLOW_ZERO_PTR);
replace_column[column_number-1]= my_strdup(to, MYF(MY_WME | MY_FAE)); 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) ...@@ -4654,7 +4989,7 @@ static char *subst_env_var(const char *str)
if (!(subst= getenv(env_var))) if (!(subst= getenv(env_var)))
{ {
my_free(result, MYF(0)); 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); env_var);
} }
......
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;
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
}
...@@ -2129,6 +2129,11 @@ sub run_mysqltest ($) { ...@@ -2129,6 +2129,11 @@ sub run_mysqltest ($) {
mysqld_arguments($args,'master',0,$tinfo->{'master_opt'},[]); mysqld_arguments($args,'master',0,$tinfo->{'master_opt'},[]);
} }
# ----------------------------------------------------------------------
# export MYSQL_TEST variable containing <path>/mysqltest <args>
# ----------------------------------------------------------------------
$ENV{'MYSQL_TEST'}= "$exe_mysqltest " . join(" ", @$args);
return mtr_run_test($exe,$args,$tinfo->{'path'},"",$path_timefile,""); return mtr_run_test($exe,$args,$tinfo->{'path'},"",$path_timefile,"");
} }
......
...@@ -714,6 +714,7 @@ if [ x$USE_TIMER = x1 ] ; then ...@@ -714,6 +714,7 @@ if [ x$USE_TIMER = x1 ] ; then
fi fi
MYSQL_TEST_BIN=$MYSQL_TEST MYSQL_TEST_BIN=$MYSQL_TEST
MYSQL_TEST="$MYSQL_TEST $MYSQL_TEST_ARGS" MYSQL_TEST="$MYSQL_TEST $MYSQL_TEST_ARGS"
export MYSQL_TEST
GDB_CLIENT_INIT=$MYSQL_TMP_DIR/gdbinit.client GDB_CLIENT_INIT=$MYSQL_TMP_DIR/gdbinit.client
GDB_MASTER_INIT=$MYSQL_TMP_DIR/gdbinit.master GDB_MASTER_INIT=$MYSQL_TMP_DIR/gdbinit.master
GDB_SLAVE_INIT=$MYSQL_TMP_DIR/gdbinit.slave GDB_SLAVE_INIT=$MYSQL_TMP_DIR/gdbinit.slave
......
...@@ -7,6 +7,7 @@ otto ...@@ -7,6 +7,7 @@ otto
select otto from (select 1 as otto) as t1; select otto from (select 1 as otto) as t1;
otto otto
1 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; select friedrich from (select 1 as otto) as t1;
ERROR 42S22: Unknown column 'friedrich' in 'field list' ERROR 42S22: Unknown column 'friedrich' in 'field list'
select otto from (select 1 as otto) as t1; select otto from (select 1 as otto) as t1;
...@@ -15,10 +16,12 @@ otto ...@@ -15,10 +16,12 @@ otto
select otto from (select 1 as otto) as t1; select otto from (select 1 as otto) as t1;
otto otto
1 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; select friedrich from (select 1 as otto) as t1;
ERROR 42S22: Unknown column 'friedrich' in 'field list' ERROR 42S22: Unknown column 'friedrich' in 'field list'
select friedrich from (select 1 as otto) as t1; select friedrich from (select 1 as otto) as t1;
ERROR 42S22: Unknown column 'friedrich' in 'field list' 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; select otto from (select 1 as otto) as t1;
otto otto
1 1
...@@ -135,6 +138,8 @@ ERROR 42S02: Table 'test.t1' doesn't exist ...@@ -135,6 +138,8 @@ ERROR 42S02: Table 'test.t1' doesn't exist
select 1146 as "after_!errno_masked_error" ; select 1146 as "after_!errno_masked_error" ;
after_!errno_masked_error after_!errno_masked_error
1146 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 ; 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 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" ; select 1064 as "after_--enable_abort_on_error" ;
...@@ -142,3 +147,119 @@ after_--enable_abort_on_error ...@@ -142,3 +147,119 @@ after_--enable_abort_on_error
1064 1064
select 3 from t1 ; select 3 from t1 ;
ERROR 42S02: Table 'test.t1' doesn't exist 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 '{'
...@@ -4,10 +4,10 @@ reset master; ...@@ -4,10 +4,10 @@ reset master;
reset slave; reset slave;
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
start slave; start slave;
stop slave;
change master to master_host='127.0.0.1',master_user='root', change master to master_host='127.0.0.1',master_user='root',
master_password='',master_port=MASTER_PORT; master_password='',master_port=MASTER_PORT;
start slave; start slave;
stop slave;
change master to master_host='127.0.0.1',master_user='root', change master to master_host='127.0.0.1',master_user='root',
master_password='',master_port=SLAVE_PORT; master_password='',master_port=SLAVE_PORT;
start slave; start slave;
......
...@@ -25,7 +25,7 @@ set autocommit=0; ...@@ -25,7 +25,7 @@ set autocommit=0;
# The following query should hang because con1 is locking the page # The following query should hang because con1 is locking the page
--send --send
update t1 set x=2 where id = 0; update t1 set x=2 where id = 0;
--sleep 2; --sleep 2
connection con1; connection con1;
update t1 set x=1 where id = 0; update t1 set x=1 where id = 0;
...@@ -63,7 +63,7 @@ set autocommit=0; ...@@ -63,7 +63,7 @@ set autocommit=0;
# The following query should hang because con1 is locking the page # The following query should hang because con1 is locking the page
--send --send
update t1 set x=2 where id = 0; update t1 set x=2 where id = 0;
--sleep 2; --sleep 2
connection con1; connection con1;
update t1 set x=1 where id = 0; update t1 set x=1 where id = 0;
...@@ -97,7 +97,7 @@ update t2 set a=2 where b = 0; ...@@ -97,7 +97,7 @@ update t2 set a=2 where b = 0;
select * from t2; select * from t2;
--send --send
update t1 set x=2 where id = 0; update t1 set x=2 where id = 0;
--sleep 2; --sleep 2
connection con1; connection con1;
update t1 set x=1 where id = 0; update t1 set x=1 where id = 0;
......
...@@ -39,7 +39,7 @@ set autocommit=0; ...@@ -39,7 +39,7 @@ set autocommit=0;
# The following statement should hang because con1 is locking the page # The following statement should hang because con1 is locking the page
--send --send
lock table t1 write; lock table t1 write;
--sleep 2; --sleep 2
connection con1; connection con1;
update t1 set x=1 where id = 0; update t1 set x=1 where id = 0;
......
...@@ -3,6 +3,24 @@ ...@@ -3,6 +3,24 @@
# #
# Test of mysqltest itself # Test of mysqltest itself
# #
# There are three rules that determines what belong to each command
# 1. A normal command is delimited by the <delimiter> 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 <delimiter>
#
# 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; ...@@ -37,7 +55,9 @@ select otto from (select 1 as otto) as t1;
# expectation <> response # expectation <> response
#--error 0 #--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 # expectation = response
--error 1054 --error 1054
...@@ -65,6 +85,9 @@ select otto from (select 1 as otto) as t1; ...@@ -65,6 +85,9 @@ select otto from (select 1 as otto) as t1;
#!S42S22 select otto from (select 1 as otto) as t1; #!S42S22 select otto from (select 1 as otto) as t1;
#--error S42S22 #--error S42S22
#select otto from (select 1 as otto) as t1; #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; ...@@ -80,7 +103,8 @@ select friedrich from (select 1 as otto) as t1;
#!S00000 select friedrich from (select 1 as otto) as t1; #!S00000 select friedrich from (select 1 as otto) as t1;
#--error S00000 #--error S00000
#select friedrich from (select 1 as otto) as t1; #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 # test cases for $mysql_errno
...@@ -262,6 +286,8 @@ eval select $mysql_errno as "after_!errno_masked_error" ; ...@@ -262,6 +286,8 @@ eval select $mysql_errno as "after_!errno_masked_error" ;
# select 3 from t1 ; # select 3 from t1 ;
# --error 1000 # --error 1000
# select 3 from t1 ; # 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 # Switch the abort on error on and check the effect on $mysql_errno
...@@ -286,3 +312,359 @@ select 3 from t1 ; ...@@ -286,3 +312,359 @@ select 3 from t1 ;
#select 3 from t1 ; #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
# ----------------------------------------------------------------------------
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
# The previous step has simply removed the frm file # The previous step has simply removed the frm file
# from disk, but left the table in NDB # from disk, but left the table in NDB
# #
--sleep 3; --sleep 3
select * from t9 order by a; select * from t9 order by a;
# handler_discover should be 1 # handler_discover should be 1
......
...@@ -8,7 +8,7 @@ insert into t1 values(1+get_lock("a",15)*0); ...@@ -8,7 +8,7 @@ insert into t1 values(1+get_lock("a",15)*0);
insert into t1 values(2); insert into t1 values(2);
save_master_pos; save_master_pos;
connection slave; 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; stop slave;
select * from t1; select * from t1;
--replace_result $MASTER_MYPORT MASTER_MYPORT --replace_result $MASTER_MYPORT MASTER_MYPORT
......
...@@ -58,7 +58,7 @@ while ($1) ...@@ -58,7 +58,7 @@ while ($1)
enable_query_log; enable_query_log;
select * from t1 for update; select * from t1 for update;
start slave; 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 insert into t2 values(22); # provoke deadlock, slave should be victim
commit; commit;
sync_with_master; sync_with_master;
...@@ -76,7 +76,7 @@ change master to master_log_pos=401; # the BEGIN log event ...@@ -76,7 +76,7 @@ change master to master_log_pos=401; # the BEGIN log event
begin; begin;
select * from t2 for update; # hold lock select * from t2 for update; # hold lock
start slave; start slave;
--sleep 10; # slave should have blocked, and be retrying --sleep 10 # slave should have blocked, and be retrying
commit; commit;
sync_with_master; sync_with_master;
select * from t1; # check that slave succeeded finally select * from t1; # check that slave succeeded finally
...@@ -97,7 +97,7 @@ change master to master_log_pos=401; ...@@ -97,7 +97,7 @@ change master to master_log_pos=401;
begin; begin;
select * from t2 for update; select * from t2 for update;
start slave; start slave;
--sleep 10; --sleep 10
commit; commit;
sync_with_master; sync_with_master;
select * from t1; select * from t1;
......
...@@ -9,5 +9,5 @@ sync_slave_with_master; ...@@ -9,5 +9,5 @@ sync_slave_with_master;
connection master; connection master;
disconnect master; disconnect master;
connection slave; 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'; show status like 'Slave_open_temp_tables';
# Testing if "flush logs" command bouncing resulting in logs created in a loop # Testing if "flush logs" command bouncing resulting in logs created in a loop
# in case of bi-directional replication # in case of bi-directional replication
source include/master-slave.inc source include/master-slave.inc;
connection slave; connection slave;
stop slave;
--replace_result $MASTER_MYPORT MASTER_PORT --replace_result $MASTER_MYPORT MASTER_PORT
eval change master to master_host='127.0.0.1',master_user='root', eval change master to master_host='127.0.0.1',master_user='root',
master_password='',master_port=$MASTER_MYPORT; master_password='',master_port=$MASTER_MYPORT;
start slave; start slave;
connection master; connection master;
stop slave;
--replace_result $SLAVE_MYPORT SLAVE_PORT --replace_result $SLAVE_MYPORT SLAVE_PORT
eval change master to master_host='127.0.0.1',master_user='root', eval change master to master_host='127.0.0.1',master_user='root',
master_password='',master_port=$SLAVE_MYPORT; master_password='',master_port=$SLAVE_MYPORT;
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# We also check how the foreign_key_check variable is replicated # We also check how the foreign_key_check variable is replicated
source include/master-slave.inc; source include/master-slave.inc;
source include/have_innodb.inc source include/have_innodb.inc;
connection master; connection master;
create table t1(a int auto_increment, key(a)); create table t1(a int auto_increment, key(a));
create table t2(b int auto_increment, c int, key(b)); create table t2(b int auto_increment, c int, key(b));
......
...@@ -102,7 +102,7 @@ show master logs; ...@@ -102,7 +102,7 @@ show master logs;
purge binary logs to 'master-bin.000002'; purge binary logs to 'master-bin.000002';
show binary logs; show binary logs;
# sleeping 10 seconds or more would make the slave believe connection is down # sleeping 10 seconds or more would make the slave believe connection is down
--real_sleep 1; --real_sleep 1
purge master logs before now(); purge master logs before now();
show binary logs; show binary logs;
insert into t2 values (65); insert into t2 values (65);
......
...@@ -60,7 +60,7 @@ stop slave; ...@@ -60,7 +60,7 @@ stop slave;
# this should stop immideately # this should stop immideately
start slave until master_log_file='master-bin.000001', master_log_pos=561; start slave until master_log_file='master-bin.000001', master_log_pos=561;
# 2 is not enough when running with valgrind # 2 is not enough when running with valgrind
real_sleep 4 --real_sleep 4
# here the sql slave thread should be stopped # 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_result $MASTER_MYPORT MASTER_MYPORT bin.000005 bin.000004 bin.000006 bin.000004 bin.000007 bin.000004
--replace_column 1 # 9 # 23 # 33 # --replace_column 1 # 9 # 23 # 33 #
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment