List:Commits« Previous MessageNext Message »
From:kpettersson Date:March 6 2008 2:41pm
Subject:bk commit into 5.1 tree (thek:1.2517) BUG#16470
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of thek.  When thek 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, 2008-03-06 15:40:54+01:00, thek@adventure.(none) +6 -0
  Bug#16470 crash on grant if old grant tables
  
  Iterative patch to convert an error message to warnings based on 
  originating code (ie error handling strategies).

  mysql-test/r/grant.result@stripped, 2008-03-06 15:40:50+01:00, thek@adventure.(none) +3 -1
    Converted error to warning.

  mysql-test/t/grant.test@stripped, 2008-03-06 15:40:51+01:00, thek@adventure.(none) +0 -1
    Converted error to warning.

  sql/mysqld.cc@stripped, 2008-03-06 15:40:51+01:00, thek@adventure.(none) +6 -0
    * Stacked error handler intercepts and/or rewrites error events (warning/error)
    Note: This should not effect the sql-eninge error interceptor.

  sql/sql_acl.cc@stripped, 2008-03-06 15:40:51+01:00, thek@adventure.(none) +4 -0
    * A scoped error handler changes the error handling strategy for grant reloads.
    ER_NO_SUCH_TABLE should be reduced to two warnings instead since failing to
    load some grant tables isn't considered as fatal as failing to load other
    tables which relys on the default error handling strategy.

  sql/sql_class.cc@stripped, 2008-03-06 15:40:51+01:00, thek@adventure.(none) +105 -0
    * A scoped error handler changes the error handling strategy for grant reloads.
    ER_NO_SUCH_TABLE should be reduced to two warnings instead since failing to
    load some grant tables isn't considered as fatal as failing to load other
    tables which relys on the default error handling strategy.

  sql/sql_class.h@stripped, 2008-03-06 15:40:51+01:00, thek@adventure.(none) +55 -1
    * Added methods to THD for pushing and popping an error handler for the
    purpose of supporting scoped error handling strategies demanded by the server
    architecture.
    * Created Scoped_error_handler class for supporting an automatic stack pop in
    the end of a function scope.

diff -Nrup a/mysql-test/r/grant.result b/mysql-test/r/grant.result
--- a/mysql-test/r/grant.result	2008-02-04 19:55:32 +01:00
+++ b/mysql-test/r/grant.result	2008-03-06 15:40:50 +01:00
@@ -1291,7 +1291,9 @@ use test;
 FLUSH PRIVILEGES without procs_priv table.
 RENAME TABLE mysql.procs_priv TO mysql.procs_gone;
 FLUSH PRIVILEGES;
-ERROR 42S02: Table 'mysql.procs_priv' doesn't exist
+Warnings:
+Error	1146	Table 'mysql.procs_priv' doesn't exist
+Error	1547	Table 'mysql.procs_priv' doesn't exist
 Assigning privileges without procs_priv table.
 CREATE DATABASE mysqltest1;
 CREATE PROCEDURE mysqltest1.test() SQL SECURITY DEFINER
diff -Nrup a/mysql-test/t/grant.test b/mysql-test/t/grant.test
--- a/mysql-test/t/grant.test	2008-02-04 19:55:32 +01:00
+++ b/mysql-test/t/grant.test	2008-03-06 15:40:51 +01:00
@@ -1384,7 +1384,6 @@ use test;
 #
 --echo FLUSH PRIVILEGES without procs_priv table.
 RENAME TABLE mysql.procs_priv TO mysql.procs_gone;
---error ER_NO_SUCH_TABLE
 FLUSH PRIVILEGES;
 --echo Assigning privileges without procs_priv table.
 CREATE DATABASE mysqltest1;
diff -Nrup a/sql/mysqld.cc b/sql/mysqld.cc
--- a/sql/mysqld.cc	2008-01-25 18:14:58 +01:00
+++ b/sql/mysqld.cc	2008-03-06 15:40:51 +01:00
@@ -2589,6 +2589,12 @@ int my_message_sql(uint error, const cha
                           MYSQL_ERROR::WARN_LEVEL_ERROR))
       DBUG_RETURN(0);
 
