diff options
Diffstat (limited to 'client/mysqltest.cc')
-rw-r--r-- | client/mysqltest.cc | 350 |
1 files changed, 221 insertions, 129 deletions
diff --git a/client/mysqltest.cc b/client/mysqltest.cc index 842bde3b99e..7ec2a62dcf7 100644 --- a/client/mysqltest.cc +++ b/client/mysqltest.cc @@ -44,7 +44,8 @@ #include <hash.h> #include <stdarg.h> #include <violite.h> -#include "my_regex.h" /* Our own version of regex */ +#define PCRE_STATIC 1 /* Important on Windows */ +#include "pcreposix.h" /* pcreposix regex library */ #ifdef HAVE_SYS_WAIT_H #include <sys/wait.h> #endif @@ -87,6 +88,8 @@ static my_bool non_blocking_api_enabled= 0; #define QUERY_SEND_FLAG 1 #define QUERY_REAP_FLAG 2 +#define QUERY_PRINT_ORIGINAL_FLAG 4 + #ifndef HAVE_SETENV static int setenv(const char *name, const char *value, int overwrite); #endif @@ -178,6 +181,7 @@ static uint my_end_arg= 0; static uint opt_tail_lines= 0; static uint opt_connect_timeout= 0; +static uint opt_wait_for_pos_timeout= 0; static char delimiter[MAX_DELIMITER_LENGTH]= ";"; static uint delimiter_length= 1; @@ -248,14 +252,16 @@ static const char *opt_suite_dir, *opt_overlay_dir; static size_t suite_dir_len, overlay_dir_len; /* Precompiled re's */ -static my_regex_t ps_re; /* the query can be run using PS protocol */ -static my_regex_t sp_re; /* the query can be run as a SP */ -static my_regex_t view_re; /* the query can be run as a view*/ +static regex_t ps_re; /* the query can be run using PS protocol */ +static regex_t sp_re; /* the query can be run as a SP */ +static regex_t view_re; /* the query can be run as a view*/ static void init_re(void); -static int match_re(my_regex_t *, char *); +static int match_re(regex_t *, char *); static void free_re(void); +static char *get_string(char **to_ptr, char **from_ptr, + struct st_command *command); static int replace(DYNAMIC_STRING *ds_str, const char *search_str, ulong search_len, const char *replace_str, ulong replace_len); @@ -345,7 +351,8 @@ enum enum_commands { Q_ERROR, Q_SEND, Q_REAP, Q_DIRTY_CLOSE, Q_REPLACE, Q_REPLACE_COLUMN, - Q_PING, Q_EVAL, + Q_PING, Q_EVAL, + Q_EVALP, Q_EVAL_RESULT, Q_ENABLE_QUERY_LOG, Q_DISABLE_QUERY_LOG, Q_ENABLE_RESULT_LOG, Q_DISABLE_RESULT_LOG, @@ -411,6 +418,7 @@ const char *command_names[]= "replace_column", "ping", "eval", + "evalp", "eval_result", /* Enable/disable that the _query_ is logged to result file */ "enable_query_log", @@ -592,7 +600,7 @@ void do_eval(DYNAMIC_STRING *query_eval, const char *query, void str_to_file(const char *fname, char *str, int size); void str_to_file2(const char *fname, char *str, int size, my_bool append); -void fix_win_paths(const char *val, int len); +void fix_win_paths(const char *val, size_t len); const char *get_errname_from_code (uint error_code); int multi_reg_replace(struct st_replace_regex* r,char* val); @@ -806,8 +814,7 @@ public: LogFile log_file; LogFile progress_file; -void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val, - int len); +void replace_dynstr_append_mem(DYNAMIC_STRING *ds, const char *val, size_t len); void replace_dynstr_append(DYNAMIC_STRING *ds, const char *val); void replace_dynstr_append_uint(DYNAMIC_STRING *ds, uint val); void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING* ds_input, @@ -832,6 +839,7 @@ static void handle_no_active_connection(struct st_command* command, #define EMB_END_CONNECTION 3 #define EMB_PREPARE_STMT 4 #define EMB_EXECUTE_STMT 5 +#define EMB_CLOSE_STMT 6 /* workaround for MySQL BUG#57491 */ #undef MY_WME @@ -880,6 +888,9 @@ pthread_handler_t connection_thread(void *arg) case EMB_EXECUTE_STMT: cn->result= mysql_stmt_execute(cn->stmt); break; + case EMB_CLOSE_STMT: + cn->result= mysql_stmt_close(cn->stmt); + break; default: DBUG_ASSERT(0); } @@ -977,6 +988,17 @@ static int do_stmt_execute(struct st_connection *cn) } +static int do_stmt_close(struct st_connection *cn) +{ + /* The cn->stmt is already set. */ + if (!cn->has_thread) + return mysql_stmt_close(cn->stmt); + signal_connection_thd(cn, EMB_CLOSE_STMT); + wait_query_thread_done(cn); + return cn->result; +} + + static void emb_close_connection(struct st_connection *cn) { if (!cn->has_thread) @@ -1012,6 +1034,7 @@ static void init_connection_thd(struct st_connection *cn) #define do_read_query_result(cn) mysql_read_query_result(cn->mysql) #define do_stmt_prepare(cn, q, q_len) mysql_stmt_prepare(cn->stmt, q, q_len) #define do_stmt_execute(cn) mysql_stmt_execute(cn->stmt) +#define do_stmt_close(cn) mysql_stmt_close(cn->stmt) #endif /*EMBEDDED_LIBRARY*/ @@ -1081,7 +1104,7 @@ void do_eval(DYNAMIC_STRING *query_eval, const char *query, Run query and dump the result to stderr in vertical format NOTE! This function should be safe to call when an error - has occured and thus any further errors will be ignored(although logged) + has occurred and thus any further errors will be ignored (although logged) SYNOPSIS show_query @@ -1147,7 +1170,7 @@ static void show_query(MYSQL* mysql, const char* query) is added to the warning stack, only print @@warning_count-1 warnings. NOTE! This function should be safe to call when an error - has occured and this any further errors will be ignored(although logged) + has occurred and this any further errors will be ignored(although logged) SYNOPSIS show_warnings_before_error @@ -1371,11 +1394,11 @@ void close_connections() DBUG_ENTER("close_connections"); for (--next_con; next_con >= connections; --next_con) { + if (next_con->stmt) + do_stmt_close(next_con); #ifdef EMBEDDED_LIBRARY emb_close_connection(next_con); #endif - if (next_con->stmt) - mysql_stmt_close(next_con->stmt); next_con->stmt= 0; mysql_close(next_con->mysql); next_con->mysql= 0; @@ -1395,7 +1418,7 @@ void close_statements() for (con= connections; con < next_con; con++) { if (con->stmt) - mysql_stmt_close(con->stmt); + do_stmt_close(con); con->stmt= 0; } DBUG_VOID_RETURN; @@ -2630,6 +2653,7 @@ void var_query_set(VAR *var, const char *query, const char** query_end) if (!mysql) { struct st_command command; + DBUG_ASSERT(query_end); memset(&command, 0, sizeof(command)); command.query= (char*)query; command.first_word_len= (*query_end - query); @@ -3327,6 +3351,8 @@ void do_exec(struct st_command *command) DBUG_ENTER("do_exec"); DBUG_PRINT("enter", ("cmd: '%s'", cmd)); + var_set_int("$sys_errno",0); + /* Skip leading space */ while (*cmd && my_isspace(charset_info, *cmd)) cmd++; @@ -3443,6 +3469,7 @@ void do_exec(struct st_command *command) report_or_die("command \"%s\" failed with wrong error: %d", command->first_argument, status); } + var_set_int("$sys_errno",status); } else if (command->expected_errors.err[0].type == ERR_ERRNO && command->expected_errors.err[0].code.errnum != 0) @@ -3697,7 +3724,6 @@ void do_remove_files_wildcard(struct st_command *command) fn_format(dirname, ds_directory.str, "", "", MY_UNPACK_FILENAME); DBUG_PRINT("info", ("listing directory: %s", dirname)); - /* Note that my_dir sorts the list if not given any flags */ if (!(dir_info= my_dir(dirname, MYF(MY_DONT_SORT | MY_WANT_STAT | MY_WME)))) { error= 1; @@ -3712,7 +3738,7 @@ void do_remove_files_wildcard(struct st_command *command) /* Set default wild chars for wild_compare, is changed in embedded mode */ set_wild_chars(1); - for (i= 0; i < (uint) dir_info->number_off_files; i++) + for (i= 0; i < (uint) dir_info->number_of_files; i++) { file= dir_info->dir_entry + i; /* Remove only regular files, i.e. no directories etc. */ @@ -3975,17 +4001,12 @@ static int get_list_files(DYNAMIC_STRING *ds, const DYNAMIC_STRING *ds_dirname, DBUG_ENTER("get_list_files"); DBUG_PRINT("info", ("listing directory: %s", ds_dirname->str)); - /* Note that my_dir sorts the list if not given any flags */ - if (!(dir_info= my_dir(ds_dirname->str, MYF(0)))) + if (!(dir_info= my_dir(ds_dirname->str, MYF(MY_WANT_SORT)))) DBUG_RETURN(1); set_wild_chars(1); - for (i= 0; i < (uint) dir_info->number_off_files; i++) + for (i= 0; i < (uint) dir_info->number_of_files; i++) { file= dir_info->dir_entry + i; - if (file->name[0] == '.' && - (file->name[1] == '\0' || - (file->name[1] == '.' && file->name[2] == '\0'))) - continue; /* . or .. */ if (ds_wild && ds_wild->length && wild_compare(file->name, ds_wild->str, 0)) continue; @@ -4657,19 +4678,21 @@ void do_wait_for_slave_to_stop(struct st_command *c __attribute__((unused))) } -void do_sync_with_master2(struct st_command *command, long offset) +void do_sync_with_master2(struct st_command *command, long offset, + const char *connection_name) { MYSQL_RES *res; MYSQL_ROW row; MYSQL *mysql= cur_con->mysql; char query_buf[FN_REFLEN+128]; - int timeout= 300; /* seconds */ + int timeout= opt_wait_for_pos_timeout; if (!master_pos.file[0]) die("Calling 'sync_with_master' without calling 'save_master_pos'"); - sprintf(query_buf, "select master_pos_wait('%s', %ld, %d)", - master_pos.file, master_pos.pos + offset, timeout); + sprintf(query_buf, "select master_pos_wait('%s', %ld, %d, '%s')", + master_pos.file, master_pos.pos + offset, timeout, + connection_name); if (mysql_query(mysql, query_buf)) die("failed in '%s': %d: %s", query_buf, mysql_errno(mysql), @@ -4704,7 +4727,7 @@ void do_sync_with_master2(struct st_command *command, long offset) master_pos_wait returned NULL. This indicates that slave SQL thread is not started, the slave's master information is not initialized, the arguments are - incorrect, or an error has occured + incorrect, or an error has occurred */ die("%.*s failed: '%s' returned NULL " \ "indicating slave SQL thread failure", @@ -4729,16 +4752,32 @@ void do_sync_with_master(struct st_command *command) long offset= 0; char *p= command->first_argument; const char *offset_start= p; + char *start, *buff= 0; + start= (char*) ""; + if (*offset_start) { for (; my_isdigit(charset_info, *p); p++) offset = offset * 10 + *p - '0'; - if(*p && !my_isspace(charset_info, *p)) + if (*p && !my_isspace(charset_info, *p) && *p != ',') die("Invalid integer argument \"%s\"", offset_start); + + while (*p && my_isspace(charset_info, *p)) + p++; + if (*p == ',') + { + p++; + while (*p && my_isspace(charset_info, *p)) + p++; + start= buff= (char*)my_malloc(strlen(p)+1,MYF(MY_WME | MY_FAE)); + get_string(&buff, &p, command); + } command->last_argument= p; } - do_sync_with_master2(command, offset); + do_sync_with_master2(command, offset, start); + if (buff) + my_free(start); return; } @@ -5390,7 +5429,7 @@ void do_get_errcodes(struct st_command *command) { die("The sqlstate definition must start with an uppercase S"); } - else if (*p == 'E' || *p == 'H') + else if (*p == 'E' || *p == 'W' || *p == 'H') { /* Error name string */ @@ -5399,9 +5438,9 @@ void do_get_errcodes(struct st_command *command) to->type= ERR_ERRNO; DBUG_PRINT("info", ("ERR_ERRNO: %d", to->code.errnum)); } - else if (*p == 'e' || *p == 'h') + else if (*p == 'e' || *p == 'w' || *p == 'h') { - die("The error name definition must start with an uppercase E or H"); + die("The error name definition must start with an uppercase E or W or H"); } else { @@ -5464,8 +5503,8 @@ void do_get_errcodes(struct st_command *command) If string is a '$variable', return the value of the variable. */ -char *get_string(char **to_ptr, char **from_ptr, - struct st_command *command) +static char *get_string(char **to_ptr, char **from_ptr, + struct st_command *command) { char c, sep; char *to= *to_ptr, *from= *from_ptr, *start=to; @@ -5639,7 +5678,11 @@ void do_close_connection(struct st_command *command) con->mysql->net.vio = 0; } } -#else +#endif /*!EMBEDDED_LIBRARY*/ + if (con->stmt) + do_stmt_close(con); + con->stmt= 0; +#ifdef EMBEDDED_LIBRARY /* As query could be still executed in a separate theread we need to check if the query's thread was finished and probably wait @@ -5647,9 +5690,6 @@ void do_close_connection(struct st_command *command) */ emb_close_connection(con); #endif /*EMBEDDED_LIBRARY*/ - if (con->stmt) - mysql_stmt_close(con->stmt); - con->stmt= 0; mysql_close(con->mysql); con->mysql= 0; @@ -5726,6 +5766,10 @@ void safe_connect(MYSQL* mysql, const char *name, const char *host, verbose_msg("Connecting to server %s:%d (socket %s) as '%s'" ", connection '%s', attempt %d ...", host, port, sock, user, name, failed_attempts); + + mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0); + mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD, + "program_name", "mysqltest"); while(!mysql_real_connect(mysql, host,user, pass, db, port, sock, CLIENT_MULTI_STATEMENTS | CLIENT_REMEMBER_OPTIONS)) { @@ -5826,7 +5870,9 @@ int connect_n_handle_errors(struct st_command *command, replace_dynstr_append(ds, command->query); dynstr_append_mem(ds, ";\n", 2); } - + + mysql_options(con, MYSQL_OPT_CONNECT_ATTR_RESET, 0); + mysql_options4(con, MYSQL_OPT_CONNECT_ATTR_ADD, "program_name", "mysqltest"); while (!mysql_real_connect(con, host, user, pass, db, port, sock ? sock: 0, CLIENT_MULTI_STATEMENTS)) { @@ -5910,6 +5956,8 @@ void do_connect(struct st_command *command) my_bool con_ssl= 0, con_compress= 0; my_bool con_pipe= 0; my_bool con_shm __attribute__ ((unused))= 0; + int read_timeout= 0; + int write_timeout= 0; int connect_timeout= 0; struct st_connection* con_slot; @@ -6007,9 +6055,21 @@ void do_connect(struct st_command *command) con_pipe= 1; else if (length == 3 && !strncmp(con_options, "SHM", 3)) con_shm= 1; + else if (strncasecmp(con_options, "read_timeout=", + sizeof("read_timeout=")-1) == 0) + { + read_timeout= atoi(con_options + sizeof("read_timeout=")-1); + } + else if (strncasecmp(con_options, "write_timeout=", + sizeof("write_timeout=")-1) == 0) + { + write_timeout= atoi(con_options + sizeof("write_timeout=")-1); + } else if (strncasecmp(con_options, "connect_timeout=", sizeof("connect_timeout=")-1) == 0) + { connect_timeout= atoi(con_options + sizeof("connect_timeout=")-1); + } else die("Illegal option to connect: %.*s", (int) (end - con_options), con_options); @@ -6060,6 +6120,8 @@ void do_connect(struct st_command *command) #if defined(HAVE_OPENSSL) && !defined(EMBEDDED_LIBRARY) mysql_ssl_set(con_slot->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, ssl_cipher ? ssl_cipher : opt_ssl_cipher); + mysql_options(con_slot->mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl); + mysql_options(con_slot->mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath); #if MYSQL_VERSION_ID >= 50000 /* Turn on ssl_verify_server_cert only if host is "localhost" */ opt_ssl_verify_server_cert= !strcmp(ds_host.str, "localhost"); @@ -6079,9 +6141,23 @@ void do_connect(struct st_command *command) if (opt_protocol) mysql_options(con_slot->mysql, MYSQL_OPT_PROTOCOL, (char*) &opt_protocol); + if (read_timeout) + { + mysql_options(con_slot->mysql, MYSQL_OPT_READ_TIMEOUT, + (char*)&read_timeout); + } + + if (write_timeout) + { + mysql_options(con_slot->mysql, MYSQL_OPT_WRITE_TIMEOUT, + (char*)&write_timeout); + } + if (connect_timeout) + { mysql_options(con_slot->mysql, MYSQL_OPT_CONNECT_TIMEOUT, (char*)&connect_timeout); + } #ifdef HAVE_SMEM if (con_shm) @@ -6603,9 +6679,9 @@ int read_line() } else if ((c == '{' && (!my_strnncoll_simple(charset_info, (const uchar*) "while", 5, - (uchar*) read_command_buf, min(5, p - read_command_buf), 0) || + (uchar*) read_command_buf, MY_MIN(5, p - read_command_buf), 0) || !my_strnncoll_simple(charset_info, (const uchar*) "if", 2, - (uchar*) read_command_buf, min(2, p - read_command_buf), 0)))) + (uchar*) read_command_buf, MY_MIN(2, p - read_command_buf), 0)))) { /* Only if and while commands can be terminated by { */ *p++= c; @@ -7082,6 +7158,10 @@ static struct my_option my_long_options[] = "Number of seconds before connection timeout.", &opt_connect_timeout, &opt_connect_timeout, 0, GET_UINT, REQUIRED_ARG, 120, 0, 3600 * 12, 0, 0, 0}, + {"wait_for_pos_timeout", 0, + "Number of seconds to wait for master_pos_wait", + &opt_wait_for_pos_timeout, &opt_wait_for_pos_timeout, 0, GET_UINT, + REQUIRED_ARG, 300, 0, 3600 * 12, 0, 0, 0}, {"plugin_dir", 0, "Directory for client-side plugins.", &opt_plugin_dir, &opt_plugin_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, @@ -7361,13 +7441,13 @@ void str_to_file(const char *fname, char *str, int size) } -void check_regerr(my_regex_t* r, int err) +void check_regerr(regex_t* r, int err) { char err_buf[1024]; if (err) { - my_regerror(err,r,err_buf,sizeof(err_buf)); + regerror(err,r,err_buf,sizeof(err_buf)); die("Regex error: %s\n", err_buf); } } @@ -7402,7 +7482,7 @@ void init_win_path_patterns() DBUG_ENTER("init_win_path_patterns"); - my_init_dynamic_array(&patterns, sizeof(const char*), 16, 16); + my_init_dynamic_array(&patterns, sizeof(const char*), 16, 16, MYF(0)); /* Loop through all paths in the array */ for (i= 0; i < num_paths; i++) @@ -7462,7 +7542,7 @@ void free_win_path_patterns() => all \ from c:\mysql\m... until next space is converted into / */ -void fix_win_paths(const char *val, int len) +void fix_win_paths(const char *val, size_t len) { uint i; char *p; @@ -7751,6 +7831,7 @@ int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql) { uint count; MYSQL_RES *warn_res; + DYNAMIC_STRING res; DBUG_ENTER("append_warnings"); if (!(count= mysql_warning_count(mysql))) @@ -7770,11 +7851,18 @@ int append_warnings(DYNAMIC_STRING *ds, MYSQL* mysql) die("Warning count is %u but didn't get any warnings", count); - append_result(ds, warn_res); + init_dynamic_string(&res, "", 1024, 1024); + + append_result(&res, warn_res); mysql_free_result(warn_res); - DBUG_PRINT("warnings", ("%s", ds->str)); + DBUG_PRINT("warnings", ("%s", res.str)); + if (display_result_sorted) + dynstr_append_sorted(ds, &res, 0); + else + dynstr_append_mem(ds, res.str, res.length); + dynstr_free(&res); DBUG_RETURN(count); } @@ -8438,7 +8526,8 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags) /* Evaluate query if this is an eval command */ - if (command->type == Q_EVAL || command->type == Q_SEND_EVAL) + if (command->type == Q_EVAL || command->type == Q_SEND_EVAL || + command->type == Q_EVALP) { if (!command->eval_query.str) init_dynamic_string(&command->eval_query, "", command->query_len + 256, @@ -8474,10 +8563,20 @@ void run_query(struct st_connection *cn, struct st_command *command, int flags) */ if (!disable_query_log && (flags & QUERY_SEND_FLAG)) { - replace_dynstr_append_mem(ds, query, query_len); + char *print_query= query; + int print_len= query_len; + if (flags & QUERY_PRINT_ORIGINAL_FLAG) + { + print_query= command->query; + print_len= command->end - command->query; + } + replace_dynstr_append_mem(ds, print_query, print_len); dynstr_append_mem(ds, delimiter, delimiter_length); dynstr_append_mem(ds, "\n", 1); } + + /* We're done with this flag */ + flags &= ~QUERY_PRINT_ORIGINAL_FLAG; /* Write the command to the result file before we execute the query @@ -8651,19 +8750,18 @@ char *re_eprint(int err) { static char epbuf[100]; size_t len __attribute__((unused))= - my_regerror(REG_ITOA|err, (my_regex_t *)NULL, epbuf, sizeof(epbuf)); + regerror(err, (regex_t *)NULL, epbuf, sizeof(epbuf)); assert(len <= sizeof(epbuf)); return(epbuf); } -void init_re_comp(my_regex_t *re, const char* str) +void init_re_comp(regex_t *re, const char* str) { - int err= my_regcomp(re, str, (REG_EXTENDED | REG_ICASE | REG_NOSUB), - &my_charset_latin1); + int err= regcomp(re, str, (REG_EXTENDED | REG_ICASE | REG_NOSUB | REG_DOTALL)); if (err) { char erbuf[100]; - int len= my_regerror(err, re, erbuf, sizeof(erbuf)); + int len= regerror(err, re, erbuf, sizeof(erbuf)); die("error %s, %d/%d `%s'\n", re_eprint(err), (int)len, (int)sizeof(erbuf), erbuf); } @@ -8709,7 +8807,7 @@ void init_re(void) } -int match_re(my_regex_t *re, char *str) +int match_re(regex_t *re, char *str) { while (my_isspace(charset_info, *str)) str++; @@ -8721,7 +8819,7 @@ int match_re(my_regex_t *re, char *str) str= comm_end + 2; } - int err= my_regexec(re, str, (size_t)0, NULL, 0); + int err= regexec(re, str, (size_t)0, NULL, 0); if (err == 0) return 1; @@ -8730,7 +8828,7 @@ int match_re(my_regex_t *re, char *str) { char erbuf[100]; - int len= my_regerror(err, re, erbuf, sizeof(erbuf)); + int len= regerror(err, re, erbuf, sizeof(erbuf)); die("error %s, %d/%d `%s'\n", re_eprint(err), (int)len, (int)sizeof(erbuf), erbuf); } @@ -8739,10 +8837,9 @@ int match_re(my_regex_t *re, char *str) void free_re(void) { - my_regfree(&ps_re); - my_regfree(&sp_re); - my_regfree(&view_re); - my_regex_end(); + regfree(&ps_re); + regfree(&sp_re); + regfree(&view_re); } /****************************************************************************/ @@ -9008,12 +9105,16 @@ int main(int argc, char **argv) cur_block->ok= TRUE; /* Outer block should always be executed */ cur_block->cmd= cmd_none; - my_init_dynamic_array(&q_lines, sizeof(struct st_command*), 1024, 1024); + my_init_dynamic_array(&q_lines, sizeof(struct st_command*), 1024, 1024, MYF(0)); if (my_hash_init2(&var_hash, 64, charset_info, - 128, 0, 0, get_var_key, var_free, MYF(0))) + 128, 0, 0, get_var_key, 0, var_free, MYF(0))) die("Variable hash initialization failed"); + { + char path_separator[]= { FN_LIBCHAR, 0 }; + var_set_string("SYSTEM_PATH_SEPARATOR", path_separator); + } var_set_string("MYSQL_SERVER_VERSION", MYSQL_SERVER_VERSION); var_set_string("MYSQL_SYSTEM_TYPE", SYSTEM_TYPE); var_set_string("MYSQL_MACHINE_TYPE", MACHINE_TYPE); @@ -9040,7 +9141,7 @@ int main(int argc, char **argv) read_command_buf= (char*)my_malloc(read_command_buflen= 65536, MYF(MY_FAE)); init_dynamic_string(&ds_res, "", 2048, 2048); - init_alloc_root(&require_file_root, 1024, 1024); + init_alloc_root(&require_file_root, 1024, 1024, MYF(0)); parse_args(argc, argv); @@ -9127,6 +9228,8 @@ int main(int argc, char **argv) { mysql_ssl_set(con->mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca, opt_ssl_capath, opt_ssl_cipher); + mysql_options(con->mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl); + mysql_options(con->mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath); #if MYSQL_VERSION_ID >= 50000 /* Turn on ssl_verify_server_cert only if host is "localhost" */ opt_ssl_verify_server_cert= opt_host && !strcmp(opt_host, "localhost"); @@ -9338,6 +9441,7 @@ int main(int argc, char **argv) case Q_EVAL_RESULT: die("'eval_result' command is deprecated"); case Q_EVAL: + case Q_EVALP: case Q_QUERY_VERTICAL: case Q_QUERY_HORIZONTAL: if (command->query == command->query_buf) @@ -9365,6 +9469,9 @@ int main(int argc, char **argv) flags= QUERY_REAP_FLAG; } + if (command->type == Q_EVALP) + flags |= QUERY_PRINT_ORIGINAL_FLAG; + /* Check for special property for this query */ display_result_vertically|= (command->type == Q_QUERY_VERTICAL); @@ -9434,7 +9541,7 @@ int main(int argc, char **argv) select_connection(command); else select_connection_name("slave"); - do_sync_with_master2(command, 0); + do_sync_with_master2(command, 0, ""); break; } case Q_COMMENT: @@ -9929,36 +10036,34 @@ struct st_regex int reg_replace(char** buf_p, int* buf_len_p, char *pattern, char *replace, char *string, int icase); +bool parse_re_part(char *start_re, char *end_re, + char **p, char *end, char **buf) +{ + if (*start_re != *end_re) + { + switch ((*start_re= *(*p)++)) { + case '(': *end_re= ')'; break; + case '[': *end_re= ']'; break; + case '{': *end_re= '}'; break; + case '<': *end_re= '>'; break; + default: *end_re= *start_re; + } + } + while (*p < end && **p != *end_re) + { + if ((*p)[0] == '\\' && *p + 1 < end && (*p)[1] == *end_re) + (*p)++; -/* - Finds the next (non-escaped) '/' in the expression. - (If the character '/' is needed, it can be escaped using '\'.) -*/ + *(*buf)++= *(*p)++; + } + *(*buf)++= 0; + + (*p)++; + + return *p > end; +} -#define PARSE_REGEX_ARG \ - while (p < expr_end) \ - { \ - char c= *p; \ - if (c == '/') \ - { \ - if (last_c == '\\') \ - { \ - buf_p[-1]= '/'; \ - } \ - else \ - { \ - *buf_p++ = 0; \ - break; \ - } \ - } \ - else \ - *buf_p++ = c; \ - \ - last_c= c; \ - p++; \ - } \ - \ /* Initializes the regular substitution expression to be used in the result output of test. @@ -9970,16 +10075,15 @@ struct st_replace_regex* init_replace_regex(char* expr) { struct st_replace_regex* res; char* buf,*expr_end; - char* p; + char* p, start_re, end_re= 1; char* buf_p; uint expr_len= strlen(expr); - char last_c = 0; struct st_regex reg; /* my_malloc() will die on fail with MY_FAE */ res=(struct st_replace_regex*)my_malloc( sizeof(*res)+expr_len ,MYF(MY_FAE+MY_WME)); - my_init_dynamic_array(&res->regex_arr,sizeof(struct st_regex),128,128); + my_init_dynamic_array(&res->regex_arr,sizeof(struct st_regex), 128, 128, MYF(0)); buf= (char*)res + sizeof(*res); expr_end= expr + expr_len; @@ -9991,44 +10095,32 @@ struct st_replace_regex* init_replace_regex(char* expr) { bzero(®,sizeof(reg)); /* find the start of the statement */ - while (p < expr_end) - { - if (*p == '/') - break; + while (my_isspace(charset_info, *p) && p < expr_end) p++; - } - if (p == expr_end || ++p == expr_end) + if (p >= expr_end) { if (res->regex_arr.elements) break; else goto err; } - /* we found the start */ - reg.pattern= buf_p; - - /* Find first argument -- pattern string to be removed */ - PARSE_REGEX_ARG - if (p == expr_end || ++p == expr_end) - goto err; + start_re= 0; + reg.pattern= buf_p; + if (parse_re_part(&start_re, &end_re, &p, expr_end, &buf_p)) + goto err; - /* buf_p now points to the replacement pattern terminated with \0 */ reg.replace= buf_p; - - /* Find second argument -- replace string to replace pattern */ - PARSE_REGEX_ARG - - if (p == expr_end) - goto err; - - /* skip the ending '/' in the statement */ - p++; + if (parse_re_part(&start_re, &end_re, &p, expr_end, &buf_p)) + goto err; /* Check if we should do matching case insensitive */ if (p < expr_end && *p == 'i') + { + p++; reg.icase= 1; + } /* done parsing the statement, now place it in regex_arr */ if (insert_dynamic(&res->regex_arr,(uchar*) ®)) @@ -10176,13 +10268,13 @@ void free_replace_regex() int reg_replace(char** buf_p, int* buf_len_p, char *pattern, char *replace, char *string, int icase) { - my_regex_t r; - my_regmatch_t *subs; + regex_t r; + regmatch_t *subs; char *replace_end; char *buf= *buf_p; int len; int buf_len, need_buf_len; - int cflags= REG_EXTENDED; + int cflags= REG_EXTENDED | REG_DOTALL; int err_code; char *res_p,*str_p,*str_end; @@ -10201,13 +10293,13 @@ int reg_replace(char** buf_p, int* buf_len_p, char *pattern, if (icase) cflags|= REG_ICASE; - if ((err_code= my_regcomp(&r,pattern,cflags,&my_charset_latin1))) + if ((err_code= regcomp(&r,pattern,cflags))) { check_regerr(&r,err_code); return 1; } - subs= (my_regmatch_t*)my_malloc(sizeof(my_regmatch_t) * (r.re_nsub+1), + subs= (regmatch_t*)my_malloc(sizeof(regmatch_t) * (r.re_nsub+1), MYF(MY_WME+MY_FAE)); *res_p= 0; @@ -10218,14 +10310,14 @@ int reg_replace(char** buf_p, int* buf_len_p, char *pattern, while (!err_code) { /* find the match */ - err_code= my_regexec(&r,str_p, r.re_nsub+1, subs, + err_code= regexec(&r,str_p, r.re_nsub+1, subs, (str_p == string) ? REG_NOTBOL : 0); /* if regular expression error (eg. bad syntax, or out of memory) */ if (err_code && err_code != REG_NOMATCH) { check_regerr(&r,err_code); - my_regfree(&r); + regfree(&r); return 1; } @@ -10338,7 +10430,7 @@ int reg_replace(char** buf_p, int* buf_len_p, char *pattern, } } my_free(subs); - my_regfree(&r); + regfree(&r); *res_p= 0; *buf_p= buf; *buf_len_p= buf_len; @@ -10953,7 +11045,7 @@ void free_pointer_array(POINTER_ARRAY *pa) /* Append the string to ds, with optional replace */ void replace_dynstr_append_mem(DYNAMIC_STRING *ds, - const char *val, int len) + const char *val, size_t len) { char lower[512]; #ifdef __WIN__ @@ -11034,7 +11126,7 @@ void dynstr_append_sorted(DYNAMIC_STRING* ds, DYNAMIC_STRING *ds_input, if (!*start) DBUG_VOID_RETURN; /* No input */ - my_init_dynamic_array(&lines, sizeof(const char*), 32, 32); + my_init_dynamic_array(&lines, sizeof(const char*), 32, 32, MYF(0)); if (keep_header) { |