#At file:///home/malff/BZR-TREE/mysql-6.0-wl2110-review/
2704 Marc Alff 2008-10-03
WL#2110 (Stored Procedures: Implement SIGNAL)
WL#2265 (Stored Procedures: Implement RESIGNAL)
Bug#11661 (Raising Exceptions from within stored procedures: Support for
SIGNAL statement)
Fixed review comments related to memory management.
- Changed all the handle_condition() methods to return a SQL_condition
as *output*, instead of *input*.
The logic now find first where the condition should be written to,
and then the caller writes the extra attributes in place.
This change removes the need for SQL_condition::deep_copy().
Also, when a condition is dropped (Internal handlers, warn_list full),
this saves some CPU cycle.
- Removed SQL_condition::deep_copy()
- Removed sp_rcontext::m_cond_root, and reverted related changes.
- Adjusted the code that raises a condition according to the new paradigm.
modified:
sql/handler.cc
sql/log.cc
sql/sp.cc
sql/sp_head.cc
sql/sp_rcontext.cc
sql/sp_rcontext.h
sql/sql_acl.cc
sql/sql_base.cc
sql/sql_class.cc
sql/sql_class.h
sql/sql_fixstring.cc
sql/sql_fixstring.h
sql/sql_signal.cc
sql/unireg.cc
=== modified file 'sql/handler.cc'
--- a/sql/handler.cc 2008-09-29 15:14:27 +0000
+++ b/sql/handler.cc 2008-10-03 21:35:16 +0000
@@ -1819,17 +1819,28 @@ const char *get_canonical_filename(handl
struct Ha_delete_table_error_handler: public Internal_error_handler
{
public:
- virtual bool handle_condition(THD *thd, const SQL_condition *cond);
+ virtual bool handle_condition(THD *thd,
+ uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ SQL_condition ** cond_hdl);
char buff[MYSQL_ERRMSG_SIZE];
};
bool
Ha_delete_table_error_handler::
-handle_condition(THD *, const SQL_condition *cond)
+handle_condition(THD *,
+ uint,
+ const char*,
+ MYSQL_ERROR::enum_warning_level,
+ const char* msg,
+ SQL_condition ** cond_hdl)
{
+ *cond_hdl= NULL;
/* Grab the error message */
- strmake(buff, cond->get_message_text(), sizeof(buff)-1);
+ strmake(buff, msg, sizeof(buff)-1);
return TRUE;
}
=== modified file 'sql/log.cc'
--- a/sql/log.cc 2008-09-29 15:14:27 +0000
+++ b/sql/log.cc 2008-10-03 21:35:16 +0000
@@ -82,14 +82,25 @@ public:
virtual ~Silence_log_table_errors() {}
- virtual bool handle_condition(THD *thd, const SQL_condition *cond);
+ virtual bool handle_condition(THD *thd,
+ uint sql_errno,
+ const char* sql_state,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ SQL_condition ** cond_hdl);
const char *message() const { return m_message; }
};
bool
-Silence_log_table_errors::handle_condition(THD *, const SQL_condition *cond)
+Silence_log_table_errors::handle_condition(THD *,
+ uint,
+ const char*,
+ MYSQL_ERROR::enum_warning_level,
+ const char* msg,
+ SQL_condition ** cond_hdl)
{
- strmake(m_message, cond->get_message_text(), sizeof(m_message)-1);
+ *cond_hdl= NULL;
+ strmake(m_message, msg, sizeof(m_message)-1);
return TRUE;
}
=== modified file 'sql/sp.cc'
--- a/sql/sp.cc 2008-08-27 22:14:03 +0000
+++ b/sql/sp.cc 2008-10-03 21:35:16 +0000
@@ -496,15 +496,26 @@ db_find_routine(THD *thd, int type, sp_n
struct Silence_deprecated_warning : public Internal_error_handler
{
public:
- virtual bool handle_condition(THD *thd, const SQL_condition *cond);
+ virtual bool handle_condition(THD *thd,
+ uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ SQL_condition ** cond_hdl);
};
bool
-Silence_deprecated_warning::handle_condition(THD *thd,
- const SQL_condition *cond)
-{
- if (cond->get_sql_errno() == ER_WARN_DEPRECATED_SYNTAX &&
- cond->get_level() == MYSQL_ERROR::WARN_LEVEL_WARN)
+Silence_deprecated_warning::handle_condition(
+ THD *,
+ uint sql_errno,
+ const char*,
+ MYSQL_ERROR::enum_warning_level level,
+ const char*,
+ SQL_condition ** cond_hdl)
+{
+ *cond_hdl= NULL;
+ if (sql_errno == ER_WARN_DEPRECATED_SYNTAX &&
+ level == MYSQL_ERROR::WARN_LEVEL_WARN)
return TRUE;
return FALSE;
=== modified file 'sql/sp_head.cc'
--- a/sql/sp_head.cc 2008-10-01 18:27:26 +0000
+++ b/sql/sp_head.cc 2008-10-03 21:35:16 +0000
@@ -1529,7 +1529,7 @@ sp_head::execute_trigger(THD *thd,
init_sql_alloc(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0);
thd->set_n_backup_active_arena(&call_arena, &backup_arena);
- if (!(nctx= new sp_rcontext(mem_root, m_pcont, 0, octx)) ||
+ if (!(nctx= new sp_rcontext(m_pcont, 0, octx)) ||
nctx->init(thd))
{
err_status= TRUE;
@@ -1646,7 +1646,7 @@ sp_head::execute_function(THD *thd, Item
init_sql_alloc(&call_mem_root, MEM_ROOT_BLOCK_SIZE, 0);
thd->set_n_backup_active_arena(&call_arena, &backup_arena);
- if (!(nctx= new sp_rcontext(mem_root, m_pcont, return_value_fld, octx)) ||
+ if (!(nctx= new sp_rcontext(m_pcont, return_value_fld, octx)) ||
nctx->init(thd))
{
thd->restore_active_arena(&call_arena, &backup_arena);
@@ -1850,7 +1850,7 @@ sp_head::execute_procedure(THD *thd, Lis
save_spcont= octx= thd->spcont;
if (! octx)
{ // Create a temporary old context
- if (!(octx= new sp_rcontext(mem_root, m_pcont, NULL, octx)) ||
+ if (!(octx= new sp_rcontext(m_pcont, NULL, octx)) ||
octx->init(thd))
{
delete octx; /* Delete octx if it was init() that failed. */
@@ -1866,7 +1866,7 @@ sp_head::execute_procedure(THD *thd, Lis
thd->spcont->callers_arena= thd;
}
- if (!(nctx= new sp_rcontext(mem_root, m_pcont, NULL, octx)) ||
+ if (!(nctx= new sp_rcontext(m_pcont, NULL, octx)) ||
nctx->init(thd))
{
delete nctx; /* Delete nctx if it was init() that failed. */
=== modified file 'sql/sp_rcontext.cc'
--- a/sql/sp_rcontext.cc 2008-10-01 18:27:26 +0000
+++ b/sql/sp_rcontext.cc 2008-10-03 21:35:16 +0000
@@ -29,7 +29,7 @@
#include "sp_pcontext.h"
-sp_rcontext::sp_rcontext(MEM_ROOT *cond_root, sp_pcontext *root_parsing_ctx,
+sp_rcontext::sp_rcontext(sp_pcontext *root_parsing_ctx,
Field *return_value_fld,
sp_rcontext *prev_runtime_ctx)
:end_partial_result_set(FALSE),
@@ -45,8 +45,7 @@ sp_rcontext::sp_rcontext(MEM_ROOT *cond_
m_hfound(-1),
m_ccount(0),
m_case_expr_holders(0),
- m_prev_runtime_ctx(prev_runtime_ctx),
- m_cond_root(cond_root)
+ m_prev_runtime_ctx(prev_runtime_ctx)
{
}
@@ -71,17 +70,22 @@ sp_rcontext::~sp_rcontext()
bool sp_rcontext::init(THD *thd)
{
uint handler_count= m_root_parsing_ctx->max_handler_index();
+ uint i;
in_sub_stmt= thd->in_sub_stmt;
if (init_var_table(thd) || init_var_items())
return TRUE;
+ if (!(m_raised_conditions= new (thd->mem_root) SQL_condition[handler_count]))
+ return TRUE;
+
+ for (i= 0; i<handler_count; i++)
+ m_raised_conditions[i].init(thd->mem_root);
+
return
!(m_handler=
(sp_handler_t*)thd->alloc(handler_count * sizeof(sp_handler_t))) ||
- !(m_raised_conditions=
- (SQL_condition**)thd->calloc(handler_count * sizeof(SQL_condition*))) ||
!(m_hstack=
(uint*)thd->alloc(handler_count * sizeof(uint))) ||
!(m_in_handler=
@@ -198,15 +202,19 @@ sp_rcontext::set_return_value(THD *thd,
*/
bool
-sp_rcontext::find_handler(THD *thd, const SQL_condition *cond)
+sp_rcontext::find_handler(THD *thd,
+ uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ SQL_condition ** cond_hdl)
{
if (m_hfound >= 0)
- return 1; // Already got one
-
- uint sql_errno= cond->get_sql_errno();
- MYSQL_ERROR::enum_warning_level level= cond->get_level();
+ {
+ *cond_hdl= NULL;
+ return TRUE; // Already got one
+ }
- const char *sqlstate= cond->get_sqlstate();
int i= m_hcount, found= -1;
/*
@@ -270,18 +278,26 @@ sp_rcontext::find_handler(THD *thd, cons
*/
if (m_prev_runtime_ctx && IS_EXCEPTION_CONDITION(sqlstate) &&
level == MYSQL_ERROR::WARN_LEVEL_ERROR)
- return m_prev_runtime_ctx->find_handler(thd, cond);
+ return m_prev_runtime_ctx->find_handler(thd,
+ sql_errno,
+ sqlstate,
+ level,
+ msg,
+ cond_hdl);
+ *cond_hdl= NULL;
return FALSE;
}
m_hfound= found;
- SQL_condition *raised;
- raised= SQL_condition::deep_copy(thd, m_cond_root, cond) ;
+ SQL_condition *raised= NULL;
DBUG_ASSERT(m_hfound >= 0);
DBUG_ASSERT((uint) m_hfound < m_root_parsing_ctx->max_handler_index());
- m_raised_conditions[m_hfound]= raised;
+ raised= & m_raised_conditions[m_hfound];
+ raised->clear();
+ raised->set(sql_errno, sqlstate, level, msg);
+ *cond_hdl= raised;
return TRUE;
}
@@ -307,22 +323,25 @@ sp_rcontext::find_handler(THD *thd, cons
FALSE if no handler was found.
*/
bool
-sp_rcontext::handle_condition(THD *thd, const SQL_condition *cond)
+sp_rcontext::handle_condition(THD *thd,
+ uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ SQL_condition ** cond_hdl)
{
+ MYSQL_ERROR::enum_warning_level elevated_level= level;
+
+
/* Depending on the sql_mode of execution,
warnings may be considered errors */
- if ((cond->m_level == MYSQL_ERROR::WARN_LEVEL_WARN) &&
+ if ((level == MYSQL_ERROR::WARN_LEVEL_WARN) &&
thd->really_abort_on_warning())
{
- SQL_condition elevated_cond(thd->mem_root);
- elevated_cond.set(thd, cond->m_sql_errno,
- cond->get_message_text(),
- MYSQL_ERROR::WARN_LEVEL_ERROR,
- MYF(0));
- return find_handler(thd, & elevated_cond);
+ elevated_level= MYSQL_ERROR::WARN_LEVEL_ERROR;
}
- return find_handler(thd, cond);
+ return find_handler(thd, sql_errno, sqlstate, elevated_level, msg, cond_hdl);
}
void
@@ -412,9 +431,7 @@ sp_rcontext::exit_handler()
DBUG_ENTER("sp_rcontext::exit_handler");
DBUG_ASSERT(m_ihsp);
uint hindex= m_in_handler[m_ihsp-1].index;
- DBUG_ASSERT(m_raised_conditions[hindex]);
- delete m_raised_conditions[hindex];
- m_raised_conditions[hindex]= NULL;
+ m_raised_conditions[hindex].clear();
m_ihsp-= 1;
DBUG_PRINT("info", ("m_ihsp: %d", m_ihsp));
DBUG_VOID_RETURN;
@@ -426,8 +443,7 @@ sp_rcontext::raised_condition() const
if (m_ihsp > 0)
{
uint hindex= m_in_handler[m_ihsp - 1].index;
- SQL_condition *raised= m_raised_conditions[hindex];
- DBUG_ASSERT(raised);
+ SQL_condition *raised= & m_raised_conditions[hindex];
return raised;
}
=== modified file 'sql/sp_rcontext.h'
--- a/sql/sp_rcontext.h 2008-10-01 18:27:26 +0000
+++ b/sql/sp_rcontext.h 2008-10-03 21:35:16 +0000
@@ -99,8 +99,8 @@ class sp_rcontext : public Sql_alloc
sp_head *sp;
#endif
- sp_rcontext(MEM_ROOT *cond_root, sp_pcontext *root_parsing_ctx,
- Field *return_value_fld, sp_rcontext *prev_runtime_ctx);
+ sp_rcontext(sp_pcontext *root_parsing_ctx, Field *return_value_fld,
+ sp_rcontext *prev_runtime_ctx);
bool init(THD *thd);
~sp_rcontext();
@@ -129,10 +129,20 @@ class sp_rcontext : public Sql_alloc
// Returns 1 if a handler was found, 0 otherwise.
bool
- find_handler(THD *thd, const SQL_condition *cond);
+ find_handler(THD *thd,
+ uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ SQL_condition ** cond_hdl);
// If there is an error handler for this error, handle it and return TRUE.
- bool handle_condition(THD *thd, const SQL_condition *cond);
+ bool handle_condition(THD *thd,
+ uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ SQL_condition ** cond_hdl);
// Returns handler type and sets *ip to location if one was found
@@ -240,7 +250,7 @@ private:
SQL conditions caught by each handler.
This is an array indexed by handler index.
*/
- SQL_condition ** m_raised_conditions;
+ SQL_condition * m_raised_conditions;
uint m_hcount; // Stack pointer for m_handler
uint *m_hstack; // Return stack for continue handlers
@@ -258,9 +268,6 @@ private:
/* Previous runtime context (NULL if none) */
sp_rcontext *m_prev_runtime_ctx;
- /** Memory root to use for SQL_condition caught by handlers. */
- MEM_ROOT *m_cond_root;
-
private:
bool init_var_table(THD *thd);
bool init_var_items();
=== modified file 'sql/sql_acl.cc'
--- a/sql/sql_acl.cc 2008-09-29 15:14:27 +0000
+++ b/sql/sql_acl.cc 2008-10-03 21:35:16 +0000
@@ -6132,7 +6132,12 @@ public:
virtual ~Silence_routine_definer_errors()
{}
- virtual bool handle_condition(THD *thd, const SQL_condition *cond);
+ virtual bool handle_condition(THD *thd,
+ uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ SQL_condition ** cond_hdl);
bool has_errors() { return is_grave; }
@@ -6141,17 +6146,23 @@ private:
};
bool
-Silence_routine_definer_errors::handle_condition(THD *thd,
- const SQL_condition *cond)
+Silence_routine_definer_errors::handle_condition(
+ THD *thd,
+ uint sql_errno,
+ const char*,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ SQL_condition ** cond_hdl)
{
- if (cond->get_level() == MYSQL_ERROR::WARN_LEVEL_ERROR)
+ *cond_hdl= NULL;
+ if (level == MYSQL_ERROR::WARN_LEVEL_ERROR)
{
- switch (cond->get_sql_errno())
+ switch (sql_errno)
{
case ER_NONEXISTING_PROC_GRANT:
/* Convert the error into a warning. */
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
- cond->get_sql_errno(), cond->get_message_text());
+ sql_errno, msg);
return TRUE;
default:
is_grave= TRUE;
=== modified file 'sql/sql_base.cc'
--- a/sql/sql_base.cc 2008-10-01 18:27:26 +0000
+++ b/sql/sql_base.cc 2008-10-03 21:35:16 +0000
@@ -45,7 +45,12 @@ public:
virtual ~Prelock_error_handler() {}
- virtual bool handle_condition(THD *thd, const SQL_condition *cond);
+ virtual bool handle_condition(THD *thd,
+ uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ SQL_condition ** cond_hdl);
bool safely_trapped_errors();
@@ -56,9 +61,15 @@ private:
bool
-Prelock_error_handler::handle_condition(THD *, const SQL_condition *cond)
+Prelock_error_handler::handle_condition(THD *,
+ uint sql_errno,
+ const char*,
+ MYSQL_ERROR::enum_warning_level,
+ const char*,
+ SQL_condition ** cond_hdl)
{
- if (cond->get_sql_errno() == ER_NO_SUCH_TABLE)
+ *cond_hdl= NULL;
+ if (sql_errno == ER_NO_SUCH_TABLE)
{
m_handled_errors++;
return TRUE;
=== modified file 'sql/sql_class.cc'
--- a/sql/sql_class.cc 2008-10-01 18:27:26 +0000
+++ b/sql/sql_class.cc 2008-10-03 21:35:16 +0000
@@ -695,14 +695,24 @@ void THD::push_internal_handler(Internal
}
-bool THD::handle_condition(const SQL_condition *cond)
+bool THD::handle_condition(uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ SQL_condition ** cond_hdl)
{
if (m_internal_handler)
{
- return m_internal_handler->handle_condition(this, cond);
+ return m_internal_handler->handle_condition(this,
+ sql_errno,
+ sqlstate,
+ level,
+ msg,
+ cond_hdl);
}
- return FALSE; // 'FALSE', as per coding style
+ *cond_hdl= NULL;
+ return FALSE;
}
@@ -712,111 +722,144 @@ void THD::pop_internal_handler()
m_internal_handler= NULL;
}
-void THD::raise_error(uint code, const char *str, myf MyFlags)
+void THD::raise_error(uint sql_errno, const char *str, myf MyFlags)
{
- SQL_condition cond(this->mem_root);
- cond.set(this, code, str, MYSQL_ERROR::WARN_LEVEL_ERROR, MyFlags);
- raise_condition(& cond);
+ const char* sqlstate= mysql_errno_to_sqlstate(sql_errno);
+ (void) raise_condition(sql_errno,
+ sqlstate,
+ MYSQL_ERROR::WARN_LEVEL_ERROR,
+ str,
+ MyFlags);
}
-void THD::raise_error_printf(uint code, const char *format, myf MyFlags, ...)
+void THD::raise_error_printf(uint sql_errno, const char *format,
+ myf MyFlags, ...)
{
va_list args;
char ebuff[ERRMSGSIZE+20];
DBUG_ENTER("THD::raise_error_printf");
DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d Format: %s",
- code, MyFlags, errno, format));
+ sql_errno, MyFlags, errno, format));
va_start(args, MyFlags);
my_vsnprintf(ebuff, sizeof(ebuff), format, args);
va_end(args);
- SQL_condition cond(this->mem_root);
- cond.set(this, code, ebuff, MYSQL_ERROR::WARN_LEVEL_ERROR, MyFlags);
- raise_condition(& cond);
+ const char* sqlstate= mysql_errno_to_sqlstate(sql_errno);
+ (void) raise_condition(sql_errno,
+ sqlstate,
+ MYSQL_ERROR::WARN_LEVEL_ERROR,
+ ebuff,
+ MyFlags);
DBUG_VOID_RETURN;
}
-void THD::raise_warning(uint code, const char *msg)
+void THD::raise_warning(uint sql_errno, const char *msg)
{
- SQL_condition cond(this->mem_root);
- cond.set(this, code, msg, MYSQL_ERROR::WARN_LEVEL_WARN, MYF(0));
- raise_condition(& cond);
+ const char* sqlstate= mysql_errno_to_sqlstate(sql_errno);
+ (void) raise_condition(sql_errno,
+ sqlstate,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
+ msg,
+ MYF(0));
}
-void THD::raise_warning_printf(uint code, const char *format, ...)
+void THD::raise_warning_printf(uint sql_errno, const char *format, ...)
{
va_list args;
char ebuff[ERRMSGSIZE+20];
DBUG_ENTER("THD::raise_warning_printf");
- DBUG_PRINT("enter", ("warning: %u", code));
+ DBUG_PRINT("enter", ("warning: %u", sql_errno));
va_start(args, format);
my_vsnprintf(ebuff, sizeof(ebuff), format, args);
va_end(args);
- SQL_condition cond(this->mem_root);
- cond.set(this, code, ebuff, MYSQL_ERROR::WARN_LEVEL_WARN, MYF(0));
- raise_condition(& cond);
+ const char* sqlstate= mysql_errno_to_sqlstate(sql_errno);
+ (void) raise_condition(sql_errno,
+ sqlstate,
+ MYSQL_ERROR::WARN_LEVEL_WARN,
+ ebuff,
+ MYF(0));
DBUG_VOID_RETURN;
}
-void THD::raise_note(uint code, const char *msg)
+void THD::raise_note(uint sql_errno, const char *msg)
{
DBUG_ENTER("THD::raise_note");
- DBUG_PRINT("enter", ("code: %d, msg: %s", code, msg));
+ DBUG_PRINT("enter", ("code: %d, msg: %s", sql_errno, msg));
if (!(this->options & OPTION_SQL_NOTES))
DBUG_VOID_RETURN;
- SQL_condition cond(this->mem_root);
- cond.set(this, code, msg, MYSQL_ERROR::WARN_LEVEL_NOTE, MYF(0));
- raise_condition(& cond);
+ const char* sqlstate= mysql_errno_to_sqlstate(sql_errno);
+ (void) raise_condition(sql_errno,
+ sqlstate,
+ MYSQL_ERROR::WARN_LEVEL_NOTE,
+ msg,
+ MYF(0));
DBUG_VOID_RETURN;
}
-void THD::raise_note_printf(uint code, const char *format, ...)
+void THD::raise_note_printf(uint sql_errno, const char *format, ...)
{
va_list args;
char ebuff[ERRMSGSIZE+20];
DBUG_ENTER("THD::raise_note_printf");
- DBUG_PRINT("enter",("code: %u", code));
+ DBUG_PRINT("enter",("code: %u", sql_errno));
if (!(this->options & OPTION_SQL_NOTES))
DBUG_VOID_RETURN;
va_start(args, format);
my_vsnprintf(ebuff, sizeof(ebuff), format, args);
va_end(args);
- SQL_condition cond(this->mem_root);
- cond.set(this, code, ebuff, MYSQL_ERROR::WARN_LEVEL_NOTE, MYF(0));
- raise_condition(& cond);
+ const char* sqlstate= mysql_errno_to_sqlstate(sql_errno);
+ (void) raise_condition(sql_errno,
+ sqlstate,
+ MYSQL_ERROR::WARN_LEVEL_NOTE,
+ ebuff,
+ MYF(0));
DBUG_VOID_RETURN;
}
-void THD::raise_condition(const SQL_condition *cond)
+SQL_condition* THD::raise_condition(uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ myf flags)
{
- const char* msg= cond->get_message_text();
-
+ SQL_condition *cond= NULL;
DBUG_ENTER("THD::raise_condition");
if (!(this->options & OPTION_SQL_NOTES) &&
- (cond->m_level == MYSQL_ERROR::WARN_LEVEL_NOTE))
- DBUG_VOID_RETURN;
+ (level == MYSQL_ERROR::WARN_LEVEL_NOTE))
+ DBUG_RETURN(NULL);
if (query_id != warn_id && !spcont)
mysql_reset_errors(this, 0);
- switch (cond->m_level)
+ if ((level == MYSQL_ERROR::WARN_LEVEL_WARN) &&
+ really_abort_on_warning())
+ {
+ /*
+ FIXME:
+ push_warning and strict SQL_MODE case.
+ */
+ level= MYSQL_ERROR::WARN_LEVEL_ERROR;
+ killed= THD::KILL_BAD_DATA;
+ }
+
+ switch (level)
{
case MYSQL_ERROR::WARN_LEVEL_NOTE:
case MYSQL_ERROR::WARN_LEVEL_WARN:
got_warning= 1;
break;
case MYSQL_ERROR::WARN_LEVEL_ERROR:
- if (cond->m_flags & ME_FATALERROR)
+ if (flags & ME_FATALERROR)
is_fatal_error= 1;
break;
default:
DBUG_ASSERT(FALSE);
}
- if (handle_condition(cond))
- DBUG_VOID_RETURN;
+ if (handle_condition(sql_errno, sqlstate, level, msg, &cond))
+ DBUG_RETURN(cond);
- if (cond->m_level == MYSQL_ERROR::WARN_LEVEL_ERROR)
+ if (level == MYSQL_ERROR::WARN_LEVEL_ERROR)
{
is_slave_error= 1; // needed to catch query errors during replication
@@ -835,8 +878,7 @@ void THD::raise_condition(const SQL_cond
(int) is_fatal_error));
}
else if (! main_da.is_error())
- main_da.set_error_status(this, cond->m_sql_errno,
- msg, cond->get_sqlstate());
+ main_da.set_error_status(this, sql_errno, msg, sqlstate);
}
/*
@@ -844,49 +886,54 @@ void THD::raise_condition(const SQL_cond
by the stored procedures code.
*/
if (!is_fatal_error && spcont &&
- spcont->handle_condition(this, cond))
+ spcont->handle_condition(this, sql_errno, sqlstate, level, msg, &cond))
{
/*
Do not push any warnings, a handled error must be completely
silenced.
*/
- DBUG_VOID_RETURN;
+ DBUG_RETURN(cond);
}
/* Un-handled conditions */
- raise_condition_no_handler(cond);
- DBUG_VOID_RETURN;
+ cond= raise_condition_no_handler(sql_errno, sqlstate, level, msg);
+ DBUG_RETURN(cond);
}
-void THD::raise_condition_no_handler(const SQL_condition *cond)
+SQL_condition*
+THD::raise_condition_no_handler(uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg)
{
+ SQL_condition *cond= NULL;
DBUG_ENTER("THD::raise_condition_no_handler");
query_cache_abort(& query_cache_tls);
/* FIXME: broken special case */
- if (no_warnings_for_error && (cond->m_level == MYSQL_ERROR::WARN_LEVEL_ERROR))
- DBUG_VOID_RETURN;
+ if (no_warnings_for_error && (level == MYSQL_ERROR::WARN_LEVEL_ERROR))
+ DBUG_RETURN(NULL);
if (! main_da.m_stmt_area.is_read_only())
{
if (main_da.m_stmt_area.warn_list.elements < variables.max_error_count)
{
/* We have to use warn_root, as mem_root is freed after each query */
- SQL_condition *stored_cond;
- stored_cond= SQL_condition::deep_copy(this, & warn_root, cond);
- if (stored_cond)
+ cond= new (& warn_root) SQL_condition(& warn_root);
+ if (cond)
{
- main_da.m_stmt_area.warn_list.push_back(stored_cond, & warn_root);
+ cond->set(sql_errno, sqlstate, level, msg);
+ main_da.m_stmt_area.warn_list.push_back(cond, & warn_root);
}
}
- main_da.m_stmt_area.warn_count[(uint) cond->m_level]++;
+ main_da.m_stmt_area.warn_count[(uint) level]++;
}
total_warn_count++;
- DBUG_VOID_RETURN;
+ DBUG_RETURN(cond);
}
extern "C"
=== modified file 'sql/sql_class.h'
--- a/sql/sql_class.h 2008-10-01 18:27:26 +0000
+++ b/sql/sql_class.h 2008-10-03 21:35:16 +0000
@@ -1168,6 +1168,20 @@ private:
friend class sp_rcontext;
/**
+ Default constructor.
+ This constructor is usefull when allocating arrays.
+ Note that the init() method should be called to complete the SQL_condition.
+ */
+ SQL_condition();
+
+ /**
+ Complete the SQL_condition initialisation.
+ @param mem_root The memory root to use for the condition items
+ of this condition
+ */
+ void init(MEM_ROOT *mem_root);
+
+ /**
Constructor.
@param mem_root The memory root to use for the condition items
of this condition
@@ -1179,27 +1193,10 @@ private:
{}
/**
- Deep copy (static method).
- Builds a copy of a condition using a given memory root.
- 'Deep copy' is useful to propagate SQL conditions raised from a short
- lived runtime environment to a parent execution environment with a longer
- life cycle.
- For example, when proc_p1() calls proc_p2(), an exception raised in
- proc_p2() should be copied when caught in proc_p1(),
- before destroying the proc_p2() memory root.
- @param thd the current thread.
- @param mem_root the memory root to use for memory allocation.
+ Copy optional condition items attributes.
@param cond the condition to copy.
- @return the duplicated condition.
*/
- static SQL_condition* deep_copy(THD *thd, MEM_ROOT *mem_root,
- const SQL_condition *cond);
-
- /**
- Deep copy (instance method).
- @param cond the condition to copy.
- */
- void deep_copy(const SQL_condition *cond);
+ void copy_opt_attributes(const SQL_condition *cond);
/**
Set this condition area with a fixed message text.
@@ -1209,19 +1206,9 @@ private:
@param level the error level for this condition.
@param MyFlags additional flags.
*/
- void set(THD *thd, uint code, const char *str,
- MYSQL_ERROR::enum_warning_level level, myf MyFlags);
-
- /**
- Set this condition area with formatting of the message text.
- @param thd the current thread.
- @param code the error number for this condition.
- @param str the message text printf format for this condition.
- @param level the error level for this condition.
- @param MyFlags additional flags.
- */
- void set_printf(THD *thd, uint code, const char *str,
- MYSQL_ERROR::enum_warning_level level, myf MyFlags, ...);
+ void set(uint sql_errno, const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg);
/**
Set the condition message test.
@@ -1233,9 +1220,18 @@ private:
/** Set the SQLSTATE of this condition. */
void set_sqlstate(const char* sqlstate);
+ /**
+ Predicate, returns true if the condition item MESSAGE_TEXT was set.
+ @return True if MESSAGE_TEXT was set.
+ */
bool is_message_text_set() const
{ return m_message_text_set; }
+ /**
+ Clear this SQL condition.
+ */
+ void clear();
+
private:
/** SQL CLASS_ORIGIN condition item. */
UTF8String64 m_class_origin;
@@ -1293,9 +1289,6 @@ private:
/** Severity (error, warning, note) of this condition. */
MYSQL_ERROR::enum_warning_level m_level;
- /** Additional flags. */
- myf m_flags;
-
/** Memory root to use to hold condition item values. */
MEM_ROOT *m_mem_root;
};
@@ -1336,7 +1329,13 @@ public:
@param cond the condition raised.
@return true if the condition is handled
*/
- virtual bool handle_condition(THD *thd, const SQL_condition *cond) = 0;
+ virtual bool handle_condition(THD *thd,
+ uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ SQL_condition ** cond_hdl) = 0;
+
};
@@ -2637,7 +2636,11 @@ public:
@param cond the sql condition to handle.
@return true if the error is handled
*/
- virtual bool handle_condition(const SQL_condition *cond);
+ bool handle_condition(uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ SQL_condition ** cond_hdl);
/**
Remove the error handler last pushed.
@@ -2724,14 +2727,23 @@ private:
Raise a generic SQL condition.
@param cond the condition to raise
*/
- void raise_condition(const SQL_condition *cond);
+ SQL_condition*
+ raise_condition(uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ myf flags);
/**
Raise a generic SQL condition, without activation any SQL condition
handlers.
@param cond the condition to raise
*/
- void raise_condition_no_handler(const SQL_condition *cond);
+ SQL_condition*
+ raise_condition_no_handler(uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg);
private:
/** The current internal error handler for this thread, or NULL. */
=== modified file 'sql/sql_fixstring.cc'
--- a/sql/sql_fixstring.cc 2008-10-01 18:27:26 +0000
+++ b/sql/sql_fixstring.cc 2008-10-03 21:35:16 +0000
@@ -33,10 +33,7 @@ void Fixed_string::set(const char* str,
if (str == NULL)
{
- m_ptr= NULL;
- m_byte_length= 0;
- m_allocated_length= 0;
- m_truncated= FALSE;
+ clear();
return;
}
@@ -115,6 +112,14 @@ void Fixed_string::copy(const Fixed_stri
set(str->m_ptr, str->m_byte_length, str->m_param->m_cs);
}
+void Fixed_string::clear()
+{
+ m_ptr= NULL;
+ m_byte_length= 0;
+ m_allocated_length= 0;
+ m_truncated= FALSE;
+}
+
void Fixed_string::reserve(size_t len)
{
if ((m_ptr != NULL) && (m_allocated_length >= len))
=== modified file 'sql/sql_fixstring.h'
--- a/sql/sql_fixstring.h 2008-10-01 18:27:26 +0000
+++ b/sql/sql_fixstring.h 2008-10-03 21:35:16 +0000
@@ -59,6 +59,9 @@ public:
m_ptr(NULL)
{}
+ void init(MEM_ROOT *mem_root)
+ { m_mem_root= mem_root; }
+
/** Destructor. */
~Fixed_string();
@@ -113,6 +116,8 @@ public:
*/
void copy(const Fixed_string *str);
+ void clear();
+
private:
/**
Allocate memory for the string representation.
@@ -176,6 +181,10 @@ public:
: Fixed_string(& params, root)
{}
+ UTF8String64()
+ : Fixed_string(& params, NULL)
+ {}
+
~UTF8String64()
{}
@@ -197,6 +206,10 @@ public:
: Fixed_string(& params, root)
{}
+ UTF8String128()
+ : Fixed_string(& params, NULL)
+ {}
+
~UTF8String128()
{}
=== modified file 'sql/sql_signal.cc'
--- a/sql/sql_signal.cc 2008-10-01 18:27:26 +0000
+++ b/sql/sql_signal.cc 2008-10-03 21:35:16 +0000
@@ -213,6 +213,60 @@ const LEX_STRING Diag_statement_item_nam
};
+SQL_condition::SQL_condition()
+ : Sql_alloc(),
+ m_class_origin(),
+ m_subclass_origin(),
+ m_constraint_catalog(),
+ m_constraint_schema(),
+ m_constraint_name(),
+ m_catalog_name(),
+ m_schema_name(),
+ m_table_name(),
+ m_column_name(),
+ m_cursor_name(),
+ m_message_text(),
+ m_message_text_set(FALSE),
+ m_sql_errno(0),
+ m_level(MYSQL_ERROR::WARN_LEVEL_ERROR),
+ m_mem_root(NULL)
+{
+ memset(m_returned_sqlstate, 0, sizeof(m_returned_sqlstate));
+}
+
+void SQL_condition::init(MEM_ROOT *mem_root)
+{
+ m_class_origin.init(mem_root);
+ m_subclass_origin.init(mem_root);
+ m_constraint_catalog.init(mem_root);
+ m_constraint_schema.init(mem_root);
+ m_constraint_name.init(mem_root);
+ m_catalog_name.init(mem_root);
+ m_schema_name.init(mem_root);
+ m_table_name.init(mem_root);
+ m_column_name.init(mem_root);
+ m_cursor_name.init(mem_root);
+ m_mem_root= mem_root;
+}
+
+void SQL_condition::clear()
+{
+ m_class_origin.clear();
+ m_subclass_origin.clear();
+ m_constraint_catalog.clear();
+ m_constraint_schema.clear();
+ m_constraint_name.clear();
+ m_catalog_name.clear();
+ m_schema_name.clear();
+ m_table_name.clear();
+ m_column_name.clear();
+ m_cursor_name.clear();
+ m_message_text.length(0);
+ m_message_text_set= FALSE;
+ m_sql_errno= 0;
+ m_level= MYSQL_ERROR::WARN_LEVEL_ERROR;
+}
+
SQL_condition::SQL_condition(MEM_ROOT *mem_root)
: Sql_alloc(),
m_class_origin(mem_root),
@@ -229,42 +283,15 @@ SQL_condition::SQL_condition(MEM_ROOT *m
m_message_text_set(FALSE),
m_sql_errno(0),
m_level(MYSQL_ERROR::WARN_LEVEL_ERROR),
- m_flags(0),
m_mem_root(mem_root)
{
memset(m_returned_sqlstate, 0, sizeof(m_returned_sqlstate));
}
-SQL_condition *
-SQL_condition::deep_copy(THD *thd, MEM_ROOT *mem_root,
- const SQL_condition *cond)
-{
- SQL_condition *copy= new (mem_root) SQL_condition(mem_root);
- if (copy)
- copy->deep_copy(cond);
- return copy;
-}
-
void
-SQL_condition::deep_copy(const SQL_condition *cond)
+SQL_condition::copy_opt_attributes(const SQL_condition *cond)
{
- memcpy(m_returned_sqlstate, cond->m_returned_sqlstate,
- sizeof(m_returned_sqlstate));
-
- if (cond->m_message_text.length())
- {
- const char* copy;
-
- copy= strdup_root(m_mem_root, cond->m_message_text.ptr());
- m_message_text.set(copy, cond->m_message_text.length(),
- error_message_charset_info);
- }
- else
- m_message_text.length(0);
-
- DBUG_ASSERT(! m_message_text.is_alloced());
-
- m_message_text_set= cond->m_message_text_set;
+ DBUG_ASSERT(this != cond);
m_class_origin.copy(& cond->m_class_origin);
m_subclass_origin.copy(& cond->m_subclass_origin);
m_constraint_catalog.copy(& cond->m_constraint_catalog);
@@ -275,66 +302,28 @@ SQL_condition::deep_copy(const SQL_condi
m_table_name.copy(& cond->m_table_name);
m_column_name.copy(& cond->m_column_name);
m_cursor_name.copy(& cond->m_cursor_name);
- m_sql_errno= cond->m_sql_errno;
- m_level= cond->m_level;
- m_flags= cond->m_flags;
}
void
-SQL_condition::set_printf(THD *thd, uint code, const char *str,
- MYSQL_ERROR::enum_warning_level level,
- myf flags, ...)
+SQL_condition::set(uint sql_errno, const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level, const char* msg)
{
- va_list args;
- char ebuff[ERRMSGSIZE+20];
-
-
- DBUG_ENTER("SQL_condition::set_printf");
-
- va_start(args, flags);
- (void) my_vsnprintf (ebuff, sizeof(ebuff), str, args);
- va_end(args);
-
- set(thd, code, ebuff, level, flags);
-
- DBUG_VOID_RETURN;
-}
-
-void
-SQL_condition::set(THD *thd, uint code, const char *str,
- MYSQL_ERROR::enum_warning_level level, myf flags)
-{
- const char* sqlstate;
-
/*
TODO: replace by DBUG_ASSERT(code != 0) once all bugs similar to
Bug#36760 are fixed: a SQL condition must have a real (!=0) error number
so that it can be caught by handlers.
*/
- if (code == 0)
- code= ER_UNKNOWN_ERROR;
- if (str == NULL)
- str= ER(code);
- m_sql_errno= code;
+ if (sql_errno == 0)
+ sql_errno= ER_UNKNOWN_ERROR;
+ if (msg == NULL)
+ msg= ER(sql_errno);
+ m_sql_errno= sql_errno;
- sqlstate= mysql_errno_to_sqlstate(m_sql_errno);
memcpy(m_returned_sqlstate, sqlstate, SQLSTATE_LENGTH);
m_returned_sqlstate[SQLSTATE_LENGTH]= '\0';
- set_builtin_message_text(str);
- if ((level == MYSQL_ERROR::WARN_LEVEL_WARN) &&
- thd->really_abort_on_warning())
- {
- /*
- FIXME:
- push_warning and strict SQL_MODE case.
- */
- m_level= MYSQL_ERROR::WARN_LEVEL_ERROR;
- thd->killed= THD::KILL_BAD_DATA;
- }
- else
- m_level= level;
- m_flags= flags;
+ set_builtin_message_text(msg);
+ m_level= level;
}
void
@@ -722,7 +711,16 @@ int Abstract_signal::raise_condition(THD
DBUG_ASSERT((cond->m_level == MYSQL_ERROR::WARN_LEVEL_WARN) ||
(cond->m_level == MYSQL_ERROR::WARN_LEVEL_ERROR));
- thd->raise_condition(cond);
+ SQL_condition *raised= NULL;
+ raised= thd->raise_condition(cond->get_sql_errno(),
+ cond->get_sqlstate(),
+ cond->get_level(),
+ cond->get_message_text(),
+ MYF(0));
+ if (raised)
+ {
+ raised->copy_opt_attributes(cond);
+ }
if (cond->m_level == MYSQL_ERROR::WARN_LEVEL_WARN)
{
@@ -780,11 +778,18 @@ int SQLCOM_resignal::execute(THD *thd)
thd->main_da.m_stmt_area.warn_list.pop();
}
- thd->raise_condition_no_handler(signaled);
+ SQL_condition *raised= NULL;
+ raised= thd->raise_condition_no_handler(signaled->get_sql_errno(),
+ signaled->get_sqlstate(),
+ signaled->get_level(),
+ signaled->get_message_text());
+ if (raised)
+ {
+ raised->copy_opt_attributes(signaled);
+ }
+
+ result= raise_condition(thd, signaled);
- SQL_condition new_cond(thd->mem_root);
- new_cond.deep_copy(signaled);
- result= raise_condition(thd, & new_cond);
DBUG_RETURN(result);
}
=== modified file 'sql/unireg.cc'
--- a/sql/unireg.cc 2008-08-27 22:14:03 +0000
+++ b/sql/unireg.cc 2008-10-03 21:35:16 +0000
@@ -56,7 +56,12 @@ static bool make_empty_rec(THD *thd, int
struct Pack_header_error_handler: public Internal_error_handler
{
- virtual bool handle_condition(THD *thd, const SQL_condition *cond);
+ virtual bool handle_condition(THD *thd,
+ uint sql_errno,
+ const char* sqlstate,
+ MYSQL_ERROR::enum_warning_level level,
+ const char* msg,
+ SQL_condition ** cond_hdl);
bool is_handled;
Pack_header_error_handler() :is_handled(FALSE) {}
};
@@ -64,9 +69,15 @@ struct Pack_header_error_handler: public
bool
Pack_header_error_handler::
-handle_condition(THD *, const SQL_condition *cond)
+handle_condition(THD *,
+ uint sql_errno,
+ const char*,
+ MYSQL_ERROR::enum_warning_level,
+ const char*,
+ SQL_condition ** cond_hdl)
{
- is_handled= (cond->get_sql_errno() == ER_TOO_MANY_FIELDS);
+ *cond_hdl= NULL;
+ is_handled= (sql_errno == ER_TOO_MANY_FIELDS);
return is_handled;
}