+    if (thd->main_da.handle_error(thd, error, str,
+                                  MYSQL_ERROR::WARN_LEVEL_ERROR))
+    {
+      DBUG_RETURN(0);
+    }
+
     thd->is_slave_error=  1; // needed to catch query errors during replication
 
     /*
diff -Nrup a/sql/sql_acl.cc b/sql/sql_acl.cc
--- a/sql/sql_acl.cc	2008-02-01 17:00:50 +01:00
+++ b/sql/sql_acl.cc	2008-03-06 15:40:51 +01:00
@@ -3530,6 +3530,7 @@ static my_bool grant_load_procs_priv(TAB
   MEM_ROOT **save_mem_root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**,
                                                            THR_MALLOC);
   DBUG_ENTER("grant_load");
+
   (void) hash_init(&proc_priv_hash,system_charset_info,
                    0,0,0, (hash_get_key) get_grant_table,
                    0,0);
@@ -3703,6 +3704,9 @@ static my_bool grant_reload_procs_priv(T
   TABLE_LIST table;
   my_bool return_val= FALSE;
   DBUG_ENTER("grant_reload_procs_priv");
+
+  Scoped_error_handler error_handler(&thd->main_da,
+                                     new Grant_system_error_handler());
 
   bzero((char*) &table, sizeof(table));
   table.alias= table.table_name= (char*) "procs_priv";
diff -Nrup a/sql/sql_class.cc b/sql/sql_class.cc
--- a/sql/sql_class.cc	2008-01-22 23:45:42 +01:00
+++ b/sql/sql_class.cc	2008-03-06 15:40:51 +01:00
@@ -3579,4 +3579,109 @@ bool Discrete_intervals_list::append(ulo
   DBUG_RETURN(0);
 }
 
+/**
+  @brief Convert ER_NO_SUCH_TABLE error code into two Warnings.
+
+  This is intended as a scoped error handler.
+
+  @see Internal_error_handler
+  @see Diagnostic_area
+*/
+
+bool Grant_system_error_handler::
+handle_error(uint sql_errno,
+             const char *message,
+             MYSQL_ERROR::enum_warning_level level,
+             THD *thd)
+{
+  if (!thd->main_da.is_error() )
+  {
+    if (sql_errno == ER_NO_SUCH_TABLE)
+    {
+      if (thd->warn_list.elements < thd->variables.max_error_count)
+      {
+        MYSQL_ERROR *err;
+        /* We have to use warn_root, as mem_root is freed after each query */
+        if ((err= new (&thd->warn_root) MYSQL_ERROR(thd, ER_NO_SUCH_TABLE,
+          MYSQL_ERROR::WARN_LEVEL_ERROR, message)))
+          thd->warn_list.push_back(err, &thd->warn_root);
+        if ((err= new (&thd->warn_root) MYSQL_ERROR(thd,
+          ER_COL_COUNT_DOESNT_MATCH_CORRUPTED,
+          MYSQL_ERROR::WARN_LEVEL_ERROR, message)))
+          thd->warn_list.push_back(err, &thd->warn_root);
+      }
+      thd->warn_count[(uint) level]++;
+      thd->total_warn_count++;
+      thd->got_warning= TRUE;
+      thd->main_da.set_ok_status(thd, 0, 0, message);
+      return TRUE;
+    }
+    if (sql_errno == 0)
+        sql_errno= ER_UNKNOWN_ERROR;
+    if (message == NULL)
+        thd->main_da.set_error_status(thd, sql_errno, ER(sql_errno));
+    else thd->main_da.set_error_status(thd, sql_errno, message);
+    return TRUE;
+  }
+  return FALSE;
+}
+
+
+/**
+  @brief Push an error handler filter to the stack.
+
+  The new filter will become the most significant.
+
+  @param hndl A pointer to internal error handler.
+*/
+
+bool Diagnostics_area::push_error_handler(Internal_error_handler *hndl)
+{
+  m_error_handlers.push_front(hndl);
+  return TRUE;
+}
+
+
+/**
+  @brief Remove the most significant error handler from the stack.
+*/
+
+Internal_error_handler *Diagnostics_area::pop_error_handler(void)
+{
+  return m_error_handlers.pop();
+}
+
+
+/**
+  @brief Iterate over all error handlers starting with the most significant.
+
+  If any error handler declares that all errors are dealt with the iteration
+  will stop and the default error handling won't be executed.
+
+  @param thd Thread handle
+  @param sql_errno The error code
+  @param message The error message (may be NULL)
+  @param level The warning level
+
+  @see my_message_sql
+
+  @return Completion status
+    @retval TRUE All errors are handled.
+    @retval FALSE Some error may have been handled.
+*/
+
+bool Diagnostics_area::handle_error(THD *thd, uint sql_errno,
+                                    const char *message,
+                                    MYSQL_ERROR::enum_warning_level level)
+{
+  List_iterator<Internal_error_handler> it(m_error_handlers);
+  Internal_error_handler *handler;
+  bool exit_flag= FALSE;
+  while( (handler= it++) != NULL && !exit_flag)
+  {
+    exit_flag= handler->handle_error(sql_errno, message, level, thd);
+  }
+  return exit_flag;
+}
+
 #endif /* !defined(MYSQL_CLIENT) */
