Added support for multi statement tests. Use mysqltest internal

command delimiter to change the default delimiter (;) to something
else, a string upto 16 characters is allowed. Separate the sub
queries with ';' and end the whole statement with your own delimiter.
parent cde71302
...@@ -42,7 +42,7 @@ ...@@ -42,7 +42,7 @@
**********************************************************************/ **********************************************************************/
#define MTEST_VERSION "2.0" #define MTEST_VERSION "2.1"
#include <my_global.h> #include <my_global.h>
#include <mysql_embed.h> #include <mysql_embed.h>
...@@ -86,7 +86,8 @@ ...@@ -86,7 +86,8 @@
#define MAX_CON_TRIES 5 #define MAX_CON_TRIES 5
#define SLAVE_POLL_INTERVAL 300000 /* 0.3 of a sec */ #define SLAVE_POLL_INTERVAL 300000 /* 0.3 of a sec */
#define DEFAULT_DELIMITER ";"
#define MAX_DELIMITER 16
enum {OPT_MANAGER_USER=256,OPT_MANAGER_HOST,OPT_MANAGER_PASSWD, enum {OPT_MANAGER_USER=256,OPT_MANAGER_HOST,OPT_MANAGER_PASSWD,
OPT_MANAGER_PORT,OPT_MANAGER_WAIT_TIMEOUT, OPT_SKIP_SAFEMALLOC, OPT_MANAGER_PORT,OPT_MANAGER_WAIT_TIMEOUT, OPT_SKIP_SAFEMALLOC,
...@@ -114,6 +115,8 @@ static FILE** cur_file; ...@@ -114,6 +115,8 @@ static FILE** cur_file;
static FILE** file_stack_end; static FILE** file_stack_end;
static uint lineno_stack[MAX_INCLUDE_DEPTH]; static uint lineno_stack[MAX_INCLUDE_DEPTH];
static char TMPDIR[FN_REFLEN]; static char TMPDIR[FN_REFLEN];
static char delimiter[MAX_DELIMITER]= DEFAULT_DELIMITER;
static uint delimiter_length= 1;
static int *cur_block, *block_stack_end; static int *cur_block, *block_stack_end;
static int block_stack[BLOCK_STACK_DEPTH]; static int block_stack[BLOCK_STACK_DEPTH];
...@@ -209,7 +212,8 @@ Q_WAIT_FOR_SLAVE_TO_STOP, ...@@ -209,7 +212,8 @@ Q_WAIT_FOR_SLAVE_TO_STOP,
Q_REQUIRE_VERSION, Q_REQUIRE_VERSION,
Q_ENABLE_WARNINGS, Q_DISABLE_WARNINGS, Q_ENABLE_WARNINGS, Q_DISABLE_WARNINGS,
Q_ENABLE_INFO, Q_DISABLE_INFO, Q_ENABLE_INFO, Q_DISABLE_INFO,
Q_EXEC, Q_EXEC, Q_DELIMITER,
Q_UNKNOWN, /* Unknown command. */ Q_UNKNOWN, /* Unknown command. */
Q_COMMENT, /* Comments, ignored. */ Q_COMMENT, /* Comments, ignored. */
Q_COMMENT_WITH_COMMAND Q_COMMENT_WITH_COMMAND
...@@ -281,6 +285,7 @@ const char *command_names[]= ...@@ -281,6 +285,7 @@ const char *command_names[]=
"enable_info", "enable_info",
"disable_info", "disable_info",
"exec", "exec",
"delimiter",
0 0
}; };
...@@ -1472,7 +1477,8 @@ int safe_connect(MYSQL* con, const char* host, const char* user, ...@@ -1472,7 +1477,8 @@ int safe_connect(MYSQL* con, const char* host, const char* user,
int i; int i;
for (i = 0; i < MAX_CON_TRIES; ++i) for (i = 0; i < MAX_CON_TRIES; ++i)
{ {
if (mysql_real_connect(con, host,user, pass, db, port, sock, 0)) if (mysql_real_connect(con, host,user, pass, db, port, sock,
CLIENT_MULTI_STATEMENTS))
{ {
con_error = 0; con_error = 0;
break; break;
...@@ -1622,24 +1628,46 @@ int do_while(struct st_query* q) ...@@ -1622,24 +1628,46 @@ int do_while(struct st_query* q)
} }
my_bool end_of_query(int c, char* p)
{
uint i= 0, j;
int tmp[MAX_DELIMITER]= {0};
for (i= 0; c == *(delimiter + i) && i < delimiter_length;
i++, c= fgetc(*cur_file))
tmp[i]= c;
tmp[i]= c;
for (j= i; j > 0 && i != delimiter_length; j--)
ungetc(tmp[j], *cur_file);
if (i == delimiter_length)
{
ungetc(tmp[j], *cur_file);
*p= 0;
return 1;
}
return 0;
}
int read_line(char* buf, int size) int read_line(char* buf, int size)
{ {
int c; int c;
char* p = buf, *buf_end = buf + size-1; char* p= buf, *buf_end= buf + size - 1;
int no_save = 0; int no_save= 0;
enum {R_NORMAL, R_Q1, R_ESC_Q_Q1, R_ESC_Q_Q2, enum {R_NORMAL, R_Q1, R_ESC_Q_Q1, R_ESC_Q_Q2,
R_ESC_SLASH_Q1, R_ESC_SLASH_Q2, R_ESC_SLASH_Q1, R_ESC_SLASH_Q2,
R_Q2, R_COMMENT, R_LINE_START} state = R_LINE_START; R_Q2, R_COMMENT, R_LINE_START} state= R_LINE_START;
start_lineno= *lineno; start_lineno= *lineno;
for (; p < buf_end ;) for (; p < buf_end ;)
{ {
no_save = 0; no_save= 0;
c = fgetc(*cur_file); c= fgetc(*cur_file);
if (feof(*cur_file)) if (feof(*cur_file))
{ {
if ((*cur_file) != stdin) if ((*cur_file) != stdin)
my_fclose(*cur_file,MYF(0)); my_fclose(*cur_file, MYF(0));
cur_file--; cur_file--;
lineno--; lineno--;
if (cur_file == file_stack) if (cur_file == file_stack)
...@@ -1650,11 +1678,8 @@ int read_line(char* buf, int size) ...@@ -1650,11 +1678,8 @@ int read_line(char* buf, int size)
switch(state) { switch(state) {
case R_NORMAL: case R_NORMAL:
/* Only accept '{' in the beginning of a line */ /* Only accept '{' in the beginning of a line */
if (c == ';') if (end_of_query(c, p))
{
*p = 0;
return 0; return 0;
}
else if (c == '\'') else if (c == '\'')
state = R_Q1; state = R_Q1;
else if (c == '"') else if (c == '"')
...@@ -1668,7 +1693,7 @@ int read_line(char* buf, int size) ...@@ -1668,7 +1693,7 @@ int read_line(char* buf, int size)
case R_COMMENT: case R_COMMENT:
if (c == '\n') if (c == '\n')
{ {
*p=0; *p= 0;
(*lineno)++; (*lineno)++;
return 0; return 0;
} }
...@@ -1678,78 +1703,72 @@ int read_line(char* buf, int size) ...@@ -1678,78 +1703,72 @@ int read_line(char* buf, int size)
{ {
state = R_COMMENT; state = R_COMMENT;
} }
else if (my_isspace(charset_info,c)) else if (my_isspace(charset_info, c))
{ {
if (c == '\n') if (c == '\n')
start_lineno= ++*lineno; /* Query hasn't started yet */ start_lineno= ++*lineno; /* Query hasn't started yet */
no_save = 1; no_save= 1;
} }
else if (c == '}') else if (c == '}')
{ {
*buf++ = '}'; *buf++= '}';
*buf = 0; *buf= 0;
return 0; return 0;
} }
else if (c == ';' || c == '{') else if (end_of_query(c, p) || c == '{')
{ {
*p = 0; *p= 0;
return 0; return 0;
} }
else if (c == '\'') else if (c == '\'')
state = R_Q1; state= R_Q1;
else if (c == '"') else if (c == '"')
state = R_Q2; state= R_Q2;
else else
state = R_NORMAL; state= R_NORMAL;
break; break;
case R_Q1: case R_Q1:
if (c == '\'') if (c == '\'')
state = R_ESC_Q_Q1; state= R_ESC_Q_Q1;
else if (c == '\\') else if (c == '\\')
state = R_ESC_SLASH_Q1; state= R_ESC_SLASH_Q1;
break; break;
case R_ESC_Q_Q1: case R_ESC_Q_Q1:
if (c == ';') if (end_of_query(c, p))
{
*p = 0;
return 0; return 0;
}
if (c != '\'') if (c != '\'')
state = R_NORMAL; state= R_NORMAL;
else else
state = R_Q1; state= R_Q1;
break; break;
case R_ESC_SLASH_Q1: case R_ESC_SLASH_Q1:
state = R_Q1; state= R_Q1;
break; break;
case R_Q2: case R_Q2:
if (c == '"') if (c == '"')
state = R_ESC_Q_Q2; state= R_ESC_Q_Q2;
else if (c == '\\') else if (c == '\\')
state = R_ESC_SLASH_Q2; state= R_ESC_SLASH_Q2;
break; break;
case R_ESC_Q_Q2: case R_ESC_Q_Q2:
if (c == ';') if (end_of_query(c, p))
{
*p = 0;
return 0; return 0;
}
if (c != '"') if (c != '"')
state = R_NORMAL; state= R_NORMAL;
else else
state = R_Q2; state= R_Q2;
break; break;
case R_ESC_SLASH_Q2: case R_ESC_SLASH_Q2:
state = R_Q2; state= R_Q2;
break; break;
} }
if (!no_save) if (!no_save)
*p++ = c; *p++= c;
} }
*p=0; /* Always end with \0 */ *p= 0; /* Always end with \0 */
return feof(*cur_file); return feof(*cur_file);
} }
...@@ -1766,22 +1785,22 @@ int read_query(struct st_query** q_ptr) ...@@ -1766,22 +1785,22 @@ int read_query(struct st_query** q_ptr)
get_dynamic(&q_lines, (gptr) q_ptr, parser.current_line) ; get_dynamic(&q_lines, (gptr) q_ptr, parser.current_line) ;
return 0; return 0;
} }
if (!(*q_ptr=q=(struct st_query*) my_malloc(sizeof(*q), MYF(MY_WME))) || if (!(*q_ptr= q= (struct st_query*) my_malloc(sizeof(*q), MYF(MY_WME))) ||
insert_dynamic(&q_lines, (gptr) &q)) insert_dynamic(&q_lines, (gptr) &q))
die(NullS); die(NullS);
q->record_file[0] = 0; q->record_file[0]= 0;
q->require_file=0; q->require_file= 0;
q->first_word_len = 0; q->first_word_len= 0;
memcpy((gptr) q->expected_errno, (gptr) global_expected_errno, memcpy((gptr) q->expected_errno, (gptr) global_expected_errno,
sizeof(global_expected_errno)); sizeof(global_expected_errno));
q->expected_errors=global_expected_errors; q->expected_errors= global_expected_errors;
q->abort_on_error = global_expected_errno[0] == 0; q->abort_on_error= global_expected_errno[0] == 0;
bzero((gptr) global_expected_errno,sizeof(global_expected_errno)); bzero((gptr) global_expected_errno, sizeof(global_expected_errno));
global_expected_errors=0; global_expected_errors=0;
q->type = Q_UNKNOWN; q->type = Q_UNKNOWN;
q->query_buf=q->query=0; q->query_buf= q->query= 0;
if (read_line(read_query_buf, sizeof(read_query_buf))) if (read_line(read_query_buf, sizeof(read_query_buf)))
return 1; return 1;
...@@ -1791,20 +1810,20 @@ int read_query(struct st_query** q_ptr) ...@@ -1791,20 +1810,20 @@ int read_query(struct st_query** q_ptr)
} }
else if (p[0] == '-' && p[1] == '-') else if (p[0] == '-' && p[1] == '-')
{ {
q->type = Q_COMMENT_WITH_COMMAND; q->type= Q_COMMENT_WITH_COMMAND;
p+=2; /* To calculate first word */ p+= 2; /* To calculate first word */
} }
else else
{ {
if (*p == '!') if (*p == '!')
{ {
q->abort_on_error = 0; q->abort_on_error= 0;
p++; p++;
if (*p == '$') if (*p == '$')
{ {
expected_errno = 0; expected_errno= 0;
p++; p++;
for (;my_isdigit(charset_info,*p);p++) for (; my_isdigit(charset_info, *p); p++)
expected_errno = expected_errno * 10 + *p - '0'; expected_errno = expected_errno * 10 + *p - '0';
q->expected_errno[0] = expected_errno; q->expected_errno[0] = expected_errno;
q->expected_errno[1] = 0; q->expected_errno[1] = 0;
...@@ -1812,30 +1831,30 @@ int read_query(struct st_query** q_ptr) ...@@ -1812,30 +1831,30 @@ int read_query(struct st_query** q_ptr)
} }
} }
while (*p && my_isspace(charset_info,*p)) while (*p && my_isspace(charset_info, *p))
p++ ; p++ ;
if (*p == '@') if (*p == '@')
{ {
p++; p++;
p1 = q->record_file; p1 = q->record_file;
while (!my_isspace(charset_info,*p) && while (!my_isspace(charset_info, *p) &&
p1 < q->record_file + sizeof(q->record_file) - 1) p1 < q->record_file + sizeof(q->record_file) - 1)
*p1++ = *p++; *p1++ = *p++;
*p1 = 0; *p1 = 0;
} }
} }
while (*p && my_isspace(charset_info,*p)) while (*p && my_isspace(charset_info, *p))
p++; p++;
if (!(q->query_buf=q->query=my_strdup(p,MYF(MY_WME)))) if (!(q->query_buf= q->query= my_strdup(p, MYF(MY_WME))))
die(NullS); die(NullS);
/* Calculate first word and first argument */ /* Calculate first word and first argument */
for (p=q->query; *p && !my_isspace(charset_info,*p) ; p++) ; for (p= q->query; *p && !my_isspace(charset_info, *p) ; p++) ;
q->first_word_len = (uint) (p - q->query); q->first_word_len= (uint) (p - q->query);
while (*p && my_isspace(charset_info,*p)) while (*p && my_isspace(charset_info, *p))
p++; p++;
q->first_argument=p; q->first_argument= p;
q->end = strend(q->query); q->end= strend(q->query);
parser.read_lines++; parser.read_lines++;
return 0; return 0;
} }
...@@ -2129,12 +2148,12 @@ static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res) ...@@ -2129,12 +2148,12 @@ static void append_result(DYNAMIC_STRING *ds, MYSQL_RES *res)
int run_query(MYSQL* mysql, struct st_query* q, int flags) int run_query(MYSQL* mysql, struct st_query* q, int flags)
{ {
MYSQL_RES* res = 0; MYSQL_RES* res= 0;
int i, error = 0; int i, error= 0, err= 0, counter= 0;
DYNAMIC_STRING *ds; DYNAMIC_STRING *ds;
DYNAMIC_STRING ds_tmp; DYNAMIC_STRING ds_tmp;
DYNAMIC_STRING eval_query; DYNAMIC_STRING eval_query;
char* query; char* query, buff[MAX_DELIMITER + 1]= {0};
int query_len; int query_len;
DBUG_ENTER("run_query"); DBUG_ENTER("run_query");
...@@ -2162,18 +2181,21 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags) ...@@ -2162,18 +2181,21 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
if ((flags & QUERY_SEND) && mysql_send_query(mysql, query, query_len)) if ((flags & QUERY_SEND) && mysql_send_query(mysql, query, query_len))
die("At line %u: unable to send query '%s'(mysql_errno=%d,errno=%d)", die("At line %u: unable to send query '%s'(mysql_errno=%d,errno=%d)",
start_lineno, query, start_lineno, query, mysql_errno(mysql), errno);
mysql_errno(mysql), errno);
if ((flags & QUERY_SEND) && !disable_query_log) do
{
if ((flags & QUERY_SEND) && !disable_query_log && !counter)
{ {
replace_dynstr_append_mem(ds,query, query_len); replace_dynstr_append_mem(ds,query, query_len);
dynstr_append_mem(ds,";\n",2); sprintf(buff, "%s\n", delimiter);
dynstr_append_mem(ds, buff, strlen(delimiter) + 1);
} }
if (!(flags & QUERY_REAP)) if (!(flags & QUERY_REAP))
DBUG_RETURN(0); DBUG_RETURN(0);
if ((*mysql->methods->read_query_result)(mysql) || if ((!counter && (*mysql->methods->read_query_result)(mysql)) ||
(!(last_result = res = mysql_store_result(mysql)) && (!(last_result= res= mysql_store_result(mysql)) &&
mysql_field_count(mysql))) mysql_field_count(mysql)))
{ {
if (q->require_file) if (q->require_file)
...@@ -2195,7 +2217,7 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags) ...@@ -2195,7 +2217,7 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
dynstr_append_mem(ds,"ERROR ",6); dynstr_append_mem(ds,"ERROR ",6);
replace_dynstr_append_mem(ds, mysql_sqlstate(mysql), replace_dynstr_append_mem(ds, mysql_sqlstate(mysql),
strlen(mysql_sqlstate(mysql))); strlen(mysql_sqlstate(mysql)));
dynstr_append_mem(ds,": ",2); dynstr_append_mem(ds, ": ", 2);
replace_dynstr_append_mem(ds,mysql_error(mysql), replace_dynstr_append_mem(ds,mysql_error(mysql),
strlen(mysql_error(mysql))); strlen(mysql_error(mysql)));
dynstr_append_mem(ds,"\n",1); dynstr_append_mem(ds,"\n",1);
...@@ -2207,7 +2229,7 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags) ...@@ -2207,7 +2229,7 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
} }
} }
DBUG_PRINT("info",("i: %d expected_errors: %d", i, q->expected_errors)); DBUG_PRINT("info",("i: %d expected_errors: %d", i, q->expected_errors));
dynstr_append_mem(ds,"ERROR ",6); dynstr_append_mem(ds, "ERROR ",6);
replace_dynstr_append_mem(ds, mysql_sqlstate(mysql), replace_dynstr_append_mem(ds, mysql_sqlstate(mysql),
strlen(mysql_sqlstate(mysql))); strlen(mysql_sqlstate(mysql)));
dynstr_append_mem(ds,": ",2); dynstr_append_mem(ds,": ",2);
...@@ -2251,6 +2273,7 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags) ...@@ -2251,6 +2273,7 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
{ {
int num_fields= mysql_num_fields(res); int num_fields= mysql_num_fields(res);
MYSQL_FIELD *fields= mysql_fetch_fields(res); MYSQL_FIELD *fields= mysql_fetch_fields(res);
for (i = 0; i < num_fields; i++) for (i = 0; i < num_fields; i++)
{ {
if (i) if (i)
...@@ -2268,7 +2291,7 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags) ...@@ -2268,7 +2291,7 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
uint count= mysql_warning_count(mysql); uint count= mysql_warning_count(mysql);
if (!mysql_real_query(mysql, "SHOW WARNINGS", 13)) if (!mysql_real_query(mysql, "SHOW WARNINGS", 13))
{ {
warn_res=mysql_store_result(mysql); warn_res= mysql_store_result(mysql);
} }
if (!warn_res) if (!warn_res)
verbose_msg("Warning count is %u but didn't get any warnings\n", verbose_msg("Warning count is %u but didn't get any warnings\n",
...@@ -2302,10 +2325,15 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags) ...@@ -2302,10 +2325,15 @@ int run_query(MYSQL* mysql, struct st_query* q, int flags)
{ {
error = check_result(ds, q->record_file, q->require_file); error = check_result(ds, q->record_file, q->require_file);
} }
end:
if (res) if (res)
mysql_free_result(res); mysql_free_result(res);
last_result= 0;
counter++;
} while (!(err= mysql_next_result(mysql)));
if (err >= 1)
mysql_error(mysql);
end:
last_result=0; last_result=0;
if (ds == &ds_tmp) if (ds == &ds_tmp)
dynstr_free(&ds_tmp); dynstr_free(&ds_tmp);
...@@ -2425,7 +2453,7 @@ int main(int argc, char **argv) ...@@ -2425,7 +2453,7 @@ int main(int argc, char **argv)
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(argv[0]);
{
DBUG_ENTER("main"); DBUG_ENTER("main");
DBUG_PROCESS(argv[0]); DBUG_PROCESS(argv[0]);
...@@ -2520,6 +2548,10 @@ int main(int argc, char **argv) ...@@ -2520,6 +2548,10 @@ int main(int argc, char **argv)
case Q_DEC: do_dec(q); break; case Q_DEC: do_dec(q); break;
case Q_ECHO: do_echo(q); break; case Q_ECHO: do_echo(q); break;
case Q_SYSTEM: do_system(q); break; case Q_SYSTEM: do_system(q); break;
case Q_DELIMITER:
strmake(delimiter, q->first_argument, sizeof(delimiter) - 1);
delimiter_length= strlen(delimiter);
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; break;
case Q_EVAL: case Q_EVAL:
...@@ -2646,9 +2678,9 @@ int main(int argc, char **argv) ...@@ -2646,9 +2678,9 @@ int main(int argc, char **argv)
free_used_memory(); free_used_memory();
exit(error ? 1 : 0); exit(error ? 1 : 0);
return error ? 1 : 0; /* Keep compiler happy */ return error ? 1 : 0; /* Keep compiler happy */
}
} }
/* /*
Read arguments for embedded server and put them into Read arguments for embedded server and put them into
embedded_server_args_count and embedded_server_args[] embedded_server_args_count and embedded_server_args[]
......
select 1;
1
1
select 2;
select 3;
select 4||||
2
2
3
3
4
4
select 5;
select 6;
select 50, 'abc';'abcd'
5
5
6
6
50 abc
50 abc
select "abcd'";'abcd'
abcd'
abcd'
select "'abcd";'abcd'
'abcd
'abcd
select 5'abcd'
5
5
select 'finish';
finish
finish
select 1;
delimiter ||||;
select 2;
select 3;
select 4||||
delimiter 'abcd'||||
select 5;
select 6;
select 50, 'abc';'abcd'
select "abcd'";'abcd'select "'abcd";'abcd'
select 5'abcd'
delimiter ;'abcd'
select 'finish';
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