diff --git a/client/mysqldump.cc b/client/mysqldump.cc index e34c16d8e423..96ccc068d1fb 100644 --- a/client/mysqldump.cc +++ b/client/mysqldump.cc @@ -5390,8 +5390,8 @@ static int do_show_slave_status(MYSQL *mysql_con) { const int n_master_host = 1; const int n_master_port = 3; const int n_master_log_file = 9; - const int n_master_log_pos = 21; - const int n_channel_name = 55; + const int n_master_log_pos = 21 + 1 /* Last_Symbolic_Errno */; + const int n_channel_name = 55 + 1 /* Last_Symbolic_Errno */; MYSQL_ROW row = mysql_fetch_row(slave); /* Since 5.7 is is possible that SSS returns multiple channels */ while (row) { diff --git a/include/my_sys.h b/include/my_sys.h index 3664e95b72b4..f18d001a0874 100644 --- a/include/my_sys.h +++ b/include/my_sys.h @@ -660,6 +660,7 @@ extern void my_osmaperr(unsigned long last_error); #endif extern const char *get_global_errmsg(int nr); +extern const char *get_global_errname(int nr); extern void wait_for_free_space(const char *filename, int errors); extern FILE *my_fopen(const char *filename, int Flags, myf MyFlags); extern FILE *my_fdopen(File fd, const char *filename, int Flags, myf MyFlags); diff --git a/include/mysys_err.h b/include/mysys_err.h index 2dace6be8909..5d34819f7530 100644 --- a/include/mysys_err.h +++ b/include/mysys_err.h @@ -27,12 +27,17 @@ @file include/mysys_err.h */ +struct my_glob_errors { + const char *errname; /* error name */ + const char *errdesc; /* error description */ +}; + #define GLOBERRS \ (EE_ERROR_LAST - EE_ERROR_FIRST + 1) /* Nr of global errors \ */ -#define EE(X) (globerrs[(X)-EE_ERROR_FIRST]) +#define EE(X) (globerrs[(X)-EE_ERROR_FIRST].errdesc) -extern const char *globerrs[]; /* my_error_messages is here */ +extern const struct my_glob_errors globerrs[]; /* my_error_messages is here */ /* Error message numbers in global map */ /* diff --git a/mysql-test/include/check-testcase.test b/mysql-test/include/check-testcase.test index 9d0484ce58dc..84c007a271fd 100644 --- a/mysql-test/include/check-testcase.test +++ b/mysql-test/include/check-testcase.test @@ -46,6 +46,7 @@ if ($tmp) { --echo Replicate_Wild_Do_Table # --echo Replicate_Wild_Ignore_Table # --echo Last_Errno 0 + --echo Last_Symbolic_Errno --echo Last_Error --echo Skip_Counter 0 --echo Exec_Source_Log_Pos # @@ -91,7 +92,7 @@ if ($tmp) { if (!$tmp) { # Note: after WL#5177, fields 13-18 shall not be filtered-out. - --replace_column 4 # 5 # 6 # 7 # 8 # 9 # 10 # 13 # 14 # 15 # 16 # 17 # 18 # 22 # 23 # 24 # 25 # 26 # 40 # 41 # 42 # 46 # 52 # 53 # 55 # 56 # + --replace_column 4 # 5 # 6 # 7 # 8 # 9 # 10 # 13 # 14 # 15 # 16 # 17 # 18 # 23 # 24 # 25 # 26 # 27 # 41 # 42 # 43 # 47 # 53 # 54 # 56 # 57 # query_vertical SHOW REPLICA STATUS; } diff --git a/mysql-test/r/disabled_replication.result b/mysql-test/r/disabled_replication.result index a3f22cd25c95..0f05dcdb59e2 100644 --- a/mysql-test/r/disabled_replication.result +++ b/mysql-test/r/disabled_replication.result @@ -1,5 +1,5 @@ SHOW SLAVE STATUS; -Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_UUID Master_Info_File SQL_Delay SQL_Remaining_Delay Slave_SQL_Running_State Master_Retry_Count Master_Bind Last_IO_Error_Timestamp Last_SQL_Error_Timestamp Master_SSL_Crl Master_SSL_Crlpath Retrieved_Gtid_Set Executed_Gtid_Set Auto_Position Replicate_Rewrite_DB Channel_Name Master_TLS_Version Master_public_key_path Get_master_public_key Network_Namespace +Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Symbolic_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master Master_SSL_Verify_Server_Cert Last_IO_Errno Last_IO_Error Last_SQL_Errno Last_SQL_Error Replicate_Ignore_Server_Ids Master_Server_Id Master_UUID Master_Info_File SQL_Delay SQL_Remaining_Delay Slave_SQL_Running_State Master_Retry_Count Master_Bind Last_IO_Error_Timestamp Last_SQL_Error_Timestamp Master_SSL_Crl Master_SSL_Crlpath Retrieved_Gtid_Set Executed_Gtid_Set Auto_Position Replicate_Rewrite_DB Channel_Name Master_TLS_Version Master_public_key_path Get_master_public_key Network_Namespace Warnings: Warning 1287 'SHOW SLAVE STATUS' is deprecated and will be removed in a future release. Please use SHOW REPLICA STATUS instead RESET SLAVE; diff --git a/mysys/errors.cc b/mysys/errors.cc index 432d0e2f5995..7ac93801f71e 100644 --- a/mysys/errors.cc +++ b/mysys/errors.cc @@ -41,106 +41,156 @@ #include "my_thread_local.h" #include "mysys_err.h" -const char *globerrs[GLOBERRS] = { - "Can't create/write to file '%s' (OS errno %d - %s)", - "Error reading file '%s' (OS errno %d - %s)", - "Error writing file '%s' (OS errno %d - %s)", - "Error on close of '%s' (OS errno %d - %s)", - "Out of memory (Needed %u bytes)", - "Error on delete of '%s' (OS errno %d - %s)", - "Error on rename of '%s' to '%s' (OS errno %d - %s)", - "", - "Unexpected EOF found when reading file '%s' (OS errno %d - %s)", - "Can't lock file (OS errno %d - %s)", - "Can't unlock file (OS errno %d - %s)", - "Can't read dir of '%s' (OS errno %d - %s)", - "Can't get stat of '%s' (OS errno %d - %s)", - "Can't change size of file (OS errno %d - %s)", - "Can't open stream from handle (OS errno %d - %s)", - "Can't get working directory (OS errno %d - %s)", - "Can't change dir to '%s' (OS errno %d - %s)", - "Warning: '%s' had %d links", - "Warning: %d files and %d streams are left open", - "Disk is full writing '%s' (OS errno %d - %s). Waiting for someone to free " - "space...", - "Can't create directory '%s' (OS errno %d - %s)", - "Character set '%s' is not a compiled character set and is not specified " - "in the '%s' file", - "Out of resources when opening file '%s' (OS errno %d - %s)", - "Can't read value for symlink '%s' (Error %d - %s)", - "Can't create symlink '%s' pointing at '%s' (Error %d - %s)", - "Error on realpath() on '%s' (Error %d - %s)", - "Can't sync file '%s' to disk (OS errno %d - %s)", - "Collation '%s' is not a compiled collation and is not specified in the " - "'%s' file", - "File '%s' not found (OS errno %d - %s)", - "File '%s' (fileno: %d) was not closed", - "Cannot change ownership of the file '%s' (OS errno %d - %s)", - "Cannot change permissions of the file '%s' (OS errno %d - %s)", - "Cannot seek in file '%s' (OS errno %d - %s)", - "Memory capacity exceeded (capacity %llu bytes)", - "Disk is full writing '%s' (OS errno %d - %s). Waiting for someone to free " - "space... Retry in %d secs. Message reprinted in %d secs.", - "Failed to create timer (OS errno %d).", - "Failed to delete timer (OS errno %d).", - "Failed to create timer queue (OS errno %d).", - "Failed to start timer notify thread.", - "Failed to create event to interrupt timer notifier thread (OS errno %d).", - "Failed to register timer event with queue (OS errno %d), exiting timer " - "notifier thread.", - "LoadLibrary(\"kernel32.dll\") failed: GetLastError returns %lu.", - "%s.", - "Failed to determine large page size.", - "Error in my_thread_global_end(): %d thread(s) did not exit.", - "Failed to create IO completion port (OS errno %d).", - "Failed to open required defaults file: %s", - "Fatal error in defaults handling. Program aborted!", - "Wrong '!%s' directive in config file %s at line %d.", - "Skipping '%s' directive as maximum include recursion level was" - " reached in file %s at line %d.", - "Wrong group definition in config file %s at line %d.", - "Found option without preceding group in config file %s at line %d.", - "%s should be readable/writable only by current user.", - "World-writable config file '%s' is ignored.", - "%s: Option '%s' was used, but is disabled.", - "%s: Option '-%c' was used, but is disabled.", - "Using a password on the command line interface can be insecure.", - "Unknown suffix '%c' used for variable '%s' (value '%s').", - "SSL error: %s from '%s'.", - "SSL error: %s.", - "%d %s.", - "Packets out of order (found %u, expected %u).", - "Unknown option to protocol: %s.", - "Failed to locate server public key '%s'.", - "Public key is not in Privacy Enhanced Mail format: '%s'.", - "%s.", - "unknown variable '%s'.", - "unknown option '--%s'.", - "%s: unknown option '-%c'.", - "%s: option '--%s' cannot take an argument.", - "%s: option '--%s' requires an argument.", - "%s: option '-%c' requires an argument.", - "%s: ignoring option '--%s' due to invalid value '%s'.", - "%s: Empty value for '%s' specified.", - "%s: Maximum value of '%s' cannot be set.", - "option '%s': boolean value '%s' was not recognized. Set to OFF.", - "%s: Error while setting value '%s' to '%s'.", - "Incorrect integer value: '%s'.", - "Incorrect unsigned integer value: '%s'.", - "option '%s': signed value %s adjusted to %s.", - "option '%s': unsigned value %s adjusted to %s.", - "option '%s': value %s adjusted to %s.", - "option '%s': value %g adjusted to %g.", - "Invalid decimal value for option '%s'.", - "%s.", - "Failed to reset before a primary ignorable character %s.", - "Failed to reset before a tertiary ignorable character %s.", - "Shift character out of range: %s.", - "Reset character out of range: %s.", - "Unknown LDML tag: '%.*s'.", - "Failed to reset before a secondary ignorable character %s.", - "Stopped processing the '%s' directive in file %s at line %d.", - "pthread_kill(thread_id:%lu, signal:%s) returned '%s'."}; +const struct my_glob_errors globerrs[GLOBERRS] = { + {"EE_CANTCREATEFILE", "Can't create/write to file '%s' (OS errno %d - %s)"}, + {"EE_READ", "Error reading file '%s' (OS errno %d - %s)"}, + {"EE_WRITE", "Error writing file '%s' (OS errno %d - %s)"}, + {"EE_BADCLOSE", "Error on close of '%s' (OS errno %d - %s)"}, + {"EE_OUTOFMEMORY", "Out of memory (Needed %u bytes)"}, + {"EE_DELETE", "Error on delete of '%s' (OS errno %d - %s)"}, + {"EE_LINK", "Error on rename of '%s' to '%s' (OS errno %d - %s)"}, + {"", ""}, + {"EE_EOFERR", + "Unexpected EOF found when reading file '%s' (OS errno %d - %s)"}, + {"EE_CANTLOCK", "Can't lock file (OS errno %d - %s)"}, + {"EE_CANTUNLOCK", "Can't unlock file (OS errno %d - %s)"}, + {"EE_DIR", "Can't read dir of '%s' (OS errno %d - %s)"}, + {"EE_STAT", "Can't get stat of '%s' (OS errno %d - %s)"}, + {"EE_CANT_CHSIZE", "Can't change size of file (OS errno %d - %s)"}, + {"EE_CANT_OPEN_STREAM", "Can't open stream from handle (OS errno %d - %s)"}, + {"EE_GETWD", "Can't get working directory (OS errno %d - %s)"}, + {"EE_SETWD", "Can't change dir to '%s' (OS errno %d - %s)"}, + {"EE_LINK_WARNING", "Warning: '%s' had %d links"}, + {"EE_OPEN_WARNING", "Warning: %d files and %d streams are left open"}, + {"EE_DISK_FULL", + "Disk is full writing '%s' (OS errno %d - %s). Waiting for someone to " + "free space..."}, + {"EE_CANT_MKDIR", "Can't create directory '%s' (OS errno %d - %s)"}, + {"EE_UNKNOWN_CHARSET", + "Character set '%s' is not a compiled character set and is not specified " + "in the '%s' file"}, + {"EE_OUT_OF_FILERESOURCES", + "Out of resources when opening file '%s' (OS errno %d - %s)"}, + {"EE_CANT_READLINK", "Can't read value for symlink '%s' (Error %d - %s)"}, + {"EE_CANT_SYMLINK", + "Can't create symlink '%s' pointing at '%s' (Error %d - %s)"}, + {"EE_REALPATH", "Error on realpath() on '%s' (Error %d - %s)"}, + {"EE_SYNC", "Can't sync file '%s' to disk (OS errno %d - %s)"}, + {"EE_UNKNOWN_COLLATION", + "Collation '%s' is not a compiled collation and is not specified in the " + "'%s' file"}, + {"EE_FILENOTFOUND", "File '%s' not found (OS errno %d - %s)"}, + {"EE_FILE_NOT_CLOSED", "File '%s' (fileno: %d) was not closed"}, + {"EE_CHANGE_OWNERSHIP", + "Cannot change ownership of the file '%s' (OS errno %d - %s)"}, + {"EE_CHANGE_PERMISSIONS", + "Cannot change permissions of the file '%s' (OS errno %d - %s)"}, + {"EE_CANT_SEEK", "Cannot seek in file '%s' (OS errno %d - %s)"}, + {"EE_CAPACITY_EXCEEDED", "Memory capacity exceeded (capacity %llu bytes)"}, + {"EE_DISK_FULL_WITH_RETRY_MSG", + "Disk is full writing '%s' (OS errno %d - %s). Waiting for someone to " + "free space... Retry in %d secs. Message reprinted in %d secs."}, + {"EE_FAILED_TO_CREATE_TIMER", "Failed to create timer (OS errno %d)."}, + {"EE_FAILED_TO_DELETE_TIMER", "Failed to delete timer (OS errno %d)."}, + {"EE_FAILED_TO_CREATE_TIMER_QUEUE", + "Failed to create timer queue (OS errno %d)."}, + {"EE_FAILED_TO_START_TIMER_NOTIFY_THREAD", + "Failed to start timer notify thread."}, + {"EE_FAILED_TO_CREATE_TIMER_NOTIFY_THREAD_INTERRUPT_EVENT", + "Failed to create event to interrupt timer notifier thread (OS errno " + "%d)."}, + {"EE_EXITING_TIMER_NOTIFY_THREAD", + "Failed to register timer event with queue (OS errno %d), exiting timer " + "notifier thread."}, + {"EE_WIN_LIBRARY_LOAD_FAILED", + "LoadLibrary(\"kernel32.dll\") failed: GetLastError returns %lu."}, + {"EE_WIN_RUN_TIME_ERROR_CHECK", "%s."}, + {"EE_FAILED_TO_DETERMINE_LARGE_PAGE_SIZE", + "Failed to determine large page size."}, + {"EE_FAILED_TO_KILL_ALL_THREADS", + "Error in my_thread_global_end(): %d thread(s) did not exit."}, + {"EE_FAILED_TO_CREATE_IO_COMPLETION_PORT", + "Failed to create IO completion port (OS errno %d)."}, + {"EE_FAILED_TO_OPEN_DEFAULTS_FILE", + "Failed to open required defaults file: %s"}, + {"EE_FAILED_TO_HANDLE_DEFAULTS_FILE", + "Fatal error in defaults handling. Program aborted!"}, + {"EE_WRONG_DIRECTIVE_IN_CONFIG_FILE", + "Wrong '!%s' directive in config file %s at line %d."}, + {"EE_SKIPPING_DIRECTIVE_DUE_TO_MAX_INCLUDE_RECURSION", + "Skipping '%s' directive as maximum include recursion level was" + " reached in file %s at line %d."}, + {"EE_INCORRECT_GRP_DEFINITION_IN_CONFIG_FILE", + "Wrong group definition in config file %s at line %d."}, + {"EE_OPTION_WITHOUT_GRP_IN_CONFIG_FILE", + "Found option without preceding group in config file %s at line %d."}, + {"EE_CONFIG_FILE_PERMISSION_ERROR", + "%s should be readable/writable only by current user."}, + {"EE_IGNORE_WORLD_WRITABLE_CONFIG_FILE", + "World-writable config file '%s' is ignored."}, + {"EE_USING_DISABLED_OPTION", "%s: Option '%s' was used, but is disabled."}, + {"EE_USING_DISABLED_SHORT_OPTION", + "%s: Option '-%c' was used, but is disabled."}, + {"EE_USING_PASSWORD_ON_CLI_IS_INSECURE", + "Using a password on the command line interface can be insecure."}, + {"EE_UNKNOWN_SUFFIX_FOR_VARIABLE", + "Unknown suffix '%c' used for variable '%s' (value '%s')."}, + {"EE_SSL_ERROR_FROM_FILE", "SSL error: %s from '%s'."}, + {"EE_SSL_ERROR", "SSL error: %s."}, + {"EE_NET_SEND_ERROR_IN_BOOTSTRAP", "%d %s."}, + {"EE_PACKETS_OUT_OF_ORDER", + "Packets out of order (found %u, expected %u)."}, + {"EE_UNKNOWN_PROTOCOL_OPTION", "Unknown option to protocol: %s."}, + {"EE_FAILED_TO_LOCATE_SERVER_PUBLIC_KEY", + "Failed to locate server public key '%s'."}, + {"EE_PUBLIC_KEY_NOT_IN_PEM_FORMAT", + "Public key is not in Privacy Enhanced Mail format: '%s'."}, + {"EE_DEBUG_INFO", "%s."}, + {"EE_UNKNOWN_VARIABLE", "unknown variable '%s'."}, + {"EE_UNKNOWN_OPTION", "unknown option '--%s'."}, + {"EE_UNKNOWN_SHORT_OPTION", "%s: unknown option '-%c'."}, + {"EE_OPTION_WITHOUT_ARGUMENT", + "%s: option '--%s' cannot take an argument."}, + {"EE_OPTION_REQUIRES_ARGUMENT", "%s: option '--%s' requires an argument."}, + {"EE_SHORT_OPTION_REQUIRES_ARGUMENT", + "%s: option '-%c' requires an argument."}, + {"EE_OPTION_IGNORED_DUE_TO_INVALID_VALUE", + "%s: ignoring option '--%s' due to invalid value '%s'."}, + {"EE_OPTION_WITH_EMPTY_VALUE", "%s: Empty value for '%s' specified."}, + {"EE_FAILED_TO_ASSIGN_MAX_VALUE_TO_OPTION", + "%s: Maximum value of '%s' cannot be set."}, + {"EE_INCORRECT_BOOLEAN_VALUE_FOR_OPTION", + "option '%s': boolean value '%s' was not recognized. Set to OFF."}, + {"EE_FAILED_TO_SET_OPTION_VALUE", + "%s: Error while setting value '%s' to '%s'."}, + {"EE_INCORRECT_INT_VALUE_FOR_OPTION", "Incorrect integer value: '%s'."}, + {"EE_INCORRECT_UINT_VALUE_FOR_OPTION", + "Incorrect unsigned integer value: '%s'."}, + {"EE_ADJUSTED_SIGNED_VALUE_FOR_OPTION", + "option '%s': signed value %s adjusted to %s."}, + {"EE_ADJUSTED_UNSIGNED_VALUE_FOR_OPTION", + "option '%s': unsigned value %s adjusted to %s."}, + {"EE_ADJUSTED_ULONGLONG_VALUE_FOR_OPTION", + "option '%s': value %s adjusted to %s."}, + {"EE_ADJUSTED_DOUBLE_VALUE_FOR_OPTION", + "option '%s': value %g adjusted to %g."}, + {"EE_INVALID_DECIMAL_VALUE_FOR_OPTION", + "Invalid decimal value for option '%s'."}, + {"EE_COLLATION_PARSER_ERROR", "%s."}, + {"EE_FAILED_TO_RESET_BEFORE_PRIMARY_IGNORABLE_CHAR", + "Failed to reset before a primary ignorable character %s."}, + {"EE_FAILED_TO_RESET_BEFORE_TERTIARY_IGNORABLE_CHAR", + "Failed to reset before a territory ignorable character %s."}, + {"EE_SHIFT_CHAR_OUT_OF_RANGE", "Shift character out of range: %s."}, + {"EE_RESET_CHAR_OUT_OF_RANGE", "Reset character out of range: %s."}, + {"EE_UNKNOWN_LDML_TAG", "Unknown LDML tag: '%.*s'."}, + {"EE_FAILED_TO_RESET_BEFORE_SECONDARY_IGNORABLE_CHAR", + "Failed to reset before a secondary ignorable character %s."}, + {"EE_FAILED_PROCESSING_DIRECTIVE", + "Stopped processing the '%s' directive in file %s at line %d."}, + {"EE_PTHREAD_KILL_FAILED", + "pthread_kill(thread_id:%lu, signal:%s) returned '%s'."}, +}; /* We cannot call my_error/my_printf_error here in this function. @@ -173,4 +223,10 @@ void wait_for_free_space(const char *filename, int errors) { } while (--time_to_sleep > 0 && !is_killed_hook(nullptr)); } -const char *get_global_errmsg(int nr) { return globerrs[nr - EE_ERROR_FIRST]; } +const char *get_global_errname(int nr) { + return globerrs[nr - EE_ERROR_FIRST].errname; +} + +const char *get_global_errmsg(int nr) { + return globerrs[nr - EE_ERROR_FIRST].errdesc; +} diff --git a/sql/rpl_replica.cc b/sql/rpl_replica.cc index 3c5ba9c4412e..c61347b3f62c 100644 --- a/sql/rpl_replica.cc +++ b/sql/rpl_replica.cc @@ -99,6 +99,7 @@ #include "mysql/thread_type.h" #include "mysql_com.h" #include "mysqld_error.h" +#include "mysys_err.h" #include "pfs_thread_provider.h" #include "prealloced_array.h" #include "sql-common/net_ns.h" @@ -3352,6 +3353,7 @@ static void show_slave_status_metadata(mem_root_deque *field_list, field_list->push_back( new Item_empty_string("Replicate_Wild_Ignore_Table", 28)); field_list->push_back(new Item_return_int("Last_Errno", 4, MYSQL_TYPE_LONG)); + field_list->push_back(new Item_empty_string("Last_Symbolic_Errno", 20)); field_list->push_back(new Item_empty_string("Last_Error", 20)); field_list->push_back( new Item_return_int("Skip_Counter", 10, MYSQL_TYPE_LONG)); @@ -3507,6 +3509,17 @@ static bool show_slave_status_send_data(THD *thd, Master_info *mi, protocol->store(&tmp); protocol->store(mi->rli->last_error().number); + + if (mi->rli->last_error().number == 0) { + protocol->store("", &my_charset_bin); + } else if (mi->rli->last_error().number >= EE_ERROR_FIRST && + mi->rli->last_error().number <= EE_ERROR_LAST) { + protocol->store(get_global_errname(mi->rli->last_error().number), + &my_charset_bin); + } else { + protocol->store("regular sql errno", &my_charset_bin); + } + protocol->store(mi->rli->last_error().message, &my_charset_bin); protocol->store((uint32)mi->rli->slave_skip_counter); protocol->store((ulonglong)mi->rli->get_group_master_log_pos_info()); diff --git a/sql/rpl_rli_pdb.cc b/sql/rpl_rli_pdb.cc index 4b1e9c4ffdc4..bb09434c02cb 100644 --- a/sql/rpl_rli_pdb.cc +++ b/sql/rpl_rli_pdb.cc @@ -1567,33 +1567,62 @@ void Slave_worker::do_report(loglevel level, int err_code, const char *msg, gtid_next->to_string(global_sid_map, buff_gtid, true); + if (is_group_replication_applier_channel) { + snprintf(buff_coord, sizeof(buff_coord), + "Worker %u failed executing transaction '%s'", internal_id, + buff_gtid); + } else { + snprintf(buff_coord, sizeof(buff_coord), + "Worker %u failed executing transaction '%s' at " + "source log %s, end_log_pos %llu", + internal_id, buff_gtid, log_name, log_pos); + } + + /* + Error reporting by the worker. The worker updates its error fields as well + as reports the error in the log. + */ + this->va_report(level, err_code, buff_coord, msg, args); + if (level == ERROR_LEVEL && (!has_temporary_error(thd, err_code) || thd->get_transaction()->cannot_safely_rollback( Transaction_ctx::SESSION))) { char coordinator_errmsg[MAX_SLAVE_ERRMSG]; + const char *err_msg = nullptr; + + mysql_mutex_lock(&err_lock); + if (m_last_error.number) { + /* We know for sure there is an valid error */ + err_msg = m_last_error.message; + } else { + /* Fallback to generic error message just in case */ + err_msg = buff_coord; + } if (is_group_replication_applier_channel) { - snprintf(coordinator_errmsg, MAX_SLAVE_ERRMSG, - "Coordinator stopped because there were error(s) in the " - "worker(s). " - "The most recent failure being: Worker %u failed executing " - "transaction '%s'. See error log and/or " - "performance_schema.replication_applier_status_by_worker " - "table for " - "more details about this failure or others, if any.", - internal_id, buff_gtid); + my_snprintf_8bit( + nullptr, coordinator_errmsg, MAX_SLAVE_ERRMSG, + "Coordinator stopped because there were error(s) in the " + "worker(s). " + "The most recent failure being: %s; " + "See error log and/or " + "performance_schema.replication_applier_status_by_worker " + "table for " + "more details about this failure or others, if any.", + err_msg); } else { - snprintf(coordinator_errmsg, MAX_SLAVE_ERRMSG, - "Coordinator stopped because there were error(s) in the " - "worker(s). " - "The most recent failure being: Worker %u failed executing " - "transaction '%s' at source log %s, end_log_pos %llu. " - "See error log and/or " - "performance_schema.replication_applier_status_by_worker " - "table for " - "more details about this failure or others, if any.", - internal_id, buff_gtid, log_name, log_pos); + my_snprintf_8bit( + nullptr, coordinator_errmsg, MAX_SLAVE_ERRMSG, + "Coordinator stopped because there were error(s) in the " + "worker(s). " + "The most recent failure being: %s; " + "See error log and/or " + "performance_schema.replication_applier_status_by_worker " + "table for " + "more details about this failure or others, if any.", + err_msg); } + mysql_mutex_unlock(&err_lock); /* We want to update the errors in coordinator as well as worker. @@ -1605,23 +1634,6 @@ void Slave_worker::do_report(loglevel level, int err_code, const char *msg, */ c_rli->fill_coord_err_buf(level, err_code, coordinator_errmsg); } - - if (is_group_replication_applier_channel) { - snprintf(buff_coord, sizeof(buff_coord), - "Worker %u failed executing transaction '%s'", internal_id, - buff_gtid); - } else { - snprintf(buff_coord, sizeof(buff_coord), - "Worker %u failed executing transaction '%s' at " - "source log %s, end_log_pos %llu", - internal_id, buff_gtid, log_name, log_pos); - } - - /* - Error reporting by the worker. The worker updates its error fields as well - as reports the error in the log. - */ - this->va_report(level, err_code, buff_coord, msg, args); } #ifndef NDEBUG diff --git a/utilities/perror.cc b/utilities/perror.cc index 7811149d5ecf..30aaa05bfefa 100644 --- a/utilities/perror.cc +++ b/utilities/perror.cc @@ -145,7 +145,7 @@ int get_ER_error_msg_by_code(uint code, const char **name_ptr, /* handle "global errors" */ if ((code >= EE_ERROR_FIRST) && (code <= EE_ERROR_LAST)) { *name_ptr = nullptr; - *msg_ptr = globerrs[code - EE_ERROR_FIRST]; + *msg_ptr = EE(code); return 1; }