diff -Nrup a/sql/sql_class.h b/sql/sql_class.h
--- a/sql/sql_class.h	2008-01-25 18:14:59 +01:00
+++ b/sql/sql_class.h	2008-03-06 15:40:51 +01:00
@@ -938,7 +938,7 @@ enum enum_thread_type
 */
 class Internal_error_handler
 {
-protected:
+public:
   Internal_error_handler() {}
   virtual ~Internal_error_handler() {}
 
@@ -1003,6 +1003,9 @@ public:
   /** Set to make set_error_status after set_{ok,eof}_status possible. */
   bool can_overwrite_status;
 
+  /** A stack of error handler filters */
+  List<Internal_error_handler> m_error_handlers;
+
   void set_ok_status(THD *thd, ha_rows affected_rows_arg,
                      ulonglong last_insert_id_arg,
                      const char *message);
@@ -1044,6 +1047,13 @@ public:
     return m_total_warn_count;
   }
 
+  bool push_error_handler(Internal_error_handler *hndl);
+
+  Internal_error_handler *pop_error_handler(void);
+
+  bool handle_error(THD *thd, uint sql_errno, const char *message,
+                    MYSQL_ERROR::enum_warning_level level);
+
   Diagnostics_area() { reset_diagnostics_area(); }
 
 private:
@@ -2203,6 +2213,50 @@ public:
 #else
   void begin_dataset() {}
 #endif
+};
+
+
+/**
+  Push an error handler to the stack for the reminder of the current function
+  lifetime.
+
+  A Scoped_error_handler is intended to be instantiated as an object on the 
+  stack in the scope of a function, so that it will be automatically deleted
+  when the function returns.
+
+*/
+
+class Scoped_error_handler
+{
+public:
+  /**
+    @param da A pointer to the diagnostic area containing the error handler stack
+    @param hndl A pointer to the error handler object to be pushed.
+  */
+  Scoped_error_handler(Diagnostics_area *da,Internal_error_handler *hndl)
+  {
+    m_da= da;
+    m_da->push_error_handler(hndl);
+  }
+
+  ~Scoped_error_handler()
+  {
+    Internal_error_handler *handler= m_da->pop_error_handler();
+    delete handler;
+  }
+
+private:
+
+  Diagnostics_area *m_da;
+};
+
+class Grant_system_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);
 };
 
 
Thread
bk commit into 5.1 tree (thek:1.2517) BUG#16470kpettersson6 Mar
  • Re: bk commit into 5.1 tree (thek:1.2517) BUG#16470Sergei Golubchik7 Mar