Loading client/mysql.cc +31 −0 Original line number Diff line number Diff line Loading @@ -2101,6 +2101,37 @@ static bool add_line(String &buffer,char *line,char *in_string, continue; } } else if (!*ml_comment && !*in_string && (end_of_line - pos) >= 10 && !my_strnncoll(charset_info, (uchar*) pos, 10, (const uchar*) "delimiter ", 10)) { // Flush previously accepted characters if (out != line) { buffer.append(line, (uint32) (out - line)); out= line; } // Flush possible comments in the buffer if (!buffer.is_empty()) { if (com_go(&buffer, 0) > 0) // < 0 is not fatal DBUG_RETURN(1); buffer.length(0); } /* Delimiter wants the get rest of the given line as argument to allow one to change ';' to ';;' and back */ buffer.append(pos); if (com_delimiter(&buffer, pos) > 0) DBUG_RETURN(1); buffer.length(0); break; } else if (!*ml_comment && !*in_string && is_prefix(pos, delimiter)) { // Found a statement. Continue parsing after the delimiter Loading client/mysqltest.cc +258 −54 Original line number Diff line number Diff line Loading @@ -170,6 +170,8 @@ static void timer_output(void); static ulonglong timer_now(void); static ulong connection_retry_sleep= 100000; /* Microseconds */ /* 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 */ Loading Loading @@ -276,6 +278,7 @@ enum enum_commands { Q_WRITE_FILE, Q_COPY_FILE, Q_PERL, Q_DIE, Q_EXIT, Q_SKIP, Q_CHMOD_FILE, Q_APPEND_FILE, Q_CAT_FILE, Q_DIFF_FILES, Q_SEND_QUIT, Q_CHANGE_USER, Q_MKDIR, Q_RMDIR, Q_LIST_FILES, Q_LIST_FILES_WRITE_FILE, Q_LIST_FILES_APPEND_FILE, Q_SEND_SHUTDOWN, Q_SHUTDOWN_SERVER, Q_UNKNOWN, /* Unknown command. */ Loading Loading @@ -368,6 +371,9 @@ const char *command_names[]= "change_user", "mkdir", "rmdir", "list_files", "list_files_write_file", "list_files_append_file", "send_shutdown", "shutdown_server", Loading Loading @@ -654,6 +660,9 @@ 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); static int match_expected_error(struct st_command *command, unsigned int err_errno, const char *err_sqlstate); void handle_error(struct st_command*, unsigned int err_errno, const char *err_error, const char *err_sqlstate, DYNAMIC_STRING *ds); Loading Loading @@ -1010,30 +1019,26 @@ void check_command_args(struct st_command *command, DBUG_VOID_RETURN; } void handle_command_error(struct st_command *command, uint error) { DBUG_ENTER("handle_command_error"); DBUG_PRINT("enter", ("error: %d", error)); if (error != 0) { uint i; int i; if (command->abort_on_error) die("command \"%.*s\" failed with error %d", command->first_word_len, command->query, error); for (i= 0; i < command->expected_errors.count; i++) { DBUG_PRINT("info", ("expected error: %d", command->expected_errors.err[i].code.errnum)); if ((command->expected_errors.err[i].type == ERR_ERRNO) && (command->expected_errors.err[i].code.errnum == error)) i= match_expected_error(command, error, NULL); if (i >= 0) { DBUG_PRINT("info", ("command \"%.*s\" failed with expected error: %d", command->first_word_len, command->query, error)); DBUG_VOID_RETURN; } } die("command \"%.*s\" failed with wrong error: %d", command->first_word_len, command->query, error); } Loading Loading @@ -2601,8 +2606,8 @@ void do_exec(struct st_command *command) error= pclose(res_file); if (error > 0) { uint status= WEXITSTATUS(error), i; my_bool ok= 0; uint status= WEXITSTATUS(error); int i; if (command->abort_on_error) { Loading @@ -2614,19 +2619,13 @@ void do_exec(struct st_command *command) DBUG_PRINT("info", ("error: %d, status: %d", error, status)); for (i= 0; i < command->expected_errors.count; i++) { DBUG_PRINT("info", ("expected error: %d", command->expected_errors.err[i].code.errnum)); if ((command->expected_errors.err[i].type == ERR_ERRNO) && (command->expected_errors.err[i].code.errnum == status)) { ok= 1; i= match_expected_error(command, status, NULL); if (i >= 0) DBUG_PRINT("info", ("command \"%s\" failed with expected error: %d", command->first_argument, status)); } } if (!ok) else { dynstr_free(&ds_cmd); die("command \"%s\" failed with wrong error: %d", Loading Loading @@ -2976,6 +2975,126 @@ void do_rmdir(struct st_command *command) } /* SYNOPSIS get_list_files ds output ds_dirname dir to list ds_wild wild-card file pattern (can be empty) DESCRIPTION list all entries in directory (matching ds_wild if given) */ static int get_list_files(DYNAMIC_STRING *ds, const DYNAMIC_STRING *ds_dirname, const DYNAMIC_STRING *ds_wild) { uint i; MY_DIR *dir_info; FILEINFO *file; 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)))) DBUG_RETURN(1); for (i= 0; i < (uint) dir_info->number_off_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; dynstr_append(ds, file->name); dynstr_append(ds, "\n"); } my_dirend(dir_info); DBUG_RETURN(0); } /* SYNOPSIS do_list_files command called command DESCRIPTION list_files <dir_name> [<file_name>] List files and directories in directory <dir_name> (like `ls`) [Matching <file_name>, where wild-cards are allowed] */ static void do_list_files(struct st_command *command) { int error; static DYNAMIC_STRING ds_dirname; static DYNAMIC_STRING ds_wild; const struct command_arg list_files_args[] = { {"dirname", ARG_STRING, TRUE, &ds_dirname, "Directory to list"}, {"file", ARG_STRING, FALSE, &ds_wild, "Filename (incl. wildcard)"} }; DBUG_ENTER("do_list_files"); check_command_args(command, command->first_argument, list_files_args, sizeof(list_files_args)/sizeof(struct command_arg), ' '); error= get_list_files(&ds_res, &ds_dirname, &ds_wild); handle_command_error(command, error); dynstr_free(&ds_dirname); dynstr_free(&ds_wild); DBUG_VOID_RETURN; } /* SYNOPSIS do_list_files_write_file_command command called command append append file, or create new DESCRIPTION list_files_{write|append}_file <filename> <dir_name> [<match_file>] List files and directories in directory <dir_name> (like `ls`) [Matching <match_file>, where wild-cards are allowed] Note: File will be truncated if exists and append is not true. */ static void do_list_files_write_file_command(struct st_command *command, my_bool append) { int error; static DYNAMIC_STRING ds_content; static DYNAMIC_STRING ds_filename; static DYNAMIC_STRING ds_dirname; static DYNAMIC_STRING ds_wild; const struct command_arg list_files_args[] = { {"filename", ARG_STRING, TRUE, &ds_filename, "Filename for write"}, {"dirname", ARG_STRING, TRUE, &ds_dirname, "Directory to list"}, {"file", ARG_STRING, FALSE, &ds_wild, "Filename (incl. wildcard)"} }; DBUG_ENTER("do_list_files_write_file"); check_command_args(command, command->first_argument, list_files_args, sizeof(list_files_args)/sizeof(struct command_arg), ' '); init_dynamic_string(&ds_content, "", 1024, 1024); error= get_list_files(&ds_content, &ds_dirname, &ds_wild); handle_command_error(command, error); str_to_file2(ds_filename.str, ds_content.str, ds_content.length, append); dynstr_free(&ds_content); dynstr_free(&ds_filename); dynstr_free(&ds_dirname); dynstr_free(&ds_wild); DBUG_VOID_RETURN; } /* Read characters from line buffer or file. This is needed to allow my_ungetc() to buffer MAX_DELIMITER_LENGTH characters for a file Loading Loading @@ -4458,7 +4577,6 @@ void safe_connect(MYSQL* mysql, const char *name, const char *host, int port, const char *sock) { int failed_attempts= 0; static ulong connection_retry_sleep= 100000; /* Microseconds */ DBUG_ENTER("safe_connect"); while(!mysql_real_connect(mysql, host,user, pass, db, port, sock, Loading Loading @@ -4525,6 +4643,7 @@ int connect_n_handle_errors(struct st_command *command, const char* db, int port, const char* sock) { DYNAMIC_STRING *ds; int failed_attempts= 0; ds= &ds_res; Loading Loading @@ -4553,9 +4672,41 @@ int connect_n_handle_errors(struct st_command *command, dynstr_append_mem(ds, delimiter, delimiter_length); dynstr_append_mem(ds, "\n", 1); } if (!mysql_real_connect(con, host, user, pass, db, port, sock ? sock: 0, while (!mysql_real_connect(con, host, user, pass, db, port, sock ? sock: 0, CLIENT_MULTI_STATEMENTS)) { /* If we have used up all our connections check whether this is expected (by --error). If so, handle the error right away. Otherwise, give it some extra time to rule out race-conditions. If extra-time doesn't help, we have an unexpected error and must abort -- just proceeding to handle_error() when second and third chances are used up will handle that for us. There are various user-limits of which only max_user_connections and max_connections_per_hour apply at connect time. For the the second to create a race in our logic, we'd need a limits test that runs without a FLUSH for longer than an hour, so we'll stay clear of trying to work out which exact user-limit was exceeded. */ if (((mysql_errno(con) == ER_TOO_MANY_USER_CONNECTIONS) || (mysql_errno(con) == ER_USER_LIMIT_REACHED)) && (failed_attempts++ < opt_max_connect_retries)) { int i; i= match_expected_error(command, mysql_errno(con), mysql_sqlstate(con)); if (i >= 0) goto do_handle_error; /* expected error, handle */ my_sleep(connection_retry_sleep); /* unexpected error, wait */ continue; /* and give it 1 more chance */ } do_handle_error: var_set_errno(mysql_errno(con)); handle_error(command, mysql_errno(con), mysql_error(con), mysql_sqlstate(con), ds); Loading Loading @@ -6265,6 +6416,56 @@ void run_query_normal(struct st_connection *cn, struct st_command *command, } /* Check whether given error is in list of expected errors SYNOPSIS match_expected_error() PARAMETERS command the current command (and its expect-list) err_errno error number of the error that actually occurred err_sqlstate SQL-state that was thrown, or NULL for impossible (file-ops, diff, etc.) RETURNS -1 for not in list, index in list of expected errors otherwise NOTE If caller needs to know whether the list was empty, they should check command->expected_errors.count. */ static int match_expected_error(struct st_command *command, unsigned int err_errno, const char *err_sqlstate) { uint i; for (i= 0 ; (uint) i < command->expected_errors.count ; i++) { if ((command->expected_errors.err[i].type == ERR_ERRNO) && (command->expected_errors.err[i].code.errnum == err_errno)) return i; if (command->expected_errors.err[i].type == ERR_SQLSTATE) { /* NULL is quite likely, but not in conjunction with a SQL-state expect! */ if (unlikely(err_sqlstate == NULL)) die("expecting a SQL-state (%s) from query '%s' which cannot produce one...", command->expected_errors.err[i].code.sqlstate, command->query); if (strncmp(command->expected_errors.err[i].code.sqlstate, err_sqlstate, SQLSTATE_LENGTH) == 0) return i; } } return -1; } /* Handle errors which occurred during execution Loading @@ -6285,7 +6486,7 @@ void handle_error(struct st_command *command, unsigned int err_errno, const char *err_error, const char *err_sqlstate, DYNAMIC_STRING *ds) { uint i; int i; DBUG_ENTER("handle_error"); Loading @@ -6311,13 +6512,10 @@ void handle_error(struct st_command *command, DBUG_PRINT("info", ("expected_errors.count: %d", command->expected_errors.count)); for (i= 0 ; (uint) i < command->expected_errors.count ; i++) { if (((command->expected_errors.err[i].type == ERR_ERRNO) && (command->expected_errors.err[i].code.errnum == err_errno)) || ((command->expected_errors.err[i].type == ERR_SQLSTATE) && (strncmp(command->expected_errors.err[i].code.sqlstate, err_sqlstate, SQLSTATE_LENGTH) == 0))) i= match_expected_error(command, err_errno, err_sqlstate); if (i >= 0) { if (!disable_result_log) { Loading @@ -6339,7 +6537,6 @@ void handle_error(struct st_command *command, /* OK */ DBUG_VOID_RETURN; } } DBUG_PRINT("info",("i: %d expected_errors: %d", i, command->expected_errors.count)); Loading @@ -6353,7 +6550,7 @@ void handle_error(struct st_command *command, dynstr_append_mem(ds, "\n", 1); } if (i) if (command->expected_errors.count > 0) { if (command->expected_errors.err[0].type == ERR_ERRNO) die("query '%s' failed with wrong errno %d: '%s', instead of %d...", Loading Loading @@ -7375,6 +7572,13 @@ int main(int argc, char **argv) case Q_REMOVE_FILE: do_remove_file(command); break; case Q_MKDIR: do_mkdir(command); break; case Q_RMDIR: do_rmdir(command); break; case Q_LIST_FILES: do_list_files(command); break; case Q_LIST_FILES_WRITE_FILE: do_list_files_write_file_command(command, FALSE); break; case Q_LIST_FILES_APPEND_FILE: do_list_files_write_file_command(command, TRUE); break; case Q_FILE_EXIST: do_file_exist(command); break; case Q_WRITE_FILE: do_write_file(command); break; case Q_APPEND_FILE: do_append_file(command); break; Loading configure.in +5 −5 Original line number Diff line number Diff line Loading @@ -617,19 +617,19 @@ fi AC_MSG_CHECKING(whether features provided by the user community should be included.) AC_ARG_ENABLE(community-features, AC_HELP_STRING( [--enable-community-features], [Enable additional features provided by the user community.]), [--disable-community-features], [Disable additional features provided by the user community.]), [ ENABLE_COMMUNITY_FEATURES=$enableval ], [ ENABLE_COMMUNITY_FEATURES=no ] [ ENABLE_COMMUNITY_FEATURES=yes ] ) if test "$ENABLE_COMMUNITY_FEATURES" = "yes" then AC_DEFINE([COMMUNITY_SERVER], [1], [Whether features provided by the user community should be included]) AC_MSG_RESULT([yes, community server]) AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no, enterprise server]) AC_MSG_RESULT([no]) fi AC_ARG_WITH(server-suffix, Loading include/my_sys.h +1 −0 Original line number Diff line number Diff line Loading @@ -693,6 +693,7 @@ extern char * fn_format(char * to,const char *name,const char *dir, const char *form, uint flag); extern size_t strlength(const char *str); extern void pack_dirname(char * to,const char *from); extern size_t normalize_dirname(char * to, const char *from); extern size_t unpack_dirname(char * to,const char *from); extern size_t cleanup_dirname(char * to,const char *from); extern size_t system_filename(char * to,const char *from); Loading libmysqld/emb_qcache.cc +2 −1 Original line number Diff line number Diff line Loading @@ -447,7 +447,8 @@ int emb_load_querycache_result(THD *thd, Querycache_stream *src) if (thd->protocol == &thd->protocol_binary) { uint length; row= (MYSQL_ROWS *)alloc_root(&data->alloc, rows * sizeof(MYSQL_ROWS)); row= (MYSQL_ROWS *)alloc_root(&data->alloc, (size_t) (rows * sizeof(MYSQL_ROWS))); end_row= row + rows; data->data= row; Loading Loading
client/mysql.cc +31 −0 Original line number Diff line number Diff line Loading @@ -2101,6 +2101,37 @@ static bool add_line(String &buffer,char *line,char *in_string, continue; } } else if (!*ml_comment && !*in_string && (end_of_line - pos) >= 10 && !my_strnncoll(charset_info, (uchar*) pos, 10, (const uchar*) "delimiter ", 10)) { // Flush previously accepted characters if (out != line) { buffer.append(line, (uint32) (out - line)); out= line; } // Flush possible comments in the buffer if (!buffer.is_empty()) { if (com_go(&buffer, 0) > 0) // < 0 is not fatal DBUG_RETURN(1); buffer.length(0); } /* Delimiter wants the get rest of the given line as argument to allow one to change ';' to ';;' and back */ buffer.append(pos); if (com_delimiter(&buffer, pos) > 0) DBUG_RETURN(1); buffer.length(0); break; } else if (!*ml_comment && !*in_string && is_prefix(pos, delimiter)) { // Found a statement. Continue parsing after the delimiter Loading
client/mysqltest.cc +258 −54 Original line number Diff line number Diff line Loading @@ -170,6 +170,8 @@ static void timer_output(void); static ulonglong timer_now(void); static ulong connection_retry_sleep= 100000; /* Microseconds */ /* 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 */ Loading Loading @@ -276,6 +278,7 @@ enum enum_commands { Q_WRITE_FILE, Q_COPY_FILE, Q_PERL, Q_DIE, Q_EXIT, Q_SKIP, Q_CHMOD_FILE, Q_APPEND_FILE, Q_CAT_FILE, Q_DIFF_FILES, Q_SEND_QUIT, Q_CHANGE_USER, Q_MKDIR, Q_RMDIR, Q_LIST_FILES, Q_LIST_FILES_WRITE_FILE, Q_LIST_FILES_APPEND_FILE, Q_SEND_SHUTDOWN, Q_SHUTDOWN_SERVER, Q_UNKNOWN, /* Unknown command. */ Loading Loading @@ -368,6 +371,9 @@ const char *command_names[]= "change_user", "mkdir", "rmdir", "list_files", "list_files_write_file", "list_files_append_file", "send_shutdown", "shutdown_server", Loading Loading @@ -654,6 +660,9 @@ 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); static int match_expected_error(struct st_command *command, unsigned int err_errno, const char *err_sqlstate); void handle_error(struct st_command*, unsigned int err_errno, const char *err_error, const char *err_sqlstate, DYNAMIC_STRING *ds); Loading Loading @@ -1010,30 +1019,26 @@ void check_command_args(struct st_command *command, DBUG_VOID_RETURN; } void handle_command_error(struct st_command *command, uint error) { DBUG_ENTER("handle_command_error"); DBUG_PRINT("enter", ("error: %d", error)); if (error != 0) { uint i; int i; if (command->abort_on_error) die("command \"%.*s\" failed with error %d", command->first_word_len, command->query, error); for (i= 0; i < command->expected_errors.count; i++) { DBUG_PRINT("info", ("expected error: %d", command->expected_errors.err[i].code.errnum)); if ((command->expected_errors.err[i].type == ERR_ERRNO) && (command->expected_errors.err[i].code.errnum == error)) i= match_expected_error(command, error, NULL); if (i >= 0) { DBUG_PRINT("info", ("command \"%.*s\" failed with expected error: %d", command->first_word_len, command->query, error)); DBUG_VOID_RETURN; } } die("command \"%.*s\" failed with wrong error: %d", command->first_word_len, command->query, error); } Loading Loading @@ -2601,8 +2606,8 @@ void do_exec(struct st_command *command) error= pclose(res_file); if (error > 0) { uint status= WEXITSTATUS(error), i; my_bool ok= 0; uint status= WEXITSTATUS(error); int i; if (command->abort_on_error) { Loading @@ -2614,19 +2619,13 @@ void do_exec(struct st_command *command) DBUG_PRINT("info", ("error: %d, status: %d", error, status)); for (i= 0; i < command->expected_errors.count; i++) { DBUG_PRINT("info", ("expected error: %d", command->expected_errors.err[i].code.errnum)); if ((command->expected_errors.err[i].type == ERR_ERRNO) && (command->expected_errors.err[i].code.errnum == status)) { ok= 1; i= match_expected_error(command, status, NULL); if (i >= 0) DBUG_PRINT("info", ("command \"%s\" failed with expected error: %d", command->first_argument, status)); } } if (!ok) else { dynstr_free(&ds_cmd); die("command \"%s\" failed with wrong error: %d", Loading Loading @@ -2976,6 +2975,126 @@ void do_rmdir(struct st_command *command) } /* SYNOPSIS get_list_files ds output ds_dirname dir to list ds_wild wild-card file pattern (can be empty) DESCRIPTION list all entries in directory (matching ds_wild if given) */ static int get_list_files(DYNAMIC_STRING *ds, const DYNAMIC_STRING *ds_dirname, const DYNAMIC_STRING *ds_wild) { uint i; MY_DIR *dir_info; FILEINFO *file; 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)))) DBUG_RETURN(1); for (i= 0; i < (uint) dir_info->number_off_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; dynstr_append(ds, file->name); dynstr_append(ds, "\n"); } my_dirend(dir_info); DBUG_RETURN(0); } /* SYNOPSIS do_list_files command called command DESCRIPTION list_files <dir_name> [<file_name>] List files and directories in directory <dir_name> (like `ls`) [Matching <file_name>, where wild-cards are allowed] */ static void do_list_files(struct st_command *command) { int error; static DYNAMIC_STRING ds_dirname; static DYNAMIC_STRING ds_wild; const struct command_arg list_files_args[] = { {"dirname", ARG_STRING, TRUE, &ds_dirname, "Directory to list"}, {"file", ARG_STRING, FALSE, &ds_wild, "Filename (incl. wildcard)"} }; DBUG_ENTER("do_list_files"); check_command_args(command, command->first_argument, list_files_args, sizeof(list_files_args)/sizeof(struct command_arg), ' '); error= get_list_files(&ds_res, &ds_dirname, &ds_wild); handle_command_error(command, error); dynstr_free(&ds_dirname); dynstr_free(&ds_wild); DBUG_VOID_RETURN; } /* SYNOPSIS do_list_files_write_file_command command called command append append file, or create new DESCRIPTION list_files_{write|append}_file <filename> <dir_name> [<match_file>] List files and directories in directory <dir_name> (like `ls`) [Matching <match_file>, where wild-cards are allowed] Note: File will be truncated if exists and append is not true. */ static void do_list_files_write_file_command(struct st_command *command, my_bool append) { int error; static DYNAMIC_STRING ds_content; static DYNAMIC_STRING ds_filename; static DYNAMIC_STRING ds_dirname; static DYNAMIC_STRING ds_wild; const struct command_arg list_files_args[] = { {"filename", ARG_STRING, TRUE, &ds_filename, "Filename for write"}, {"dirname", ARG_STRING, TRUE, &ds_dirname, "Directory to list"}, {"file", ARG_STRING, FALSE, &ds_wild, "Filename (incl. wildcard)"} }; DBUG_ENTER("do_list_files_write_file"); check_command_args(command, command->first_argument, list_files_args, sizeof(list_files_args)/sizeof(struct command_arg), ' '); init_dynamic_string(&ds_content, "", 1024, 1024); error= get_list_files(&ds_content, &ds_dirname, &ds_wild); handle_command_error(command, error); str_to_file2(ds_filename.str, ds_content.str, ds_content.length, append); dynstr_free(&ds_content); dynstr_free(&ds_filename); dynstr_free(&ds_dirname); dynstr_free(&ds_wild); DBUG_VOID_RETURN; } /* Read characters from line buffer or file. This is needed to allow my_ungetc() to buffer MAX_DELIMITER_LENGTH characters for a file Loading Loading @@ -4458,7 +4577,6 @@ void safe_connect(MYSQL* mysql, const char *name, const char *host, int port, const char *sock) { int failed_attempts= 0; static ulong connection_retry_sleep= 100000; /* Microseconds */ DBUG_ENTER("safe_connect"); while(!mysql_real_connect(mysql, host,user, pass, db, port, sock, Loading Loading @@ -4525,6 +4643,7 @@ int connect_n_handle_errors(struct st_command *command, const char* db, int port, const char* sock) { DYNAMIC_STRING *ds; int failed_attempts= 0; ds= &ds_res; Loading Loading @@ -4553,9 +4672,41 @@ int connect_n_handle_errors(struct st_command *command, dynstr_append_mem(ds, delimiter, delimiter_length); dynstr_append_mem(ds, "\n", 1); } if (!mysql_real_connect(con, host, user, pass, db, port, sock ? sock: 0, while (!mysql_real_connect(con, host, user, pass, db, port, sock ? sock: 0, CLIENT_MULTI_STATEMENTS)) { /* If we have used up all our connections check whether this is expected (by --error). If so, handle the error right away. Otherwise, give it some extra time to rule out race-conditions. If extra-time doesn't help, we have an unexpected error and must abort -- just proceeding to handle_error() when second and third chances are used up will handle that for us. There are various user-limits of which only max_user_connections and max_connections_per_hour apply at connect time. For the the second to create a race in our logic, we'd need a limits test that runs without a FLUSH for longer than an hour, so we'll stay clear of trying to work out which exact user-limit was exceeded. */ if (((mysql_errno(con) == ER_TOO_MANY_USER_CONNECTIONS) || (mysql_errno(con) == ER_USER_LIMIT_REACHED)) && (failed_attempts++ < opt_max_connect_retries)) { int i; i= match_expected_error(command, mysql_errno(con), mysql_sqlstate(con)); if (i >= 0) goto do_handle_error; /* expected error, handle */ my_sleep(connection_retry_sleep); /* unexpected error, wait */ continue; /* and give it 1 more chance */ } do_handle_error: var_set_errno(mysql_errno(con)); handle_error(command, mysql_errno(con), mysql_error(con), mysql_sqlstate(con), ds); Loading Loading @@ -6265,6 +6416,56 @@ void run_query_normal(struct st_connection *cn, struct st_command *command, } /* Check whether given error is in list of expected errors SYNOPSIS match_expected_error() PARAMETERS command the current command (and its expect-list) err_errno error number of the error that actually occurred err_sqlstate SQL-state that was thrown, or NULL for impossible (file-ops, diff, etc.) RETURNS -1 for not in list, index in list of expected errors otherwise NOTE If caller needs to know whether the list was empty, they should check command->expected_errors.count. */ static int match_expected_error(struct st_command *command, unsigned int err_errno, const char *err_sqlstate) { uint i; for (i= 0 ; (uint) i < command->expected_errors.count ; i++) { if ((command->expected_errors.err[i].type == ERR_ERRNO) && (command->expected_errors.err[i].code.errnum == err_errno)) return i; if (command->expected_errors.err[i].type == ERR_SQLSTATE) { /* NULL is quite likely, but not in conjunction with a SQL-state expect! */ if (unlikely(err_sqlstate == NULL)) die("expecting a SQL-state (%s) from query '%s' which cannot produce one...", command->expected_errors.err[i].code.sqlstate, command->query); if (strncmp(command->expected_errors.err[i].code.sqlstate, err_sqlstate, SQLSTATE_LENGTH) == 0) return i; } } return -1; } /* Handle errors which occurred during execution Loading @@ -6285,7 +6486,7 @@ void handle_error(struct st_command *command, unsigned int err_errno, const char *err_error, const char *err_sqlstate, DYNAMIC_STRING *ds) { uint i; int i; DBUG_ENTER("handle_error"); Loading @@ -6311,13 +6512,10 @@ void handle_error(struct st_command *command, DBUG_PRINT("info", ("expected_errors.count: %d", command->expected_errors.count)); for (i= 0 ; (uint) i < command->expected_errors.count ; i++) { if (((command->expected_errors.err[i].type == ERR_ERRNO) && (command->expected_errors.err[i].code.errnum == err_errno)) || ((command->expected_errors.err[i].type == ERR_SQLSTATE) && (strncmp(command->expected_errors.err[i].code.sqlstate, err_sqlstate, SQLSTATE_LENGTH) == 0))) i= match_expected_error(command, err_errno, err_sqlstate); if (i >= 0) { if (!disable_result_log) { Loading @@ -6339,7 +6537,6 @@ void handle_error(struct st_command *command, /* OK */ DBUG_VOID_RETURN; } } DBUG_PRINT("info",("i: %d expected_errors: %d", i, command->expected_errors.count)); Loading @@ -6353,7 +6550,7 @@ void handle_error(struct st_command *command, dynstr_append_mem(ds, "\n", 1); } if (i) if (command->expected_errors.count > 0) { if (command->expected_errors.err[0].type == ERR_ERRNO) die("query '%s' failed with wrong errno %d: '%s', instead of %d...", Loading Loading @@ -7375,6 +7572,13 @@ int main(int argc, char **argv) case Q_REMOVE_FILE: do_remove_file(command); break; case Q_MKDIR: do_mkdir(command); break; case Q_RMDIR: do_rmdir(command); break; case Q_LIST_FILES: do_list_files(command); break; case Q_LIST_FILES_WRITE_FILE: do_list_files_write_file_command(command, FALSE); break; case Q_LIST_FILES_APPEND_FILE: do_list_files_write_file_command(command, TRUE); break; case Q_FILE_EXIST: do_file_exist(command); break; case Q_WRITE_FILE: do_write_file(command); break; case Q_APPEND_FILE: do_append_file(command); break; Loading
configure.in +5 −5 Original line number Diff line number Diff line Loading @@ -617,19 +617,19 @@ fi AC_MSG_CHECKING(whether features provided by the user community should be included.) AC_ARG_ENABLE(community-features, AC_HELP_STRING( [--enable-community-features], [Enable additional features provided by the user community.]), [--disable-community-features], [Disable additional features provided by the user community.]), [ ENABLE_COMMUNITY_FEATURES=$enableval ], [ ENABLE_COMMUNITY_FEATURES=no ] [ ENABLE_COMMUNITY_FEATURES=yes ] ) if test "$ENABLE_COMMUNITY_FEATURES" = "yes" then AC_DEFINE([COMMUNITY_SERVER], [1], [Whether features provided by the user community should be included]) AC_MSG_RESULT([yes, community server]) AC_MSG_RESULT([yes]) else AC_MSG_RESULT([no, enterprise server]) AC_MSG_RESULT([no]) fi AC_ARG_WITH(server-suffix, Loading
include/my_sys.h +1 −0 Original line number Diff line number Diff line Loading @@ -693,6 +693,7 @@ extern char * fn_format(char * to,const char *name,const char *dir, const char *form, uint flag); extern size_t strlength(const char *str); extern void pack_dirname(char * to,const char *from); extern size_t normalize_dirname(char * to, const char *from); extern size_t unpack_dirname(char * to,const char *from); extern size_t cleanup_dirname(char * to,const char *from); extern size_t system_filename(char * to,const char *from); Loading
libmysqld/emb_qcache.cc +2 −1 Original line number Diff line number Diff line Loading @@ -447,7 +447,8 @@ int emb_load_querycache_result(THD *thd, Querycache_stream *src) if (thd->protocol == &thd->protocol_binary) { uint length; row= (MYSQL_ROWS *)alloc_root(&data->alloc, rows * sizeof(MYSQL_ROWS)); row= (MYSQL_ROWS *)alloc_root(&data->alloc, (size_t) (rows * sizeof(MYSQL_ROWS))); end_row= row + rows; data->data= row; Loading