Loading .bzrignore +1 −0 Original line number Diff line number Diff line Loading @@ -183,3 +183,4 @@ mysqld.S mysqld.sym .snprj/* sql-bench/output/* sql-bench/Results-linux/ATIS-mysql_bdb-Linux_2.2.14_my_SMP_i686 Docs/manual.texi +16 −7 Original line number Diff line number Diff line Loading @@ -2571,7 +2571,7 @@ PMP Computer Solutions. Database developers using @strong{MySQL} and @item @uref{http://www.aewa.org/}@* Airborne Early Warning Association. @item @uref{http://21ccs.com/~gboersm/y2kmatrix/}@* @item @uref{http://www.dedserius.com/y2kmatrix/}@* Y2K tester. @end itemize Loading Loading @@ -4493,9 +4493,15 @@ China [linuxforum.net] @ @item @c EMAIL: Vincent_Fong@innovator.com.hk (Vincent Fong) @c @image{Flags/china} China [Hong Kong] @ China [ISL/Hong Kong] @ @uref{http://mysql.islnet.net, WWW} @item @c EMAIL: marquischan@hotmail.com (Marquis Chan) @c @image{Flags/china} China [TraLand.com/Hong Kong] @ @uref{http://www.traland.com/mysql/, WWW} @c @item @c Not ok 20000919; Non-existent (Matt) @c EMAIL: george@netfirm.net (Hongsheng Zhu) Loading Loading @@ -20271,7 +20277,7 @@ differ somewhat: | flush | OFF | | flush_time | 0 | | have_bdb | YES | | have_gemeni | NO | | have_gemini | NO | | have_innobase | YES | | have_raid | YES | | have_ssl | NO | Loading Loading @@ -20449,9 +20455,9 @@ very little resources. @item @code{have_bdb} @code{YES} if @code{mysqld} supports Berkeley DB tables. @code{DISABLED} if @code{--skip-bdb} is used. @item @code{have_gemeni} @code{YES} if @code{mysqld} supports Gemeni tables. @code{DISABLED} if @code{--skip-gemeni} is used. @item @code{have_gemini} @code{YES} if @code{mysqld} supports Gemini tables. @code{DISABLED} if @code{--skip-gemini} is used. @item @code{have_innobase} @code{YES} if @code{mysqld} supports Innobase tables. @code{DISABLED} if @code{--skip-innobase} is used. Loading Loading @@ -40050,9 +40056,12 @@ though, so Version 3.23 is not released as a stable version yet. @appendixsubsec Changes in release 3.23.30 @itemize @bullet @item Allow hex constants in the @code{--fields-*-by} and @code{--lines-terminated-by} options to @code{mysqldump}. By Paul DuBois. @item Added option @code{--safe-show-databases}. @item Added @code{have_bdb}, @code{have_gemeni}, @code{have_innobase}, Added @code{have_bdb}, @code{have_gemini}, @code{have_innobase}, @code{have_raid} and @code{have_ssl} to @code{SHOW VARIABLES} to make it easy to test for supported extensions. @item client/mysqlimport.c +8 −3 Original line number Diff line number Diff line Loading @@ -455,11 +455,16 @@ static void db_error(MYSQL *mysql) static char *add_load_option(char *ptr,const char *object,const char *statement) { if (object) { if (!strncasecmp(object,"0x",2)) /* hex constant; don't escape */ ptr= strxmov(ptr," ",statement," ",object,NullS); else /* char constant; escape */ { ptr= strxmov(ptr," ",statement," '",NullS); ptr= field_escape(ptr,object,(uint) strlen(object)); *ptr++= '\''; } } return ptr; } Loading client/mysqltest.c +517 −469 Original line number Diff line number Diff line Loading @@ -20,10 +20,10 @@ * Written by: * Sasha Pachev <sasha@mysql.com> * Matt Wagner <matt@mysql.com> * * Monty **/ #define MTEST_VERSION "1.0" #define MTEST_VERSION "1.2" #include "global.h" #include "my_sys.h" Loading @@ -41,7 +41,7 @@ #include <unistd.h> #include <errno.h> #define MAX_QUERY 16384 #define MAX_QUERY 65536 #define PAD_SIZE 128 #define MAX_CONS 1024 #define MAX_INCLUDE_DEPTH 16 Loading @@ -51,15 +51,17 @@ #define BLOCK_STACK_DEPTH 32 int record = 0, verbose = 0, silent = 0; const char* record_mode = "r"; static char *db = 0, *pass=0; const char* user = 0, *host = 0, *unix_sock = 0; int port = 0; static uint start_lineno, *lineno; static const char *load_default_groups[]= { "mysqltest","client",0 }; FILE* file_stack[MAX_INCLUDE_DEPTH]; FILE** cur_file; FILE** file_stack_end; uint lineno_stack[MAX_INCLUDE_DEPTH]; int block_stack[BLOCK_STACK_DEPTH]; int *cur_block, *block_stack_end; Loading Loading @@ -104,17 +106,27 @@ struct connection* cur_con, *next_con, *cons_end; struct query { char q[MAX_QUERY]; int has_result_set; int first_word_len; int abort_on_error; my_bool abort_on_error, require_file; uint expected_errno; char record_file[FN_REFLEN]; enum {Q_CONNECTION, Q_QUERY, Q_CONNECT, /* Add new commands before Q_UNKNOWN */ enum { Q_CONNECTION=1, Q_QUERY, Q_CONNECT, Q_SLEEP, Q_INC, Q_DEC,Q_SOURCE, Q_DISCONNECT,Q_LET, Q_ECHO, Q_WHILE, Q_END_BLOCK, Q_SYSTEM, Q_UNKNOWN} type; Q_SYSTEM, Q_RESULT, Q_REQUIRE, Q_UNKNOWN, Q_COMMENT, Q_COMMENT_WITH_COMMAND} type; }; const char *command_names[] = { "connection", "query","connect","sleep","inc","dec","source","disconnect", "let","echo","while","end","system","result", "require",0 }; TYPELIB command_typelib= {array_elements(command_names),"", command_names}; #define DS_CHUNK 16384 typedef struct dyn_string Loading @@ -131,11 +143,53 @@ void dyn_string_append(DYN_STRING* ds, const char* str, int len); int dyn_string_cmp(DYN_STRING* ds, const char* fname); void reject_dump(const char* record_file, char* buf, int size); static void die(const char* fmt, ...); int close_connection(struct query* q); VAR* var_get(char* var_name, char* var_name_end, int raw); void verbose_msg(const char* fmt, ...); static void close_cons() { for(--next_con; next_con >= cons; --next_con) { mysql_close(&next_con->mysql); my_free(next_con->name, MYF(MY_ALLOW_ZERO_PTR)); } } static void die(const char* fmt, ...) { va_list args; va_start(args, fmt); fprintf(stderr, "%s: ", my_progname); vfprintf(stderr, fmt, args); fprintf(stderr, "\n"); va_end(args); close_cons(); exit(1); } static void abort_not_supported_test() { fprintf(stderr, "This test is not supported by this installation\n"); if (!silent) printf("skipped\n"); close_cons(); exit(2); } static void verbose_msg(const char* fmt, ...) { va_list args; if (!verbose) return; va_start(args, fmt); fprintf(stderr, "%s: At line %u: ", my_progname, start_lineno); vfprintf(stderr, fmt, args); fprintf(stderr, "\n"); va_end(args); } void init_parser() { Loading Loading @@ -192,6 +246,8 @@ void dyn_string_append(DYN_STRING* ds, const char* str, int len) ds->len += len; } } int dyn_string_cmp(DYN_STRING* ds, const char* fname) { MY_STAT stat_info; Loading @@ -214,10 +270,15 @@ int dyn_string_cmp(DYN_STRING* ds, const char* fname) return res; } int check_result(DYN_STRING* ds, const char* fname) static int check_result(DYN_STRING* ds, const char* fname, my_bool require_option) { int error = 0; switch(dyn_string_cmp(ds, fname)) int res=dyn_string_cmp(ds, fname); if (res && require_option) abort_not_supported_test(); switch (res) { case 0: break; /* ok */ Loading Loading @@ -304,8 +365,9 @@ int open_file(const char* name) { if (*cur_file && ++cur_file == file_stack_end) die("Source directives are nesting too deep"); if(!(*cur_file = fopen(name, "r"))) if (!(*cur_file = my_fopen(name, O_RDONLY, MYF(MY_WME)))) die("Could not read '%s': errno %d\n", name, errno); *++lineno=1; return 0; } Loading Loading @@ -438,7 +500,7 @@ int do_sleep(struct query* q) p = (char*)q->q + q->first_word_len; while(*p && isspace(*p)) p++; if (!*p) die("Missing agument in sleep\n"); die("Missing argument in sleep\n"); arg = p; t.tv_sec = atoi(arg); t.tv_usec = 0; Loading Loading @@ -468,6 +530,17 @@ int do_sleep(struct query* q) return select(0,0,0,0, &t); } static void get_file_name(char *filename, struct query* q) { char *p = (char*) q->q + q->first_word_len; while(*p && isspace(*p)) p++; strnmov(filename, p, FN_REFLEN); /* Remove end space */ while (p > filename && isspace(p[-1])) p--; p[0]=0; } int select_connection(struct query* q) { Loading Loading @@ -619,14 +692,6 @@ int do_while(struct query* q) return 0; } void close_cons() { for(--next_con; next_con >= cons; --next_con) { mysql_close(&next_con->mysql); my_free(next_con->name, MYF(MY_ALLOW_ZERO_PTR)); } } int safe_copy_unescape(char* dest, char* src, int size) { Loading Loading @@ -683,35 +748,35 @@ int safe_copy_unescape(char* dest, char* src, int size) int read_line(char* buf, int size) { int c; char* p = buf, *buf_end = buf + size; char* p = buf, *buf_end = buf + size-1; int no_save = 0; enum {R_NORMAL, R_Q1, R_ESC_Q_Q1, R_ESC_Q_Q2, R_ESC_SLASH_Q1, R_ESC_SLASH_Q2, R_Q2, R_COMMENT, R_LINE_START} state = R_LINE_START; start_lineno= *lineno; for (; p < buf_end ;) { no_save = 0; c = fgetc(*cur_file); if (feof(*cur_file)) { fclose(*cur_file); my_fclose(*cur_file,MYF(0)); if (cur_file == file_stack) return 1; else { cur_file--; lineno--; continue; } } switch(state) { switch(state) { case R_NORMAL: if(c == ';' || c == '{') /* '{' allows some interesting syntax * but we don't care, as long as the * correct sytnax gets parsed right */ /* Only accept '{' in the beginning of a line */ if (c == ';') { *p = 0; return 0; Loading @@ -721,23 +786,30 @@ int read_line(char* buf, int size) else if (c == '"') state = R_Q2; else if (c == '\n') { state = R_LINE_START; (*lineno)++; } break; case R_COMMENT: no_save = 1; if (c == '\n') state = R_LINE_START; { *p=0; (*lineno)++; return 0; } break; case R_LINE_START: if(c == '#') if (c == '#' || c == '-') { state = R_COMMENT; no_save = 1; } else if (isspace(c)) { if (c == '\n') start_lineno= ++*lineno; /* Query hasn't started yet */ no_save = 1; } else if (c == '}') { *buf++ = '}'; Loading Loading @@ -767,6 +839,8 @@ int read_line(char* buf, int size) } if (c != '\'') state = R_NORMAL; else state = R_Q1; break; case R_ESC_SLASH_Q1: state = R_Q1; Loading @@ -786,6 +860,8 @@ int read_line(char* buf, int size) } if (c != '"') state = R_NORMAL; else state = R_Q2; break; case R_ESC_SLASH_Q2: state = R_Q2; Loading @@ -795,15 +871,18 @@ int read_line(char* buf, int size) if (!no_save) *p++ = c; } *p=0; /* Always end with \0 */ return feof(*cur_file); } static char read_query_buf[MAX_QUERY]; int read_query(struct query** q_ptr) { char buf[MAX_QUERY]; char* p = buf,* p1 ; char* p = read_query_buf, * p1 ; int c, expected_errno; struct query* q; if (parser.current_line < parser.read_lines) { get_dynamic(&q_lines, (gptr)q_ptr, parser.current_line) ; Loading @@ -815,13 +894,25 @@ int read_query(struct query** q_ptr) die("Out of memory"); q->record_file[0] = 0; q->require_file=0; q->abort_on_error = 1; q->has_result_set = 0; q->first_word_len = 0; q->expected_errno = 0; q->type = Q_UNKNOWN; if(read_line(buf, sizeof(buf))) if (read_line(read_query_buf, sizeof(read_query_buf))) return 1; if (*p == '#') { q->type = Q_COMMENT; } else if (p[0] == '-' && p[1] == '-') { q->type = Q_COMMENT_WITH_COMMAND; p+=2; /* To calculate first word */ } else { if (*p == '!') { q->abort_on_error = 0; Loading @@ -839,23 +930,22 @@ int read_query(struct query** q_ptr) while(*p && isspace(*p)) p++ ; if (*p == '@') { q->has_result_set = 1; p++; p1 = q->record_file; while(!isspace(c = *p) && p1 < q->record_file + sizeof(q->record_file) - 1) *p1++ = *p++; *p1 = 0; } } while(*p && isspace(*p)) p++; /* Calculate first word */ p1 = q->q; while(*p && !isspace(*p)) *p1++ = *p++; q->first_word_len = p1 - q->q; strcpy(p1, p); strmov(p1, p); parser.read_lines++; return 0; } Loading @@ -878,31 +968,6 @@ struct option long_options[] = {0, 0,0,0} }; void die(const char* fmt, ...) { va_list args; va_start(args, fmt); fprintf(stderr, "%s: ", my_progname); vfprintf(stderr, fmt, args); fprintf(stderr, "\n"); va_end(args); close_cons(); exit(1); } void verbose_msg(const char* fmt, ...) { va_list args; if(!verbose) return; va_start(args, fmt); fprintf(stderr, "%s: ", my_progname); vfprintf(stderr, fmt, args); fprintf(stderr, "\n"); va_end(args); } static void print_version(void) { Loading @@ -913,7 +978,7 @@ static void print_version(void) void usage() { print_version(); printf("MySQL AB, by Sasha & Matt\n"); printf("MySQL AB, by Sasha, Matt & Monty\n"); printf("This software comes with ABSOLUTELY NO WARRANTY\n\n"); printf("Runs a test against the mysql server and compares output with a results file.\n\n"); printf("Usage: %s [OPTIONS] [database] < test_file\n", my_progname); Loading @@ -927,10 +992,11 @@ void usage() -P, --port=... Port number to use for connection.\n\ -S, --socket=... Socket file to use for connection.\n\ -r, --record Record output of test_file into result file.\n\ -R, --result-file=... Store result in this file\n\ -R, --result-file=... Read/Store result from/in this file.\n\ -v, --verbose Write more.\n\ -q, --quiet, --silent Suppress all normal output.\n\ -V, --version Output version information and exit.\n\n"); -V, --version Output version information and exit.\n\ --no-defaults Don't read default options from any options file.\n\n"); } int parse_args(int argc, char **argv) Loading @@ -939,6 +1005,7 @@ int parse_args(int argc, char **argv) my_bool tty_password=0; load_defaults("my",load_default_groups,&argc,&argv); while((c = getopt_long(argc, argv, "h:p::u:P:D:S:R:?rvVq", long_options, &option_index)) != EOF) { Loading @@ -949,7 +1016,6 @@ int parse_args(int argc, char **argv) break; case 'r': record = 1; record_mode = "w"; break; case 'u': user = optarg; Loading Loading @@ -990,7 +1056,7 @@ int parse_args(int argc, char **argv) exit(0); default: usage(); exit(0); exit(1); } } Loading @@ -1002,10 +1068,7 @@ int parse_args(int argc, char **argv) exit(1); } if (argc == 1) { my_free(db,MYF(MY_ALLOW_ZERO_PTR)); db=my_strdup(*argv,MYF(MY_WME)); } db= *argv; if (tty_password) pass=get_tty_password(NullS); Loading @@ -1024,7 +1087,8 @@ char* safe_str_append(char* buf, const char* str, int size) void str_to_file(const char* fname, char* str, int size) { int fd; if((fd = my_open(fname, O_WRONLY|O_CREAT, MYF(MY_WME | MY_FFNF))) < 0) if ((fd = my_open(fname, O_WRONLY | O_CREAT | O_TRUNC, MYF(MY_WME | MY_FFNF))) < 0) die("Could not open %s: errno = %d", fname, errno); if (my_write(fd, (byte*)str, size, MYF(MY_WME|MY_FNABP))) die("write failed"); Loading @@ -1034,14 +1098,13 @@ void str_to_file(const char* fname, char* str, int size) void reject_dump(const char* record_file, char* buf, int size) { char reject_file[FN_REFLEN]; char* p; if (strlen(record_file) >= FN_REFLEN-8) die("too long path name for reject"); strmov(strmov(reject_file, record_file),".reject"); str_to_file(reject_file, buf, size); } int run_query(MYSQL* mysql, struct query* q) { MYSQL_RES* res = 0; Loading @@ -1060,12 +1123,13 @@ int run_query(MYSQL* mysql, struct query* q) ds = &ds_tmp; } if (mysql_query(mysql, q->q)) { if (q->require_file) abort_not_supported_test(); if (q->abort_on_error) die("query '%s' failed: %s", q->q, mysql_error(mysql)); die("At line %u: query '%s' failed: %d: %s", start_lineno, q->q, mysql_errno(mysql), mysql_error(mysql)); else { if (q->expected_errno) Loading @@ -1077,7 +1141,8 @@ int run_query(MYSQL* mysql, struct query* q) goto end; } verbose_msg("query '%s' failed: %s", q->q, mysql_error(mysql)); verbose_msg("query '%s' failed: %d: %s", q->q, mysql_errno(mysql), mysql_error(mysql)); /* if we do not abort on error, failure to run the query does not fail the whole test case */ Loading @@ -1096,11 +1161,15 @@ int run_query(MYSQL* mysql, struct query* q) if (!(res = mysql_store_result(mysql)) && mysql_field_count(mysql)) { if (q->require_file) abort_not_supported_test(); if (q->abort_on_error) die("failed in mysql_store_result for query '%s'", q->q); die("At line %u: Failed in mysql_store_result for query '%s' (%d)", start_lineno, q->q, mysql_errno(mysql)); else { verbose_msg("failed in mysql_store_result for query '%s'", q->q); verbose_msg("failed in mysql_store_result for query '%s' (%d)", q->q, mysql_errno(mysql)); error = 1; goto end; } Loading @@ -1112,8 +1181,9 @@ int run_query(MYSQL* mysql, struct query* q) num_fields = mysql_num_fields(res); for( i = 0; i < num_fields; i++) { dyn_string_append(ds, fields[i].name, 0); if (i) dyn_string_append(ds, "\t", 1); dyn_string_append(ds, fields[i].name, 0); } dyn_string_append(ds, "\n", 1); Loading @@ -1133,8 +1203,9 @@ int run_query(MYSQL* mysql, struct query* q) len = 4; } dyn_string_append(ds, val, len); if (i) dyn_string_append(ds, "\t", 1); dyn_string_append(ds, val, len); } dyn_string_append(ds, "\n", 1); Loading @@ -1143,13 +1214,13 @@ int run_query(MYSQL* mysql, struct query* q) if (record) { if (!q->record_file[0] && !result_file) die("Missing result file"); die("At line %u: Missing result file", start_lineno); if (!result_file) str_to_file(q->record_file, ds->str, ds->len); } else if (q->record_file[0]) { error = check_result(ds, q->record_file); error = check_result(ds, q->record_file, q->require_file); } end: Loading @@ -1157,77 +1228,36 @@ int run_query(MYSQL* mysql, struct query* q) return error; } int check_first_word(struct query* q, const char* word, int len) { const char* p, *p1, *end; if(len != q->first_word_len) return 0; p = word; end = p + len; p1 = q->q; for(; p < end; p++, p1++) if(tolower(*p) != tolower(*p1)) return 0; return 1; } void get_query_type(struct query* q) { char save; uint type; if (*q->q == '}') { q->type = Q_END_BLOCK; return; } if (q->type != Q_COMMENT_WITH_COMMAND) q->type = Q_QUERY; switch(q->first_word_len) { case 3: if(check_first_word(q, "inc", 3)) q->type = Q_INC; else if(check_first_word(q, "dec", 3)) q->type = Q_DEC; else if(check_first_word(q, "let", 3)) q->type = Q_LET; break; case 4: if(check_first_word(q, "echo", 4)) q->type = Q_ECHO; break; case 5: if(check_first_word(q, "sleep", 5)) q->type = Q_SLEEP; else if(check_first_word(q, "while", 5)) q->type = Q_WHILE; break; case 6: if(check_first_word(q, "source", 6)) q->type = Q_SOURCE; else if(check_first_word(q, "system", 6)) q->type = Q_SYSTEM; break; case 7: if(check_first_word(q, "connect", 7)) q->type = Q_CONNECT; break; case 10: if(check_first_word(q, "connection", 10)) q->type = Q_CONNECTION; else if(check_first_word(q, "disconnect", 10)) q->type = Q_DISCONNECT; break; save=q->q[q->first_word_len]; q->q[q->first_word_len]=0; type=find_type(q->q, &command_typelib, 0); q->q[q->first_word_len]=save; if (type > 0) q->type=type; /* Found command */ } } int main(int argc, char** argv) { int error = 0; struct query* q; my_bool require_file=0; char save_file[FN_REFLEN]; save_file[0]=0; MY_INIT(argv[0]); memset(cons, 0, sizeof(cons)); Loading @@ -1238,6 +1268,7 @@ int main(int argc, char** argv) memset(file_stack, 0, sizeof(file_stack)); file_stack_end = file_stack + MAX_INCLUDE_DEPTH; cur_file = file_stack; lineno = lineno_stack; init_dynamic_array(&q_lines, sizeof(struct query*), INIT_Q_LINES, INIT_Q_LINES); memset(block_stack, 0, sizeof(block_stack)); Loading @@ -1247,8 +1278,7 @@ int main(int argc, char** argv) parse_args(argc, argv); if (!*cur_file) *cur_file = stdin; *lineno=1; if (!( mysql_init(&cur_con->mysql))) die("Failed in mysql_init()"); Loading @@ -1267,13 +1297,12 @@ int main(int argc, char** argv) for(;!read_query(&q);) { int current_line_inc = 1, processed = 0; if(q->type == Q_UNKNOWN) if (q->type == Q_UNKNOWN || q->type == Q_COMMENT_WITH_COMMAND) get_query_type(q); if (block_ok) { processed = 1; switch(q->type) { switch (q->type) { case Q_CONNECT: do_connect(q); break; case Q_CONNECTION: select_connection(q); break; case Q_DISCONNECT: close_connection(q); break; Loading @@ -1284,7 +1313,26 @@ int main(int argc, char** argv) case Q_ECHO: do_echo(q); break; case Q_SYSTEM: do_system(q); break; case Q_LET: do_let(q); break; case Q_QUERY: error |= run_query(&cur_con->mysql, q); break; case Q_QUERY: { if (save_file[0]) { strmov(q->record_file,save_file); q->require_file=require_file; save_file[0]=0; } error |= run_query(&cur_con->mysql, q); break; } case Q_RESULT: get_file_name(save_file,q); require_file=0; break; case Q_REQUIRE: get_file_name(save_file,q); require_file=1; break; case Q_COMMENT: /* Ignore row */ case Q_COMMENT_WITH_COMMAND: default: processed = 0; break; } } Loading @@ -1308,7 +1356,7 @@ int main(int argc, char** argv) if (result_file && ds_res.len) { if(!record) error |= check_result(&ds_res, result_file); error |= check_result(&ds_res, result_file, q->require_file); else str_to_file(result_file, ds_res.str, ds_res.len); } Loading configure.in +1 −1 Original line number Diff line number Diff line Loading @@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! AM_INIT_AUTOMAKE(mysql, 3.23.29a-gamma) AM_INIT_AUTOMAKE(mysql, 3.23.30-gamma) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 Loading Loading
.bzrignore +1 −0 Original line number Diff line number Diff line Loading @@ -183,3 +183,4 @@ mysqld.S mysqld.sym .snprj/* sql-bench/output/* sql-bench/Results-linux/ATIS-mysql_bdb-Linux_2.2.14_my_SMP_i686
Docs/manual.texi +16 −7 Original line number Diff line number Diff line Loading @@ -2571,7 +2571,7 @@ PMP Computer Solutions. Database developers using @strong{MySQL} and @item @uref{http://www.aewa.org/}@* Airborne Early Warning Association. @item @uref{http://21ccs.com/~gboersm/y2kmatrix/}@* @item @uref{http://www.dedserius.com/y2kmatrix/}@* Y2K tester. @end itemize Loading Loading @@ -4493,9 +4493,15 @@ China [linuxforum.net] @ @item @c EMAIL: Vincent_Fong@innovator.com.hk (Vincent Fong) @c @image{Flags/china} China [Hong Kong] @ China [ISL/Hong Kong] @ @uref{http://mysql.islnet.net, WWW} @item @c EMAIL: marquischan@hotmail.com (Marquis Chan) @c @image{Flags/china} China [TraLand.com/Hong Kong] @ @uref{http://www.traland.com/mysql/, WWW} @c @item @c Not ok 20000919; Non-existent (Matt) @c EMAIL: george@netfirm.net (Hongsheng Zhu) Loading Loading @@ -20271,7 +20277,7 @@ differ somewhat: | flush | OFF | | flush_time | 0 | | have_bdb | YES | | have_gemeni | NO | | have_gemini | NO | | have_innobase | YES | | have_raid | YES | | have_ssl | NO | Loading Loading @@ -20449,9 +20455,9 @@ very little resources. @item @code{have_bdb} @code{YES} if @code{mysqld} supports Berkeley DB tables. @code{DISABLED} if @code{--skip-bdb} is used. @item @code{have_gemeni} @code{YES} if @code{mysqld} supports Gemeni tables. @code{DISABLED} if @code{--skip-gemeni} is used. @item @code{have_gemini} @code{YES} if @code{mysqld} supports Gemini tables. @code{DISABLED} if @code{--skip-gemini} is used. @item @code{have_innobase} @code{YES} if @code{mysqld} supports Innobase tables. @code{DISABLED} if @code{--skip-innobase} is used. Loading Loading @@ -40050,9 +40056,12 @@ though, so Version 3.23 is not released as a stable version yet. @appendixsubsec Changes in release 3.23.30 @itemize @bullet @item Allow hex constants in the @code{--fields-*-by} and @code{--lines-terminated-by} options to @code{mysqldump}. By Paul DuBois. @item Added option @code{--safe-show-databases}. @item Added @code{have_bdb}, @code{have_gemeni}, @code{have_innobase}, Added @code{have_bdb}, @code{have_gemini}, @code{have_innobase}, @code{have_raid} and @code{have_ssl} to @code{SHOW VARIABLES} to make it easy to test for supported extensions. @item
client/mysqlimport.c +8 −3 Original line number Diff line number Diff line Loading @@ -455,11 +455,16 @@ static void db_error(MYSQL *mysql) static char *add_load_option(char *ptr,const char *object,const char *statement) { if (object) { if (!strncasecmp(object,"0x",2)) /* hex constant; don't escape */ ptr= strxmov(ptr," ",statement," ",object,NullS); else /* char constant; escape */ { ptr= strxmov(ptr," ",statement," '",NullS); ptr= field_escape(ptr,object,(uint) strlen(object)); *ptr++= '\''; } } return ptr; } Loading
client/mysqltest.c +517 −469 Original line number Diff line number Diff line Loading @@ -20,10 +20,10 @@ * Written by: * Sasha Pachev <sasha@mysql.com> * Matt Wagner <matt@mysql.com> * * Monty **/ #define MTEST_VERSION "1.0" #define MTEST_VERSION "1.2" #include "global.h" #include "my_sys.h" Loading @@ -41,7 +41,7 @@ #include <unistd.h> #include <errno.h> #define MAX_QUERY 16384 #define MAX_QUERY 65536 #define PAD_SIZE 128 #define MAX_CONS 1024 #define MAX_INCLUDE_DEPTH 16 Loading @@ -51,15 +51,17 @@ #define BLOCK_STACK_DEPTH 32 int record = 0, verbose = 0, silent = 0; const char* record_mode = "r"; static char *db = 0, *pass=0; const char* user = 0, *host = 0, *unix_sock = 0; int port = 0; static uint start_lineno, *lineno; static const char *load_default_groups[]= { "mysqltest","client",0 }; FILE* file_stack[MAX_INCLUDE_DEPTH]; FILE** cur_file; FILE** file_stack_end; uint lineno_stack[MAX_INCLUDE_DEPTH]; int block_stack[BLOCK_STACK_DEPTH]; int *cur_block, *block_stack_end; Loading Loading @@ -104,17 +106,27 @@ struct connection* cur_con, *next_con, *cons_end; struct query { char q[MAX_QUERY]; int has_result_set; int first_word_len; int abort_on_error; my_bool abort_on_error, require_file; uint expected_errno; char record_file[FN_REFLEN]; enum {Q_CONNECTION, Q_QUERY, Q_CONNECT, /* Add new commands before Q_UNKNOWN */ enum { Q_CONNECTION=1, Q_QUERY, Q_CONNECT, Q_SLEEP, Q_INC, Q_DEC,Q_SOURCE, Q_DISCONNECT,Q_LET, Q_ECHO, Q_WHILE, Q_END_BLOCK, Q_SYSTEM, Q_UNKNOWN} type; Q_SYSTEM, Q_RESULT, Q_REQUIRE, Q_UNKNOWN, Q_COMMENT, Q_COMMENT_WITH_COMMAND} type; }; const char *command_names[] = { "connection", "query","connect","sleep","inc","dec","source","disconnect", "let","echo","while","end","system","result", "require",0 }; TYPELIB command_typelib= {array_elements(command_names),"", command_names}; #define DS_CHUNK 16384 typedef struct dyn_string Loading @@ -131,11 +143,53 @@ void dyn_string_append(DYN_STRING* ds, const char* str, int len); int dyn_string_cmp(DYN_STRING* ds, const char* fname); void reject_dump(const char* record_file, char* buf, int size); static void die(const char* fmt, ...); int close_connection(struct query* q); VAR* var_get(char* var_name, char* var_name_end, int raw); void verbose_msg(const char* fmt, ...); static void close_cons() { for(--next_con; next_con >= cons; --next_con) { mysql_close(&next_con->mysql); my_free(next_con->name, MYF(MY_ALLOW_ZERO_PTR)); } } static void die(const char* fmt, ...) { va_list args; va_start(args, fmt); fprintf(stderr, "%s: ", my_progname); vfprintf(stderr, fmt, args); fprintf(stderr, "\n"); va_end(args); close_cons(); exit(1); } static void abort_not_supported_test() { fprintf(stderr, "This test is not supported by this installation\n"); if (!silent) printf("skipped\n"); close_cons(); exit(2); } static void verbose_msg(const char* fmt, ...) { va_list args; if (!verbose) return; va_start(args, fmt); fprintf(stderr, "%s: At line %u: ", my_progname, start_lineno); vfprintf(stderr, fmt, args); fprintf(stderr, "\n"); va_end(args); } void init_parser() { Loading Loading @@ -192,6 +246,8 @@ void dyn_string_append(DYN_STRING* ds, const char* str, int len) ds->len += len; } } int dyn_string_cmp(DYN_STRING* ds, const char* fname) { MY_STAT stat_info; Loading @@ -214,10 +270,15 @@ int dyn_string_cmp(DYN_STRING* ds, const char* fname) return res; } int check_result(DYN_STRING* ds, const char* fname) static int check_result(DYN_STRING* ds, const char* fname, my_bool require_option) { int error = 0; switch(dyn_string_cmp(ds, fname)) int res=dyn_string_cmp(ds, fname); if (res && require_option) abort_not_supported_test(); switch (res) { case 0: break; /* ok */ Loading Loading @@ -304,8 +365,9 @@ int open_file(const char* name) { if (*cur_file && ++cur_file == file_stack_end) die("Source directives are nesting too deep"); if(!(*cur_file = fopen(name, "r"))) if (!(*cur_file = my_fopen(name, O_RDONLY, MYF(MY_WME)))) die("Could not read '%s': errno %d\n", name, errno); *++lineno=1; return 0; } Loading Loading @@ -438,7 +500,7 @@ int do_sleep(struct query* q) p = (char*)q->q + q->first_word_len; while(*p && isspace(*p)) p++; if (!*p) die("Missing agument in sleep\n"); die("Missing argument in sleep\n"); arg = p; t.tv_sec = atoi(arg); t.tv_usec = 0; Loading Loading @@ -468,6 +530,17 @@ int do_sleep(struct query* q) return select(0,0,0,0, &t); } static void get_file_name(char *filename, struct query* q) { char *p = (char*) q->q + q->first_word_len; while(*p && isspace(*p)) p++; strnmov(filename, p, FN_REFLEN); /* Remove end space */ while (p > filename && isspace(p[-1])) p--; p[0]=0; } int select_connection(struct query* q) { Loading Loading @@ -619,14 +692,6 @@ int do_while(struct query* q) return 0; } void close_cons() { for(--next_con; next_con >= cons; --next_con) { mysql_close(&next_con->mysql); my_free(next_con->name, MYF(MY_ALLOW_ZERO_PTR)); } } int safe_copy_unescape(char* dest, char* src, int size) { Loading Loading @@ -683,35 +748,35 @@ int safe_copy_unescape(char* dest, char* src, int size) int read_line(char* buf, int size) { int c; char* p = buf, *buf_end = buf + size; char* p = buf, *buf_end = buf + size-1; int no_save = 0; enum {R_NORMAL, R_Q1, R_ESC_Q_Q1, R_ESC_Q_Q2, R_ESC_SLASH_Q1, R_ESC_SLASH_Q2, R_Q2, R_COMMENT, R_LINE_START} state = R_LINE_START; start_lineno= *lineno; for (; p < buf_end ;) { no_save = 0; c = fgetc(*cur_file); if (feof(*cur_file)) { fclose(*cur_file); my_fclose(*cur_file,MYF(0)); if (cur_file == file_stack) return 1; else { cur_file--; lineno--; continue; } } switch(state) { switch(state) { case R_NORMAL: if(c == ';' || c == '{') /* '{' allows some interesting syntax * but we don't care, as long as the * correct sytnax gets parsed right */ /* Only accept '{' in the beginning of a line */ if (c == ';') { *p = 0; return 0; Loading @@ -721,23 +786,30 @@ int read_line(char* buf, int size) else if (c == '"') state = R_Q2; else if (c == '\n') { state = R_LINE_START; (*lineno)++; } break; case R_COMMENT: no_save = 1; if (c == '\n') state = R_LINE_START; { *p=0; (*lineno)++; return 0; } break; case R_LINE_START: if(c == '#') if (c == '#' || c == '-') { state = R_COMMENT; no_save = 1; } else if (isspace(c)) { if (c == '\n') start_lineno= ++*lineno; /* Query hasn't started yet */ no_save = 1; } else if (c == '}') { *buf++ = '}'; Loading Loading @@ -767,6 +839,8 @@ int read_line(char* buf, int size) } if (c != '\'') state = R_NORMAL; else state = R_Q1; break; case R_ESC_SLASH_Q1: state = R_Q1; Loading @@ -786,6 +860,8 @@ int read_line(char* buf, int size) } if (c != '"') state = R_NORMAL; else state = R_Q2; break; case R_ESC_SLASH_Q2: state = R_Q2; Loading @@ -795,15 +871,18 @@ int read_line(char* buf, int size) if (!no_save) *p++ = c; } *p=0; /* Always end with \0 */ return feof(*cur_file); } static char read_query_buf[MAX_QUERY]; int read_query(struct query** q_ptr) { char buf[MAX_QUERY]; char* p = buf,* p1 ; char* p = read_query_buf, * p1 ; int c, expected_errno; struct query* q; if (parser.current_line < parser.read_lines) { get_dynamic(&q_lines, (gptr)q_ptr, parser.current_line) ; Loading @@ -815,13 +894,25 @@ int read_query(struct query** q_ptr) die("Out of memory"); q->record_file[0] = 0; q->require_file=0; q->abort_on_error = 1; q->has_result_set = 0; q->first_word_len = 0; q->expected_errno = 0; q->type = Q_UNKNOWN; if(read_line(buf, sizeof(buf))) if (read_line(read_query_buf, sizeof(read_query_buf))) return 1; if (*p == '#') { q->type = Q_COMMENT; } else if (p[0] == '-' && p[1] == '-') { q->type = Q_COMMENT_WITH_COMMAND; p+=2; /* To calculate first word */ } else { if (*p == '!') { q->abort_on_error = 0; Loading @@ -839,23 +930,22 @@ int read_query(struct query** q_ptr) while(*p && isspace(*p)) p++ ; if (*p == '@') { q->has_result_set = 1; p++; p1 = q->record_file; while(!isspace(c = *p) && p1 < q->record_file + sizeof(q->record_file) - 1) *p1++ = *p++; *p1 = 0; } } while(*p && isspace(*p)) p++; /* Calculate first word */ p1 = q->q; while(*p && !isspace(*p)) *p1++ = *p++; q->first_word_len = p1 - q->q; strcpy(p1, p); strmov(p1, p); parser.read_lines++; return 0; } Loading @@ -878,31 +968,6 @@ struct option long_options[] = {0, 0,0,0} }; void die(const char* fmt, ...) { va_list args; va_start(args, fmt); fprintf(stderr, "%s: ", my_progname); vfprintf(stderr, fmt, args); fprintf(stderr, "\n"); va_end(args); close_cons(); exit(1); } void verbose_msg(const char* fmt, ...) { va_list args; if(!verbose) return; va_start(args, fmt); fprintf(stderr, "%s: ", my_progname); vfprintf(stderr, fmt, args); fprintf(stderr, "\n"); va_end(args); } static void print_version(void) { Loading @@ -913,7 +978,7 @@ static void print_version(void) void usage() { print_version(); printf("MySQL AB, by Sasha & Matt\n"); printf("MySQL AB, by Sasha, Matt & Monty\n"); printf("This software comes with ABSOLUTELY NO WARRANTY\n\n"); printf("Runs a test against the mysql server and compares output with a results file.\n\n"); printf("Usage: %s [OPTIONS] [database] < test_file\n", my_progname); Loading @@ -927,10 +992,11 @@ void usage() -P, --port=... Port number to use for connection.\n\ -S, --socket=... Socket file to use for connection.\n\ -r, --record Record output of test_file into result file.\n\ -R, --result-file=... Store result in this file\n\ -R, --result-file=... Read/Store result from/in this file.\n\ -v, --verbose Write more.\n\ -q, --quiet, --silent Suppress all normal output.\n\ -V, --version Output version information and exit.\n\n"); -V, --version Output version information and exit.\n\ --no-defaults Don't read default options from any options file.\n\n"); } int parse_args(int argc, char **argv) Loading @@ -939,6 +1005,7 @@ int parse_args(int argc, char **argv) my_bool tty_password=0; load_defaults("my",load_default_groups,&argc,&argv); while((c = getopt_long(argc, argv, "h:p::u:P:D:S:R:?rvVq", long_options, &option_index)) != EOF) { Loading @@ -949,7 +1016,6 @@ int parse_args(int argc, char **argv) break; case 'r': record = 1; record_mode = "w"; break; case 'u': user = optarg; Loading Loading @@ -990,7 +1056,7 @@ int parse_args(int argc, char **argv) exit(0); default: usage(); exit(0); exit(1); } } Loading @@ -1002,10 +1068,7 @@ int parse_args(int argc, char **argv) exit(1); } if (argc == 1) { my_free(db,MYF(MY_ALLOW_ZERO_PTR)); db=my_strdup(*argv,MYF(MY_WME)); } db= *argv; if (tty_password) pass=get_tty_password(NullS); Loading @@ -1024,7 +1087,8 @@ char* safe_str_append(char* buf, const char* str, int size) void str_to_file(const char* fname, char* str, int size) { int fd; if((fd = my_open(fname, O_WRONLY|O_CREAT, MYF(MY_WME | MY_FFNF))) < 0) if ((fd = my_open(fname, O_WRONLY | O_CREAT | O_TRUNC, MYF(MY_WME | MY_FFNF))) < 0) die("Could not open %s: errno = %d", fname, errno); if (my_write(fd, (byte*)str, size, MYF(MY_WME|MY_FNABP))) die("write failed"); Loading @@ -1034,14 +1098,13 @@ void str_to_file(const char* fname, char* str, int size) void reject_dump(const char* record_file, char* buf, int size) { char reject_file[FN_REFLEN]; char* p; if (strlen(record_file) >= FN_REFLEN-8) die("too long path name for reject"); strmov(strmov(reject_file, record_file),".reject"); str_to_file(reject_file, buf, size); } int run_query(MYSQL* mysql, struct query* q) { MYSQL_RES* res = 0; Loading @@ -1060,12 +1123,13 @@ int run_query(MYSQL* mysql, struct query* q) ds = &ds_tmp; } if (mysql_query(mysql, q->q)) { if (q->require_file) abort_not_supported_test(); if (q->abort_on_error) die("query '%s' failed: %s", q->q, mysql_error(mysql)); die("At line %u: query '%s' failed: %d: %s", start_lineno, q->q, mysql_errno(mysql), mysql_error(mysql)); else { if (q->expected_errno) Loading @@ -1077,7 +1141,8 @@ int run_query(MYSQL* mysql, struct query* q) goto end; } verbose_msg("query '%s' failed: %s", q->q, mysql_error(mysql)); verbose_msg("query '%s' failed: %d: %s", q->q, mysql_errno(mysql), mysql_error(mysql)); /* if we do not abort on error, failure to run the query does not fail the whole test case */ Loading @@ -1096,11 +1161,15 @@ int run_query(MYSQL* mysql, struct query* q) if (!(res = mysql_store_result(mysql)) && mysql_field_count(mysql)) { if (q->require_file) abort_not_supported_test(); if (q->abort_on_error) die("failed in mysql_store_result for query '%s'", q->q); die("At line %u: Failed in mysql_store_result for query '%s' (%d)", start_lineno, q->q, mysql_errno(mysql)); else { verbose_msg("failed in mysql_store_result for query '%s'", q->q); verbose_msg("failed in mysql_store_result for query '%s' (%d)", q->q, mysql_errno(mysql)); error = 1; goto end; } Loading @@ -1112,8 +1181,9 @@ int run_query(MYSQL* mysql, struct query* q) num_fields = mysql_num_fields(res); for( i = 0; i < num_fields; i++) { dyn_string_append(ds, fields[i].name, 0); if (i) dyn_string_append(ds, "\t", 1); dyn_string_append(ds, fields[i].name, 0); } dyn_string_append(ds, "\n", 1); Loading @@ -1133,8 +1203,9 @@ int run_query(MYSQL* mysql, struct query* q) len = 4; } dyn_string_append(ds, val, len); if (i) dyn_string_append(ds, "\t", 1); dyn_string_append(ds, val, len); } dyn_string_append(ds, "\n", 1); Loading @@ -1143,13 +1214,13 @@ int run_query(MYSQL* mysql, struct query* q) if (record) { if (!q->record_file[0] && !result_file) die("Missing result file"); die("At line %u: Missing result file", start_lineno); if (!result_file) str_to_file(q->record_file, ds->str, ds->len); } else if (q->record_file[0]) { error = check_result(ds, q->record_file); error = check_result(ds, q->record_file, q->require_file); } end: Loading @@ -1157,77 +1228,36 @@ int run_query(MYSQL* mysql, struct query* q) return error; } int check_first_word(struct query* q, const char* word, int len) { const char* p, *p1, *end; if(len != q->first_word_len) return 0; p = word; end = p + len; p1 = q->q; for(; p < end; p++, p1++) if(tolower(*p) != tolower(*p1)) return 0; return 1; } void get_query_type(struct query* q) { char save; uint type; if (*q->q == '}') { q->type = Q_END_BLOCK; return; } if (q->type != Q_COMMENT_WITH_COMMAND) q->type = Q_QUERY; switch(q->first_word_len) { case 3: if(check_first_word(q, "inc", 3)) q->type = Q_INC; else if(check_first_word(q, "dec", 3)) q->type = Q_DEC; else if(check_first_word(q, "let", 3)) q->type = Q_LET; break; case 4: if(check_first_word(q, "echo", 4)) q->type = Q_ECHO; break; case 5: if(check_first_word(q, "sleep", 5)) q->type = Q_SLEEP; else if(check_first_word(q, "while", 5)) q->type = Q_WHILE; break; case 6: if(check_first_word(q, "source", 6)) q->type = Q_SOURCE; else if(check_first_word(q, "system", 6)) q->type = Q_SYSTEM; break; case 7: if(check_first_word(q, "connect", 7)) q->type = Q_CONNECT; break; case 10: if(check_first_word(q, "connection", 10)) q->type = Q_CONNECTION; else if(check_first_word(q, "disconnect", 10)) q->type = Q_DISCONNECT; break; save=q->q[q->first_word_len]; q->q[q->first_word_len]=0; type=find_type(q->q, &command_typelib, 0); q->q[q->first_word_len]=save; if (type > 0) q->type=type; /* Found command */ } } int main(int argc, char** argv) { int error = 0; struct query* q; my_bool require_file=0; char save_file[FN_REFLEN]; save_file[0]=0; MY_INIT(argv[0]); memset(cons, 0, sizeof(cons)); Loading @@ -1238,6 +1268,7 @@ int main(int argc, char** argv) memset(file_stack, 0, sizeof(file_stack)); file_stack_end = file_stack + MAX_INCLUDE_DEPTH; cur_file = file_stack; lineno = lineno_stack; init_dynamic_array(&q_lines, sizeof(struct query*), INIT_Q_LINES, INIT_Q_LINES); memset(block_stack, 0, sizeof(block_stack)); Loading @@ -1247,8 +1278,7 @@ int main(int argc, char** argv) parse_args(argc, argv); if (!*cur_file) *cur_file = stdin; *lineno=1; if (!( mysql_init(&cur_con->mysql))) die("Failed in mysql_init()"); Loading @@ -1267,13 +1297,12 @@ int main(int argc, char** argv) for(;!read_query(&q);) { int current_line_inc = 1, processed = 0; if(q->type == Q_UNKNOWN) if (q->type == Q_UNKNOWN || q->type == Q_COMMENT_WITH_COMMAND) get_query_type(q); if (block_ok) { processed = 1; switch(q->type) { switch (q->type) { case Q_CONNECT: do_connect(q); break; case Q_CONNECTION: select_connection(q); break; case Q_DISCONNECT: close_connection(q); break; Loading @@ -1284,7 +1313,26 @@ int main(int argc, char** argv) case Q_ECHO: do_echo(q); break; case Q_SYSTEM: do_system(q); break; case Q_LET: do_let(q); break; case Q_QUERY: error |= run_query(&cur_con->mysql, q); break; case Q_QUERY: { if (save_file[0]) { strmov(q->record_file,save_file); q->require_file=require_file; save_file[0]=0; } error |= run_query(&cur_con->mysql, q); break; } case Q_RESULT: get_file_name(save_file,q); require_file=0; break; case Q_REQUIRE: get_file_name(save_file,q); require_file=1; break; case Q_COMMENT: /* Ignore row */ case Q_COMMENT_WITH_COMMAND: default: processed = 0; break; } } Loading @@ -1308,7 +1356,7 @@ int main(int argc, char** argv) if (result_file && ds_res.len) { if(!record) error |= check_result(&ds_res, result_file); error |= check_result(&ds_res, result_file, q->require_file); else str_to_file(result_file, ds_res.str, ds_res.len); } Loading
configure.in +1 −1 Original line number Diff line number Diff line Loading @@ -4,7 +4,7 @@ dnl Process this file with autoconf to produce a configure script. AC_INIT(sql/mysqld.cc) AC_CANONICAL_SYSTEM # The Docs Makefile.am parses this line! AM_INIT_AUTOMAKE(mysql, 3.23.29a-gamma) AM_INIT_AUTOMAKE(mysql, 3.23.30-gamma) AM_CONFIG_HEADER(config.h) PROTOCOL_VERSION=10 Loading