List:Commits« Previous MessageNext Message »
From:Marc Alff Date:October 3 2008 9:43pm
Subject:bzr push into mysql-6.0-wl2110-review branch (marc.alff:2703 to 2704)
Bug#11661 WL#2110 WL#2265
View as plain text  
 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

 2703 Marc Alff	2008-10-01
      Implemented code review comments
modified:
  libmysqld/Makefile.am
  mysql-test/r/signal.result
  mysql-test/r/signal_demo1.result
  mysql-test/t/signal.test
  mysql-test/t/signal_demo1.test
  sql/Makefile.am
  sql/ha_ndbcluster_binlog.cc
  sql/mysql_priv.h
  sql/sp_head.cc
  sql/sp_rcontext.cc
  sql/sp_rcontext.h
  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/sql_signal.h
  sql/sql_view.cc
  sql/table.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;
 }
 

Thread
bzr push into mysql-6.0-wl2110-review branch (marc.alff:2703 to 2704)Bug#11661 WL#2110 WL#2265Marc Alff3 Oct