From: konstantin Date: October 30 2007 7:32pm Subject: bk commit into 5.1 tree (kostja:1.2598) BUG#12713 List-Archive: http://lists.mysql.com/commits/36692 X-Bug: 12713 Message-Id: <20071030193226.A922511047@vajra.local> Below is the list of changes that have just been committed into a local 5.1 repository of kostja. When kostja does a push these changes will be propagated to the main repository and, within 24 hours after the push, to the public repository. For information on how to access the public repository see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html ChangeSet@stripped, 2007-10-30 22:32:20+03:00, kostja@bodhi.(none) +7 -0 In ha_delete_table, use a standard mechanism to intercept the error message and convert it to a warning instead of direct manipulation with the thread error stack. Fix a bug in handler::print_erorr when a garbled message was printed for HA_ERR_NO_SUCH_TABLE. This is a pre-requisite patch for the fix for Bug#12713 Error in a stored function called from a SELECT doesn't cause ROLLBACK of statem" sql/handler.cc@stripped, 2007-10-30 22:32:17+03:00, kostja@bodhi.(none) +45 -25 Use a standard mechanism to intercept the error message, instead of direct manipulation with thread error stack. Fix a bug when for HA_ERR_NO_SUCH_TABLE handler::print_error() would print a garbled message. sql/log.cc@stripped, 2007-10-30 22:32:17+03:00, kostja@bodhi.(none) +2 -1 Extend internal error handler interface to carry the message text. sql/mysqld.cc@stripped, 2007-10-30 22:32:17+03:00, kostja@bodhi.(none) +1 -1 Extend internal error handler interface to carry the message text. sql/sql_base.cc@stripped, 2007-10-30 22:32:17+03:00, kostja@bodhi.(none) +2 -1 Extend internal error handler interface to carry the message text. sql/sql_class.cc@stripped, 2007-10-30 22:32:17+03:00, kostja@bodhi.(none) +2 -2 Extend internal error handler interface to carry the message text. sql/sql_class.h@stripped, 2007-10-30 22:32:17+03:00, kostja@bodhi.(none) +2 -1 Extend internal error handler interface to carry the message text. sql/sql_error.cc@stripped, 2007-10-30 22:32:17+03:00, kostja@bodhi.(none) +1 -1 Extend internal error handler interface to carry the message text. diff -Nrup a/sql/handler.cc b/sql/handler.cc --- a/sql/handler.cc 2007-10-29 17:07:14 +03:00 +++ b/sql/handler.cc 2007-10-30 22:32:17 +03:00 @@ -1414,6 +1414,36 @@ static const char *check_lowercase_names } +/** + An interceptor to hijack the text of the error message without + setting an error in the thread. We need the text to present it + in the form of a warning to the user. +*/ + +struct Ha_delete_table_error_handler: public Internal_error_handler +{ +public: + virtual bool handle_error(uint sql_errno, + const char *message, + MYSQL_ERROR::enum_warning_level level, + THD *thd); + char buff[MYSQL_ERRMSG_SIZE]; +}; + + +bool +Ha_delete_table_error_handler:: +handle_error(uint sql_errno, + const char *message, + MYSQL_ERROR::enum_warning_level level, + THD *thd) +{ + /* Grab the error message */ + strmake(buff, message, sizeof(buff)-1); + return TRUE; +} + + /** @brief This should return ENOENT if the file doesn't exists. The .frm file will be deleted only if we return 0 or ENOENT @@ -1442,23 +1472,11 @@ int ha_delete_table(THD *thd, handlerton { /* Because file->print_error() use my_error() to generate the error message - we must store the error state in thd, reset it and restore it to - be able to get hold of the error message. - (We should in the future either rewrite handler::print_error() or make - a nice method of this. + we use an internal error handler to intercept it and store the text + in a temporary buffer. Later the message will be presented to user + as a warning. */ - bool is_slave_error= thd->is_slave_error; - sp_rcontext *spcont= thd->spcont; - SELECT_LEX *current_select= thd->lex->current_select; - char buff[sizeof(thd->net.last_error)]; - char new_error[sizeof(thd->net.last_error)]; - int last_errno= thd->net.last_errno; - - strmake(buff, thd->net.last_error, sizeof(buff)-1); - thd->is_slave_error= 0; - thd->spcont= NULL; - thd->lex->current_select= 0; - thd->net.last_error[0]= 0; + Ha_delete_table_error_handler ha_delete_table_error_handler; /* Fill up strucutures that print_error may need */ dummy_share.path.str= (char*) path; @@ -1471,16 +1489,18 @@ int ha_delete_table(THD *thd, handlerton file->table_share= &dummy_share; file->table= &dummy_table; + + thd->push_internal_handler(&ha_delete_table_error_handler); file->print_error(error, 0); - strmake(new_error, thd->net.last_error, sizeof(buff)-1); - /* restore thd */ - thd->is_slave_error= is_slave_error; - thd->spcont= spcont; - thd->lex->current_select= current_select; - thd->net.last_errno= last_errno; - strmake(thd->net.last_error, buff, sizeof(buff)-1); - push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error, new_error); + thd->pop_internal_handler(); + + /* + XXX: should we convert *all* errors to warnings here? + What if the error is fatal? + */ + push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error, + ha_delete_table_error_handler.buff); } delete file; DBUG_RETURN(error); @@ -2203,7 +2223,7 @@ void handler::print_error(int error, myf case HA_ERR_NO_SUCH_TABLE: my_error(ER_NO_SUCH_TABLE, MYF(0), table_share->db.str, table_share->table_name.str); - break; + DBUG_VOID_RETURN; case HA_ERR_RBR_LOGGING_FAILED: textno= ER_BINLOG_ROW_LOGGING_FAILED; break; diff -Nrup a/sql/log.cc b/sql/log.cc --- a/sql/log.cc 2007-10-20 01:20:34 +04:00 +++ b/sql/log.cc 2007-10-30 22:32:17 +03:00 @@ -72,13 +72,14 @@ public: virtual ~Silence_log_table_errors() {} - virtual bool handle_error(uint sql_errno, + virtual bool handle_error(uint sql_errno, const char *message, MYSQL_ERROR::enum_warning_level level, THD *thd); }; bool Silence_log_table_errors::handle_error(uint /* sql_errno */, + const char * /* message */, MYSQL_ERROR::enum_warning_level /* level */, THD * /* thd */) { diff -Nrup a/sql/mysqld.cc b/sql/mysqld.cc --- a/sql/mysqld.cc 2007-10-20 01:20:35 +04:00 +++ b/sql/mysqld.cc 2007-10-30 22:32:17 +03:00 @@ -2583,7 +2583,7 @@ int my_message_sql(uint error, const cha TODO: There are two exceptions mechanism (THD and sp_rcontext), this could be improved by having a common stack of handlers. */ - if (thd->handle_error(error, + if (thd->handle_error(error, str, MYSQL_ERROR::WARN_LEVEL_ERROR)) DBUG_RETURN(0); diff -Nrup a/sql/sql_base.cc b/sql/sql_base.cc --- a/sql/sql_base.cc 2007-10-30 20:08:11 +03:00 +++ b/sql/sql_base.cc 2007-10-30 22:32:17 +03:00 @@ -44,7 +44,7 @@ public: virtual ~Prelock_error_handler() {} - virtual bool handle_error(uint sql_errno, + virtual bool handle_error(uint sql_errno, const char *message, MYSQL_ERROR::enum_warning_level level, THD *thd); @@ -58,6 +58,7 @@ private: bool Prelock_error_handler::handle_error(uint sql_errno, + const char * /* message */, MYSQL_ERROR::enum_warning_level /* level */, THD * /* thd */) { diff -Nrup a/sql/sql_class.cc b/sql/sql_class.cc --- a/sql/sql_class.cc 2007-10-30 20:08:12 +03:00 +++ b/sql/sql_class.cc 2007-10-30 22:32:17 +03:00 @@ -498,12 +498,12 @@ void THD::push_internal_handler(Internal } -bool THD::handle_error(uint sql_errno, +bool THD::handle_error(uint sql_errno, const char *message, MYSQL_ERROR::enum_warning_level level) { if (m_internal_handler) { - return m_internal_handler->handle_error(sql_errno, level, this); + return m_internal_handler->handle_error(sql_errno, message, level, this); } return FALSE; // 'FALSE', as per coding style diff -Nrup a/sql/sql_class.h b/sql/sql_class.h --- a/sql/sql_class.h 2007-10-30 20:08:12 +03:00 +++ b/sql/sql_class.h 2007-10-30 22:32:17 +03:00 @@ -969,6 +969,7 @@ public: @return true if the error is handled */ virtual bool handle_error(uint sql_errno, + const char *message, MYSQL_ERROR::enum_warning_level level, THD *thd) = 0; }; @@ -1923,7 +1924,7 @@ public: @param level the error level @return true if the error is handled */ - virtual bool handle_error(uint sql_errno, + virtual bool handle_error(uint sql_errno, const char *message, MYSQL_ERROR::enum_warning_level level); /** diff -Nrup a/sql/sql_error.cc b/sql/sql_error.cc --- a/sql/sql_error.cc 2007-07-27 04:26:40 +04:00 +++ b/sql/sql_error.cc 2007-10-30 22:32:17 +03:00 @@ -137,7 +137,7 @@ MYSQL_ERROR *push_warning(THD *thd, MYSQ level= MYSQL_ERROR::WARN_LEVEL_ERROR; } - if (thd->handle_error(code, level)) + if (thd->handle_error(code, msg, level)) DBUG_RETURN(NULL); if (thd->spcont &&