List:Commits« Previous MessageNext Message »
From:ahristov Date:August 16 2006 5:55pm
Subject:bk commit into 5.1 tree (andrey:1.2278)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of andrey. When andrey 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, 2006-08-16 19:55:14+02:00, andrey@stripped +16 -0
  WL#3337 (Event scheduler new architecture)
  Fixes from review.
  
  1) Move Event_queue::check_system_tables() to Events::check_system_tables()
  2) Create artificial THD in Events::init(). Hence, don't create a separate thread
     in Event_queue::init_queue() to load the events from disk.
  3) Whitespace changes.
  4) Added const modifier wherever is feasible.
  5) Whitespace fixes.
  6) Method comments fixes.
  7) Changed method which return value to be void wherever the
    return value wasn't actually used (drop_schema_events())
  8) Other small changes.
  
  All but the const change are according review of WL#3337 patch code by Kostja

  sql/event_data_objects.cc@stripped, 2006-08-16 19:55:08+02:00, andrey@stripped +44 -37
    Changes that does not affect the execution:
    - Whitespace changes
    - Adding consts wherever feasible.
    - Use initialization list for the constructor of Event_parse_data
    - Shorten comments so they don't span till column 80
    - Rename a parameter of event_basic_identifier_equal

  sql/event_data_objects.h@stripped, 2006-08-16 19:55:09+02:00, andrey@stripped +10 -9
    - White space changes
    - Add const modifier wherever is feasible

  sql/event_db_repository.cc@stripped, 2006-08-16 19:55:09+02:00, andrey@stripped +89 -113
    - Fix usage of initialized value in case of ha_write_row() has failed.
    
    Changes that does not affect the actual execution
    - Add const modifier wherever is feasible
    - Fix function comments Returns -> RETURN VALUE
                            Synopsis -> SYNOPSIS
    - Remove usage of macros for checking the values against the maximal
      length of a column. The column already has this value. This makes
      the code more transparent to changes.
    - Modify methods to return bool instead of int, when only one error code
      is returned.
    - Fixed long comment, which mentions possible valgrind problem. Made it short.
    - Made methods void where the return value is not actually used 
      (drop_schema_events(), drop_events_by_field())

  sql/event_db_repository.h@stripped, 2006-08-16 19:55:09+02:00, andrey@stripped +21 -21
    - Remove unneeded declaration
    - Add const modifier wherever is feasible
    - Make drop_schema_events() and drop_events_by_field() void as their
      return value is unused.
    - Change methods to return bool instead of int, because they return
      actually only one error code.

  sql/event_queue.cc@stripped, 2006-08-16 19:55:09+02:00, andrey@stripped +59 -190
    - The queue won't create a separate thread to load events on start up.
      It gets the THD from the caller. The thd in the caller is artificially
      and temporarily created.
    - White space changes
    - Added a better comment for Event_queue::init()
    - Added const modifier wherever is feasible
    - Whitespace changes
    - Fixed method comments
    - Changed find_n_remove_event() to destroy the removed object.
      Helpful against memory leaks (this is according to Kostja's review).
      Also made it void.
    - Shortened comments so they don't span till column 80.

  sql/event_queue.h@stripped, 2006-08-16 19:55:09+02:00, andrey@stripped +17 -19
    - Add possibility to pass THD instance to used during init_queue() call.
      This saves creation of a temporary THD (and a thread) inside init_queue().
    - Whitespace changes
    - Added const modifier wherever is feasible
    - Made find_n_remove_event() void

  sql/event_scheduler.cc@stripped, 2006-08-16 19:55:09+02:00, andrey@stripped +6 -6
    - Fix warning about usage of uninitialized variable in Event_scheduler::run()
    - Added const modifiers wherever is feasible

  sql/event_scheduler.h@stripped, 2006-08-16 19:55:09+02:00, andrey@stripped +6 -6
    - Whitespace changes
    - Added const modifier to execute_top()'s declaration

  sql/events.cc@stripped, 2006-08-16 19:55:09+02:00, andrey@stripped +229 -47
    - Create a temporary THD to be used to initialize the queue.
    - Move Event_queue::check_system_tables to Events::check_system_tables()
      Check the tables only on start-up. If not in order then throw an error
      message anytime any query which uses events DDL is used.
    - If there was a problem during loading of events from disk on server start,
      disable the queue functionality but allow creation on disk. The server needs
      to be restarted to bring the queue to operation, if the problem that prevented
      loading has been fixed.
    - Added const modifier wherever is feasible
    - Fixed methods' comments (parameter names)
    - Whitespace changes
    - Changed drop_schema_events() to be void, as its value is actually
      not used in sql_db.cc
    - Renamed is_started() to is_execution_of_events_started()

  sql/events.h@stripped, 2006-08-16 19:55:09+02:00, andrey@stripped +33 -19
    - Event_queue::check_system_tables() -> Events::check_system_tables()
      db_ok -> TRUE, no problems during loading of events on server boot.
               FALSE, there was an error.
    
    - Whitespace changes
    - Added const modifier wherever is feasible
    - Moved friend declaration to be after the comment about it
    - Changed drop_schema_event() to be void, as its value is not used

  sql/set_var.cc@stripped, 2006-08-16 19:55:09+02:00, andrey@stripped +1 -1
    is_started() renamed to is_execution_of_events_started()

  sql/share/errmsg.txt@stripped, 2006-08-16 19:55:09+02:00, andrey@stripped +2 -0
    New error message for the case when the system tables were not what Events subsystem
    expects, on server-start.

  sql/sql_db.cc@stripped, 2006-08-16 19:55:09+02:00, andrey@stripped +1 -1
    drop_schema_events() changed to be void. The return value wasn't
    actually used.

  sql/sql_yacc.yy@stripped, 2006-08-16 19:55:09+02:00, andrey@stripped +20 -19
    - Fixed comments
    - Removed unneeded assigment Lex->spname= NULL. It is NULL-ed in lex_init()
    - Changed an umlaut to be in ascii and not utf8

  sql/table.cc@stripped, 2006-08-16 19:55:09+02:00, andrey@stripped +22 -22
    Added const modifier to table_check_intact()
    Fixed the comments of table_check_intact()

  sql/table.h@stripped, 2006-08-16 19:55:09+02:00, andrey@stripped +3 -3
    Added const modifier to the third parameter of table_check_intact()

# This is a BitKeeper patch.  What follows are the unified diffs for the
# set of deltas contained in the patch.  The rest of the patch, the part
# that BitKeeper cares about, is below these diffs.
# User:	andrey
# Host:	example.com
# Root:	/work/mysql-5.1-runtime-wl3337

--- 1.140/sql/sql_db.cc	2006-08-16 19:55:26 +02:00
+++ 1.141/sql/sql_db.cc	2006-08-16 19:55:26 +02:00
@@ -949,7 +949,7 @@ bool mysql_rm_db(THD *thd,char *db,bool 
 
 exit:
   (void)sp_drop_db_routines(thd, db); /* QQ Ignore errors for now  */
-  error= Events::get_instance()->drop_schema_events(thd, db);
+  Events::get_instance()->drop_schema_events(thd, db);
   /*
     If this database was the client's selected database, we silently
     change the client's selected database to nothing (to have an empty

--- 1.492/sql/sql_yacc.yy	2006-08-16 19:55:26 +02:00
+++ 1.493/sql/sql_yacc.yy	2006-08-16 19:55:26 +02:00
@@ -1445,11 +1445,11 @@ ev_sql_stmt:
           {
             LEX *lex=Lex;
 
-            // return back to the original memory root ASAP
+            /* return back to the original memory root ASAP */
             lex->sphead->init_strings(YYTHD, lex);
             lex->sphead->restore_thd_mem_root(YYTHD);
 
-            lex->sp_chistics.suid= SP_IS_SUID;//always the definer!
+            lex->sp_chistics.suid= SP_IS_SUID;  //always the definer!
 
             Lex->event_parse_data->init_body(YYTHD);
           }
@@ -1568,10 +1568,10 @@ create_function_tail:
 	    sp->m_type= TYPE_ENUM_FUNCTION;
 	    lex->sphead= sp;
 	    /*
-	     * We have to turn of CLIENT_MULTI_QUERIES while parsing a
-	     * stored procedure, otherwise yylex will chop it into pieces
-	     * at each ';'.
-	     */
+	      We have to turn off CLIENT_MULTI_QUERIES while parsing a
+	      stored procedure, otherwise yylex will chop it into pieces
+	      at each ';'.
+	    */
             $<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
 	    YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES;
 	    lex->sphead->m_param_begin= lex->tok_start+1;
@@ -4673,25 +4673,24 @@ alter:
 	  {}
 	| ALTER EVENT_SYM sp_name
           /*
-             BE CAREFUL when you add a new rule to update the block where
-             YYTHD->client_capabilities is set back to original value
+            BE CAREFUL when you add a new rule to update the block where
+            YYTHD->client_capabilities is set back to original value
           */
           {
             /* 
-               It is safe to use Lex->spname because
-               ALTER EVENT xxx RENATE TO yyy DO ALTER EVENT RENAME TO
-               is not allowed. Lex->spname is used in the case of RENAME TO
-               If it had to be supported spname had to be added to
-               Event_parse_data.
+              It is safe to use Lex->spname because
+              ALTER EVENT xxx RENATE TO yyy DO ALTER EVENT RENAME TO
+              is not allowed. Lex->spname is used in the case of RENAME TO
+              If it had to be supported spname had to be added to
+              Event_parse_data.
             */
-            Lex->spname= NULL;
 
             if (!(Lex->event_parse_data= Event_parse_data::new_instance(YYTHD)))
               YYABORT;
             Lex->event_parse_data->identifier= $3;
 
             /*
-              We have to turn of CLIENT_MULTI_QUERIES while parsing a
+              We have to turn off CLIENT_MULTI_QUERIES while parsing a
               stored procedure, otherwise yylex will chop it into pieces
               at each ';'.
             */
@@ -4757,9 +4756,11 @@ ev_alter_on_schedule_completion: /* empt
 opt_ev_rename_to: /* empty */ { $$= 0;}
         | RENAME TO_SYM sp_name
           {
-            LEX *lex=Lex;
-            lex->spname= $3; //use lex's spname to hold the new name
-	                     //the original name is in the Event_parse_data object
+            /*
+              Use lex's spname to hold the new name.
+              The original name is in the Event_parse_data object
+            */
+            Lex->spname= $3; 
             $$= 1;
           }
       ;
@@ -4783,7 +4784,7 @@ alter_commands:
         | remove_partitioning
         | partitioning
 /*
-  This part was added for release 5.1 by Mikael Ronström.
   From here we insert a number of commands to manage the partitions of a
   partitioned table such as adding partitions, dropping partitions,
   reorganising partitions in various manners. In future releases the list

--- 1.239/sql/table.cc	2006-08-16 19:55:26 +02:00
+++ 1.240/sql/table.cc	2006-08-16 19:55:26 +02:00
@@ -2352,28 +2352,28 @@ bool check_column_name(const char *name)
   Checks whether a table is intact. Should be done *just* after the table has
   been opened.
   
-  Synopsis
+  SYNOPSIS
     table_check_intact()
-      table         - the table to check
-      table_f_count - expected number of columns in the table
-      table_def     - expected structure of the table (column name and type)
-    last_create_time- the table->file->create_time of the table in memory
-                      we have checked last time
-      error_num     - ER_XXXX from the error messages file. When 0 no error
-                      is sent to the client in case types does not match.
-                      If different col number either 
-                      ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE or 
-                      ER_COL_COUNT_DOESNT_MATCH_CORRUPTED is used
+      table             The table to check
+      table_f_count     Expected number of columns in the table
+      table_def         Expected structure of the table (column name and type)
+      last_create_time  The table->file->create_time of the table in memory
+                        we have checked last time
+      error_num         ER_XXXX from the error messages file. When 0 no error
+                        is sent to the client in case types does not match.
+                        If different col number either 
+                        ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE or 
+                        ER_COL_COUNT_DOESNT_MATCH_CORRUPTED is used
 
   RETURNS
-    0   - OK
-    1   - There was an error
+    FALSE  OK
+    TRUE   There was an error
 */
 
 my_bool
-table_check_intact(TABLE *table, uint table_f_count,
-                   TABLE_FIELD_W_TYPE *table_def, time_t *last_create_time,
-                   int error_num)
+table_check_intact(TABLE *table, const uint table_f_count,
+                   const TABLE_FIELD_W_TYPE *table_def,
+                   time_t *last_create_time, int error_num)
 {
   uint i;
   my_bool error= FALSE;
@@ -2388,7 +2388,7 @@ table_check_intact(TABLE *table, uint ta
     DBUG_PRINT("info", ("I am suspecting, checking table"));
     if (fields_diff_count)
     {
-      // previous MySQL version
+      /* previous MySQL version */
       error= TRUE;
       if (MYSQL_VERSION_ID > table->s->mysql_version)
       {
@@ -2411,22 +2411,22 @@ table_check_intact(TABLE *table, uint ta
       else
       {
         /*
-          moving from newer mysql to older one -> let's say not an error but
+          Moving from newer mysql to older one -> let's say not an error but
           will check the definition afterwards. If a column was added at the
           end then we don't care much since it's not in the middle.
         */
         error= FALSE;
       }
     }
-    //definitely something has changed
+    /* definitely something has changed */
     char buffer[255];
     for (i=0 ; i < table_f_count; i++, table_def++)
     {      
       String sql_type(buffer, sizeof(buffer), system_charset_info);
       sql_type.length(0);
       /*
-        name changes are not fatal, we use sequence numbers => no prob for us
-        but this can show tampered table or broken table.
+        Name changes are not fatal, we use sequence numbers => no problem
+        for us but this can show tampered table or broken table.
       */
       if (i < table->s->fields)
       {
@@ -2440,7 +2440,7 @@ table_check_intact(TABLE *table, uint ta
         }
                         
         /*
-          IF the type does not match than something is really wrong
+          If the type does not match than something is really wrong
           Check up to length - 1. Why?
           1. datetime -> datetim -> the same
           2. int(11) -> int(11  -> the same

--- 1.148/sql/table.h	2006-08-16 19:55:26 +02:00
+++ 1.149/sql/table.h	2006-08-16 19:55:26 +02:00
@@ -965,9 +965,9 @@ typedef struct st_table_field_w_type
 
 
 my_bool
-table_check_intact(TABLE *table, uint table_f_count,
-                   TABLE_FIELD_W_TYPE *table_def, time_t *last_create_time,
-                   int error_num);
+table_check_intact(TABLE *table, const uint table_f_count,
+                   const TABLE_FIELD_W_TYPE * const table_def,
+                   time_t *last_create_time, int error_num);
 
 static inline my_bitmap_map *tmp_use_all_columns(TABLE *table,
                                                  MY_BITMAP *bitmap)

--- 1.58/sql/events.cc	2006-08-16 19:55:26 +02:00
+++ 1.59/sql/events.cc	2006-08-16 19:55:26 +02:00
@@ -90,7 +90,9 @@ ulong Events::opt_event_scheduler= 2;
     1   s > t
 */
 
-int sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs)
+int
+sortcmp_lex_string(const LEX_STRING s, const LEX_STRING t,
+                   CHARSET_INFO * const cs)
 {
  return cs->coll->strnncollsp(cs, (uchar *) s.str,s.length,
                                   (uchar *) t.str,t.length, 0);
@@ -265,7 +267,7 @@ common_1_lev_code:
 
 int
 Events::open_event_table(THD *thd, enum thr_lock_type lock_type,
-                                   TABLE **table)
+                         TABLE **table)
 {
   return db_repository->open_event_table(thd, lock_type, table);
 }
@@ -277,7 +279,7 @@ Events::open_event_table(THD *thd, enum 
   SYNOPSIS
     Events::create_event()
       thd            [in]  THD
-      et             [in]  Event's data from parsing stage
+      parse_data     [in]  Event's data from parsing stage
       if_not_exists  [in]  Whether IF NOT EXISTS was specified in the DDL
       rows_affected  [out] How many rows were affected
 
@@ -291,18 +293,25 @@ Events::open_event_table(THD *thd, enum 
 */
 
 int
-Events::create_event(THD *thd, Event_parse_data *parse_data, bool if_not_exists,
-                     uint *rows_affected)
+Events::create_event(THD *thd, Event_parse_data * const parse_data,
+                     bool if_not_exists, uint *rows_affected)
 {
   int ret;
   DBUG_ENTER("Events::create_event");
+  if (unlikely(init_state < Events::SYSTEM_TABLES_CHECKED))
+  {
+    DBUG_PRINT("info", ("init_state=%d", init_state));
+    my_error(ER_EVENTS_DB_ERROR, MYF(0));
+    DBUG_RETURN(1);
+  }
 
   pthread_mutex_lock(&LOCK_event_metadata);
   /* On error conditions my_error() is called so no need to handle here */
   if (!(ret= db_repository->create_event(thd, parse_data, if_not_exists,
                                          rows_affected)))
   {
-    if ((ret= event_queue->create_event(thd, parse_data->dbname,
+    if (init_state >= Events::QUEUE_INITIALIZED &&
+        (ret= event_queue->create_event(thd, parse_data->dbname,
                                         parse_data->name)))
     {
       DBUG_ASSERT(ret == OP_LOAD_ERROR);
@@ -321,7 +330,7 @@ Events::create_event(THD *thd, Event_par
   SYNOPSIS
     Events::update_event()
       thd           [in]  THD
-      et            [in]  Event's data from parsing stage
+      parse_data    [in]  Event's data from parsing stage
       rename_to     [in]  Set in case of RENAME TO.
       rows_affected [out] How many rows were affected.
 
@@ -336,19 +345,27 @@ Events::create_event(THD *thd, Event_par
 */
 
 int
-Events::update_event(THD *thd, Event_parse_data *parse_data, sp_name *rename_to,
-                     uint *rows_affected)
+Events::update_event(THD *thd, Event_parse_data * const parse_data,
+                     const sp_name * const rename_to, uint *rows_affected)
 {
   int ret;
   DBUG_ENTER("Events::update_event");
-  LEX_STRING *new_dbname= rename_to? &rename_to->m_db: NULL;
-  LEX_STRING *new_name= rename_to? &rename_to->m_name: NULL;
+  const LEX_STRING * const new_dbname= rename_to ? &rename_to->m_db: NULL;
+  const LEX_STRING * const new_name= rename_to ? &rename_to->m_name: NULL;
+
+  if (unlikely(init_state < Events::SYSTEM_TABLES_CHECKED))
+  {
+    DBUG_PRINT("info", ("init_state=%d", init_state));
+    my_error(ER_EVENTS_DB_ERROR, MYF(0));
+    DBUG_RETURN(1);
+  }
 
   pthread_mutex_lock(&LOCK_event_metadata);
   /* On error conditions my_error() is called so no need to handle here */
   if (!(ret= db_repository->update_event(thd, parse_data, new_dbname, new_name)))
   {
-    if ((ret= event_queue->update_event(thd, parse_data->dbname,
+    if (init_state >= Events::QUEUE_INITIALIZED &&
+        (ret= event_queue->update_event(thd, parse_data->dbname,
                                         parse_data->name, new_dbname, new_name)))
     {
       DBUG_ASSERT(ret == OP_LOAD_ERROR);
@@ -388,13 +405,18 @@ Events::drop_event(THD *thd, LEX_STRING 
 {
   int ret;
   DBUG_ENTER("Events::drop_event");
+  if (unlikely(init_state < Events::SYSTEM_TABLES_CHECKED))
+  {
+    my_error(ER_EVENTS_DB_ERROR, MYF(0));
+    DBUG_RETURN(1);
+  }
 
   pthread_mutex_lock(&LOCK_event_metadata);
   /* On error conditions my_error() is called so no need to handle here */
   if (!(ret= db_repository->drop_event(thd, dbname, name, if_exists,
                                        rows_affected)))
   {
-    if (!only_from_disk)
+    if (init_state >= Events::QUEUE_INITIALIZED && !only_from_disk)
       event_queue->drop_event(thd, dbname, name);
   }
   pthread_mutex_unlock(&LOCK_event_metadata);
@@ -409,27 +431,29 @@ Events::drop_event(THD *thd, LEX_STRING 
     Events::drop_schema_events()
       thd  Thread
       db   ASCIIZ schema name
-
-  RETURN VALUE
-    0   OK
-    !0  Error
 */
 
-int
+void
 Events::drop_schema_events(THD *thd, char *db)
 {
-  int ret= 0;
-  LEX_STRING db_lex= {db, strlen(db)};
+  LEX_STRING const db_lex= { db, strlen(db) };
   
   DBUG_ENTER("Events::drop_schema_events");  
   DBUG_PRINT("enter", ("dropping events from %s", db));
+  if (unlikely(init_state < Events::SYSTEM_TABLES_CHECKED))
+  {
+    DBUG_PRINT("info", ("init_state=%d", init_state));
+    /* Don't send an error message because OK packet has been already sent */
+    DBUG_VOID_RETURN;
+  }
 
   pthread_mutex_lock(&LOCK_event_metadata);
-  event_queue->drop_schema_events(thd, db_lex);
-  ret= db_repository->drop_schema_events(thd, db_lex);
+  if (init_state >= Events::QUEUE_INITIALIZED)
+    event_queue->drop_schema_events(thd, db_lex);
+  db_repository->drop_schema_events(thd, db_lex);
   pthread_mutex_unlock(&LOCK_event_metadata);
 
-  DBUG_RETURN(ret);
+  DBUG_VOID_RETURN;
 }
 
 
@@ -438,8 +462,8 @@ Events::drop_schema_events(THD *thd, cha
 
   SYNOPSIS
     Events::show_create_event()
-      thd        THD
-      spn        the name of the event (db, name)
+      thd   Thread context
+      spn   The name of the event (db, name)
 
   RETURN VALUE
     0  OK
@@ -447,7 +471,7 @@ Events::drop_schema_events(THD *thd, cha
 */
 
 int
-Events::show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name)
+Events::show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name) const
 {
   CHARSET_INFO *scs= system_charset_info;
   int ret;
@@ -455,6 +479,12 @@ Events::show_create_event(THD *thd, LEX_
 
   DBUG_ENTER("Events::show_create_event");
   DBUG_PRINT("enter", ("name: %s@%s", dbname.str, name.str));
+  if (unlikely(init_state < Events::SYSTEM_TABLES_CHECKED))
+  {
+    DBUG_PRINT("info", ("init_state=%d", init_state));
+    my_error(ER_EVENTS_DB_ERROR, MYF(0));
+    DBUG_RETURN(1);
+  }
 
   ret= db_repository->load_named_event(thd, dbname, name, et);
 
@@ -481,8 +511,8 @@ Events::show_create_event(THD *thd, LEX_
 
     field_list.push_back(new Item_empty_string("sql_mode", sql_mode_len));
 
-    field_list.
-        push_back(new Item_empty_string("Create Event", show_str.length()));
+    field_list.push_back(new Item_empty_string("Create Event",
+                                               show_str.length()));
 
     if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
                                            Protocol::SEND_EOF))
@@ -511,7 +541,7 @@ err:
 
   SYNOPSIS
     Events::fill_schema_events()
-      thd     Thread
+      thd     Thread context
       tables  The schema table
       cond    Unused
 
@@ -524,7 +554,14 @@ int
 Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
 {
   char *db= NULL;
+  Events *myself= get_instance();
   DBUG_ENTER("Events::fill_schema_events");
+  if (unlikely(myself->init_state < Events::SYSTEM_TABLES_CHECKED))
+  {
+    DBUG_PRINT("info", ("init_state=%d", myself->init_state));
+    my_error(ER_EVENTS_DB_ERROR, MYF(0));
+    DBUG_RETURN(1);
+  }
   /*
     If it's SHOW EVENTS then thd->lex->select_lex.db is guaranteed not to
     be NULL. Let's do an assert anyway.
@@ -537,8 +574,7 @@ Events::fill_schema_events(THD *thd, TAB
       DBUG_RETURN(1);
     db= thd->lex->select_lex.db;
   }
-  DBUG_RETURN(get_instance()->db_repository->
-                                      fill_schema_events(thd, tables, db));
+  DBUG_RETURN(myself->db_repository->fill_schema_events(thd, tables, db));
 }
 
 
@@ -552,31 +588,64 @@ Events::fill_schema_events(THD *thd, TAB
     This function is not synchronized.
 
   RETURN VALUE
-    0  OK
-    1  Error in case the scheduler can't start
+    FALSE  OK
+    TRUE   Error in case the scheduler can't start
 */
 
 bool
 Events::init()
 {
-  int res;
+  THD *thd;
+  bool res= FALSE;
   DBUG_ENTER("Events::init");
-  if (event_queue->init_queue(db_repository, scheduler))
+
+  /*
+    We need a temporary THD during boot.
+  */
+  if (!(thd= new THD()))
   {
-    sql_print_information("SCHEDULER: Error while loading from disk.");
-    DBUG_RETURN(TRUE);
+    res= TRUE;
+    goto end;
+  }
+  /*
+    The thread stack does not start from this function but we cannot
+    guess the real value. So better some value that doesn't assert than
+    no value.
+  */
+  thd->thread_stack= (char*) &thd;
+  thd->store_globals();
+
+  if (check_system_tables(thd))
+  {
+    sql_print_error("SCHEDULER: The system tables are damaged. "
+                    "The scheduler subsystem will be unusable during this run.");
+    goto end;
   }
+  init_state= Events::SYSTEM_TABLES_CHECKED;
+
+  if (event_queue->init_queue(thd, db_repository, scheduler))
+  {
+    sql_print_error("SCHEDULER: Error while loading from disk.");
+    goto end;
+  }
+  init_state= Events::QUEUE_INITIALIZED;
+
   scheduler->init_scheduler(event_queue);
+  init_state= Events::SCHEDULER_INITIALIZED;
 
-  /* it should be an assignment! */
   if (opt_event_scheduler)
   {
     DBUG_ASSERT(opt_event_scheduler == 1 || opt_event_scheduler == 2);
     if (opt_event_scheduler == 1)
-      DBUG_RETURN(scheduler->start());
+      res= scheduler->start();
   }
 
-  DBUG_RETURN(FALSE);
+end:
+  delete thd;
+  /* Remember that we don't have a THD */
+  my_pthread_setspecific_ptr(THR_THD,  NULL);
+
+  DBUG_RETURN(res);
 }
 
 
@@ -594,11 +663,15 @@ void
 Events::deinit()
 {
   DBUG_ENTER("Events::deinit");
+  DBUG_PRINT("info", ("init_state=%d", init_state));
 
-  scheduler->stop();
-  scheduler->deinit_scheduler();
-
-  event_queue->deinit_queue();
+  if (likely(init_state >= Events::SCHEDULER_INITIALIZED))
+  {
+    scheduler->stop();
+    scheduler->deinit_scheduler();
+  }
+  if (likely(init_state >= Events::QUEUE_INITIALIZED))
+    event_queue->deinit_queue();
 
   DBUG_VOID_RETURN;
 }
@@ -610,6 +683,14 @@ Events::deinit()
   SYNOPSIS
     Events::init_mutexes()
       thd  Thread
+
+  NOTES
+    db_repository, event_queue and scheduler are allocated on the
+    stack to get a facade of class Events which won't lead to
+    recompilation of the clients that use events.h every time some
+    internal class has been changed. If they were static parts, and
+    not static pointers, then a change of the interface of one of the
+    classes will lead to recompile of every client of Events.
 */
 
 void
@@ -670,13 +751,23 @@ Events::dump_internal_status(THD *thd)
   Protocol *protocol= thd->protocol;
   List<Item> field_list;
 
+  if (unlikely(init_state < Events::QUEUE_INITIALIZED))
+  {
+    DBUG_PRINT("info", ("init_state=%d", init_state));
+    my_error(ER_EVENTS_DB_ERROR, MYF(0));
+    DBUG_RETURN(TRUE);
+  }
+
   field_list.push_back(new Item_empty_string("Name", 30));
   field_list.push_back(new Item_empty_string("Value",20));
   if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
                                          Protocol::SEND_EOF))
     DBUG_RETURN(TRUE);
 
-  if (scheduler->dump_internal_status(thd) ||
+  if (scheduler->dump_internal_status(thd))
+    DBUG_RETURN(TRUE);
+
+  if (init_state < Events::SCHEDULER_INITIALIZED ||
       event_queue->dump_internal_status(thd))
     DBUG_RETURN(TRUE);
 
@@ -700,6 +791,12 @@ bool
 Events::start_execution_of_events()
 {
   DBUG_ENTER("Events::start_execution_of_events");
+  if (unlikely(init_state < Events::SCHEDULER_INITIALIZED))
+  {
+    DBUG_PRINT("info", ("init_state=%d", init_state));
+    my_error(ER_EVENTS_DB_ERROR, MYF(0));
+    DBUG_RETURN(TRUE);
+  }
   DBUG_RETURN(scheduler->start());
 }
 
@@ -721,6 +818,12 @@ bool
 Events::stop_execution_of_events()
 {
   DBUG_ENTER("Events::stop_execution_of_events");
+  if (unlikely(init_state < Events::SCHEDULER_INITIALIZED))
+  {
+    DBUG_PRINT("info", ("init_state=%d", init_state));
+    my_error(ER_EVENTS_DB_ERROR, MYF(0));
+    DBUG_RETURN(TRUE);
+  }
   DBUG_RETURN(scheduler->stop());
 }
 
@@ -737,8 +840,87 @@ Events::stop_execution_of_events()
 */
 
 bool
-Events::is_started()
+Events::is_execution_of_events_started() const
 {
-  DBUG_ENTER("Events::is_started");
+  DBUG_ENTER("Events::is_execution_of_events_started");
+  if (unlikely(init_state < Events::SCHEDULER_INITIALIZED))
+  {
+    DBUG_PRINT("info", ("init_state=%d", init_state));
+    my_error(ER_EVENTS_DB_ERROR, MYF(0));
+    DBUG_RETURN(TRUE);
+  }
   DBUG_RETURN(scheduler->get_state() == Event_scheduler::RUNNING);
+}
+
+
+
+/*
+  Opens mysql.db and mysql.user and checks whether:
+    1. mysql.db has column Event_priv at column 20 (0 based);
+    2. mysql.user has column Event_priv at column 29 (0 based);
+
+  SYNOPSIS
+    Events::check_system_tables()
+      thd  Thread
+
+  RETURN VALUE
+    FALSE  OK
+    TRUE   Error
+*/
+
+bool
+Events::check_system_tables(THD *thd)
+{
+  TABLE_LIST tables;
+  bool not_used;
+  Open_tables_state backup;
+  bool ret= FALSE;
+
+  DBUG_ENTER("Events::check_system_tables");
+  DBUG_PRINT("enter", ("thd=0x%lx", thd));
+
+  thd->reset_n_backup_open_tables_state(&backup);
+
+  bzero((char*) &tables, sizeof(tables));
+  tables.db= (char*) "mysql";
+  tables.table_name= tables.alias= (char*) "db";
+  tables.lock_type= TL_READ;
+
+  if ((ret= simple_open_n_lock_tables(thd, &tables)))
+  {
+    sql_print_error("SCHEDULER: Cannot open mysql.db");
+    ret= TRUE;
+  }
+  ret= table_check_intact(tables.table, MYSQL_DB_FIELD_COUNT,
+                          mysql_db_table_fields, &mysql_db_table_last_check,
+                          ER_CANNOT_LOAD_FROM_TABLE);
+  close_thread_tables(thd);
+
+  bzero((char*) &tables, sizeof(tables));
+  tables.db= (char*) "mysql";
+  tables.table_name= tables.alias= (char*) "user";
+  tables.lock_type= TL_READ;
+
+  if (simple_open_n_lock_tables(thd, &tables))
+  {
+    sql_print_error("SCHEDULER: Cannot open mysql.user");
+    ret= TRUE;
+  }
+  else
+  {
+    if (tables.table->s->fields < 29 ||
+        strncmp(tables.table->field[29]->field_name,
+                STRING_WITH_LEN("Event_priv")))
+    {
+      sql_print_error("mysql.user has no `Event_priv` column at position %d",
+                      29);
+      ret= TRUE;
+    }
+    close_thread_tables(thd);
+  }
+
+end:
+  thd->restore_backup_open_tables_state(&backup);
+
+  DBUG_RETURN(ret);
 }

--- 1.43/sql/events.h	2006-08-16 19:55:26 +02:00
+++ 1.44/sql/events.h	2006-08-16 19:55:26 +02:00
@@ -36,66 +36,66 @@ enum enum_events_error_code
 };
 
 int
-sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs);
-
+sortcmp_lex_string(const LEX_STRING s, const LEX_STRING t,
+                   CHARSET_INFO * const cs);
 
 class Events
 {
 public:
-  friend class Event_queue_element;
   /*
     Quite NOT the best practice and will be removed once
     Event_timed::drop() and Event_timed is fixed not do drop directly
     or other scheme will be found.
   */
+  friend class Event_queue_element;
 
   static ulong opt_event_scheduler;
   static TYPELIB opt_typelib;
 
   bool
   init();
-  
+
   void
   deinit();
 
   void
   init_mutexes();
-  
+
   void
   destroy_mutexes();
 
   bool
   start_execution_of_events();
-  
+
   bool
   stop_execution_of_events();
-  
+
   bool
-  is_started();
+  is_execution_of_events_started() const;
 
-  static Events*
+  static Events *
   get_instance();
 
   int
-  create_event(THD *thd, Event_parse_data *parse_data, bool if_exists,
-               uint *rows_affected);
+  create_event(THD *thd, Event_parse_data * const parse_data,
+               bool if_exists, uint *rows_affected);
 
   int
-  update_event(THD *thd, Event_parse_data *parse_data, sp_name *rename_to,
-               uint *rows_affected);
+  update_event(THD *thd, Event_parse_data * const parse_data,
+               const sp_name * const rename_to, uint *rows_affected);
 
   int
   drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists,
              uint *rows_affected, bool only_from_disk);
 
-  int
+  void
   drop_schema_events(THD *thd, char *db);
 
   int
   open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
 
   int
-  show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name);
+  show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name) const;
 
   /* Needed for both SHOW CREATE EVENT and INFORMATION_SCHEMA */
   static int
@@ -104,23 +104,37 @@ public:
 
   static int
   fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */);
-  
+
   bool
   dump_internal_status(THD *thd);
 
 private:
+  enum enum_events_init_state
+  {
+    UNINITIALIZED= 0,
+    SYSTEM_TABLES_CHECKED,
+    QUEUE_INITIALIZED,
+    SCHEDULER_INITIALIZED
+  };
+
+  bool
+  check_system_tables(THD *thd);
+
   /* Singleton DP is used */
-  Events(){}
+  Events():init_state(Events::UNINITIALIZED)
+  {}
   ~Events(){}
 
   /* Singleton instance */
   static Events singleton;
 
   Event_queue         *event_queue;
-  Event_scheduler  *scheduler;
+  Event_scheduler     *scheduler;
   Event_db_repository *db_repository;
 
-  pthread_mutex_t LOCK_event_metadata;  
+  enum enum_events_init_state init_state;
+
+  pthread_mutex_t LOCK_event_metadata;
 
   /* Prevent use of these */
   Events(const Events &);

--- 1.12/sql/event_db_repository.cc	2006-08-16 19:55:26 +02:00
+++ 1.13/sql/event_db_repository.cc	2006-08-16 19:55:26 +02:00
@@ -22,14 +22,12 @@
 #include "sp.h"
 #include "sp_head.h"
 
-#define EVEX_DB_FIELD_LEN 64
-#define EVEX_NAME_FIELD_LEN 64
-
 
+static
 time_t mysql_event_last_create_time= 0L;
 
 static
-TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] =
+TABLE_FIELD_W_TYPE const event_table_fields[ET_FIELD_COUNT] =
 {
   {
     {(char *) STRING_WITH_LEN("db")},
@@ -250,20 +248,21 @@ err_truncate:
 /*
   Performs an index scan of event_table (mysql.event) and fills schema_table.
 
-  Synopsis
+  SYNOPSIS
     Event_db_repository::index_read_for_db_for_i_s()
       thd          Thread
       schema_table The I_S.EVENTS table
       event_table  The event table to use for loading (mysql.event)
 
-  Returns
+  RETURN VALUE
     0  OK
     1  Error
 */
 
-int
+bool
 Event_db_repository::index_read_for_db_for_i_s(THD *thd, TABLE *schema_table,
-                                               TABLE *event_table, char *db)
+                                               TABLE *event_table,
+                                               const char *db)
 {
   int ret=0;
   CHARSET_INFO *scs= system_charset_info;
@@ -305,33 +304,33 @@ Event_db_repository::index_read_for_db_f
   event_table->file->ha_index_end(); 
   /*  ret is guaranteed to be != 0 */
   if (ret == HA_ERR_END_OF_FILE || ret == HA_ERR_KEY_NOT_FOUND)
-    DBUG_RETURN(0);
-  DBUG_RETURN(1);
+    DBUG_RETURN(FALSE);
+  DBUG_RETURN(TRUE);
 }
 
 
 /*
   Performs a table scan of event_table (mysql.event) and fills schema_table.
 
-  Synopsis
+  SYNOPSIS
     Events_db_repository::table_scan_all_for_i_s()
       thd          Thread
       schema_table The I_S.EVENTS in memory table
       event_table  The event table to use for loading.
 
-  Returns
-    0  OK
-    1  Error
+  RETURN VALUE
+    FALSE  OK
+    TRUE   Error
 */
 
-int
+bool
 Event_db_repository::table_scan_all_for_i_s(THD *thd, TABLE *schema_table,
                                             TABLE *event_table)
 {
   int ret;
   READ_RECORD read_record_info;
-
   DBUG_ENTER("Event_db_repository::table_scan_all_for_i_s");
+
   init_read_record(&read_record_info, thd, event_table, NULL, 1, 0);
 
   /*
@@ -350,7 +349,7 @@ Event_db_repository::table_scan_all_for_
   end_read_record(&read_record_info);
 
   /*  ret is guaranteed to be != 0 */
-  DBUG_RETURN(ret == -1? 0:1);
+  DBUG_RETURN(ret == -1? FALSE:TRUE);
 }
 
 
@@ -358,19 +357,20 @@ Event_db_repository::table_scan_all_for_
   Fills I_S.EVENTS with data loaded from mysql.event. Also used by
   SHOW EVENTS
 
-  Synopsis
+  SYNOPSIS
     Event_db_repository::fill_schema_events()
       thd     Thread
       tables  The schema table
       db      If not NULL then get events only from this schema
 
-  Returns
-    0  OK
-    1  Error
+  RETURN VALUE
+    FALSE  OK
+    TRUE   Error
 */
 
-int
-Event_db_repository::fill_schema_events(THD *thd, TABLE_LIST *tables, char *db)
+bool
+Event_db_repository::fill_schema_events(THD *thd, TABLE_LIST *tables,
+                                        const char *db)
 {
   TABLE *schema_table= tables->table;
   TABLE *event_table= NULL;
@@ -385,7 +385,7 @@ Event_db_repository::fill_schema_events(
   {
     sql_print_error("Table mysql.event is damaged.");
     thd->restore_backup_open_tables_state(&backup);
-    DBUG_RETURN(1);
+    DBUG_RETURN(TRUE);
   }
 
   /*
@@ -455,20 +455,20 @@ Event_db_repository::open_event_table(TH
 
 
 /*
-   Checks parameters which we got from the parsing phase.
+  Checks parameters which we got from the parsing phase.
 
-   SYNOPSIS
-     check_parse_params()
-       thd            THD
-       et             event's data
+  SYNOPSIS
+    check_parse_params()
+      thd         Thread context
+      parse_data  Event's data
   
-   RETURNS
-     0                OK
-     EVEX_BAD_PARAMS  Error (reported)
+  RETURN VALUE
+    FALSE  OK
+    TRUE   Error (reported)
 */
 
-static int
-check_parse_params(THD *thd, Event_parse_data *parse_data)
+static bool
+check_parse_params(THD *thd, Event_parse_data * const parse_data)
 {
   const char *pos= NULL;
   Item *bad_item;
@@ -477,24 +477,16 @@ check_parse_params(THD *thd, Event_parse
   DBUG_ENTER("check_parse_params");
 
   if (parse_data->check_parse_data(thd))
-    DBUG_RETURN(EVEX_BAD_PARAMS);
-
-  if (!parse_data->dbname.str ||
-      (thd->lex->sql_command == SQLCOM_ALTER_EVENT && thd->lex->spname &&
-       !thd->lex->spname->m_db.str))
-  {
-    my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
-    DBUG_RETURN(EVEX_BAD_PARAMS);
-  }
+    DBUG_RETURN(TRUE);
 
   if (check_access(thd, EVENT_ACL, parse_data->dbname.str, 0, 0, 0,
                    is_schema_db(parse_data->dbname.str)) ||
       (thd->lex->sql_command == SQLCOM_ALTER_EVENT && thd->lex->spname &&
        (check_access(thd, EVENT_ACL, thd->lex->spname->m_db.str, 0, 0, 0,
                      is_schema_db(thd->lex->spname->m_db.str)))))
-    DBUG_RETURN(EVEX_BAD_PARAMS);
+    DBUG_RETURN(TRUE);
 
-  DBUG_RETURN(0);
+  DBUG_RETURN(FALSE);
 }
 
 
@@ -504,7 +496,7 @@ check_parse_params(THD *thd, Event_parse
   SYNOPSIS
     Event_db_repository::create_event()
       thd             [in]  THD
-      et              [in]  Object containing info about the event
+      parse_data      [in]  Object containing info about the event
       create_if_not   [in]  Whether to generate anwarning in case event exists
       rows_affected   [out] How many rows were affected
 
@@ -517,8 +509,8 @@ check_parse_params(THD *thd, Event_parse
     ::update_event. The name of the event is inside "et".
 */
 
-int
-Event_db_repository::create_event(THD *thd, Event_parse_data *parse_data,
+bool
+Event_db_repository::create_event(THD *thd, Event_parse_data * const parse_data,
                                   my_bool create_if_not, uint *rows_affected)
 {
   int ret= 0;
@@ -531,6 +523,9 @@ Event_db_repository::create_event(THD *t
   DBUG_ENTER("Event_db_repository::create_event");
 
   *rows_affected= 0;
+  if (check_parse_params(thd, parse_data))
+    goto err;
+
   DBUG_PRINT("info", ("open mysql.event for update"));
   if (open_event_table(thd, TL_WRITE, &table))
   {
@@ -538,8 +533,6 @@ Event_db_repository::create_event(THD *t
     goto err;
   }
 
-  if (check_parse_params(thd, parse_data))
-    goto err;
 
   DBUG_PRINT("info", ("name: %.*s", parse_data->name.length,
              parse_data->name.str));
@@ -570,16 +563,17 @@ Event_db_repository::create_event(THD *t
 
   if (system_charset_info->cset->
         numchars(system_charset_info, parse_data->dbname.str,
-                 parse_data->dbname.str +
-                 parse_data->dbname.length) > EVEX_DB_FIELD_LEN)
+                 parse_data->dbname.str + parse_data->dbname.length) >
+      table->field[ET_FIELD_DB]->char_length())
   {
     my_error(ER_TOO_LONG_IDENT, MYF(0), parse_data->dbname.str);
     goto err;
   }
+
   if (system_charset_info->cset->
         numchars(system_charset_info, parse_data->name.str,
-                 parse_data->name.str +
-                 parse_data->name.length) > EVEX_DB_FIELD_LEN)
+                 parse_data->name.str + parse_data->name.length) >
+      table->field[ET_FIELD_NAME]->char_length())
   {
     my_error(ER_TOO_LONG_IDENT, MYF(0), parse_data->name.str);
     goto err;
@@ -622,36 +616,18 @@ ok:
   if (dbchanged)
     (void) mysql_change_db(thd, old_db.str, 1);
   /*
-    When valgrinded, the following call may lead to the following error:
-    
-    Syscall param pwrite64(buf) points to uninitialised byte(s)
-      at 0x406003B: do_pwrite64 (in /lib/tls/libpthread.so.0)
-      by 0x40600EF: pwrite64 (in /lib/tls/libpthread.so.0)
-      by 0x856FF74: my_pwrite (my_pread.c:146)
-      by 0x85734E1: flush_cached_blocks (mf_keycache.c:2280)
-    ....
-    Address 0x6618110 is 56 bytes inside a block of size 927,772 alloc'd
-     at 0x401C451: malloc (vg_replace_malloc.c:149)
-      by 0x8578CDC: _mymalloc (safemalloc.c:138)
-      by 0x858E5E2: my_large_malloc (my_largepage.c:65)
-      by 0x8570634: init_key_cache (mf_keycache.c:343)
-      by 0x82EDA51: ha_init_key_cache(char const*, st_key_cache*) (handler.cc:2509)
-      by 0x8212071: process_key_caches(int (*)(char const*, st_key_cache*))
-                                                                  (set_var.cc:3824)
-      by 0x8206D75: init_server_components() (mysqld.cc:3304)
-      by 0x8207163: main (mysqld.cc:3578)
-
-    I think it is safe not to think about it.
+    This statement may cause a spooky valgrind warning at startup
+    inside init_key_cache on my system (ahristov, 2006/08/10) 
   */
   close_thread_tables(thd);
-  DBUG_RETURN(0);
+  DBUG_RETURN(FALSE);
 
 err:
   if (dbchanged)
     (void) mysql_change_db(thd, old_db.str, 1);
   if (table)
     close_thread_tables(thd);
-  DBUG_RETURN(EVEX_GENERAL_ERROR);
+  DBUG_RETURN(TRUE);
 }
 
 
@@ -665,8 +641,8 @@ err:
       et       event's data
 
   RETURN VALUE
-    0  OK
-    EVEX_GENERAL_ERROR  Error occured and reported
+    FALSE  OK
+    TRUE   Error (reported)
 
   NOTES
     sp_name is passed since this is the name of the event to
@@ -674,12 +650,12 @@ err:
 */
 
 bool
-Event_db_repository::update_event(THD *thd, Event_parse_data *parse_data,
-                                  LEX_STRING *new_dbname, LEX_STRING *new_name)
+Event_db_repository::update_event(THD *thd, Event_parse_data * const parse_data,
+                                  const LEX_STRING * const new_dbname,
+                                  const LEX_STRING * const new_name)
 {
   CHARSET_INFO *scs= system_charset_info;
   TABLE *table= NULL;
-  int ret;
   DBUG_ENTER("Event_db_repository::update_event");
 
   if (open_event_table(thd, TL_WRITE, &table))
@@ -698,7 +674,7 @@ Event_db_repository::update_event(THD *t
     DBUG_PRINT("info", ("rename to: %s@%s", new_dbname->str, new_name->str));
 
   /* first look whether we overwrite */
-  if (new_dbname)
+  if (new_name)
   {
     if (!sortcmp_lex_string(parse_data->name, *new_name, scs) &&
         !sortcmp_lex_string(parse_data->dbname, *new_dbname, scs))
@@ -747,9 +723,10 @@ Event_db_repository::update_event(THD *t
   if (end_active_trans(thd))
     goto err;
 
-  if (table->file->ha_update_row(table->record[1], table->record[0]))
+  int res;
+  if ((res= table->file->ha_update_row(table->record[1], table->record[0])))
   {
-    my_error(ER_EVENT_STORE_FAILED, MYF(0), parse_data->name.str, ret);
+    my_error(ER_EVENT_STORE_FAILED, MYF(0), parse_data->name.str, res);
     goto err;
   }
 
@@ -782,8 +759,9 @@ err:
 */
 
 bool
-Event_db_repository::drop_event(THD *thd, LEX_STRING db, LEX_STRING name,
-                                bool drop_if_exists, uint *rows_affected)
+Event_db_repository::drop_event(THD *thd, const LEX_STRING db,
+                                const LEX_STRING name, bool drop_if_exists,
+                                uint *rows_affected)
 {
   TABLE *table= NULL;
   Open_tables_state backup;
@@ -844,8 +822,8 @@ done:
 */
 
 bool
-Event_db_repository::find_named_event(THD *thd, LEX_STRING db, LEX_STRING name,
-                                     TABLE *table)
+Event_db_repository::find_named_event(THD *thd, const LEX_STRING db,
+                                      const LEX_STRING name, TABLE * const table)
 {
   byte key[MAX_KEY_LENGTH];
   DBUG_ENTER("Event_db_repository::find_named_event");
@@ -887,16 +865,14 @@ Event_db_repository::find_named_event(TH
     Event_db_repository::drop_schema_events()
       thd     Thread
       schema  The database to clean from events
-
-  RETURN VALUE
-    0  OK
-   !0  Error (Reported)
 */
 
-int
+void
 Event_db_repository::drop_schema_events(THD *thd, LEX_STRING schema)
 {
-  return drop_events_by_field(thd, ET_FIELD_DB, schema);
+  DBUG_ENTER("Event_db_repository::drop_schema_events");
+  drop_events_by_field(thd, ET_FIELD_DB, schema);
+  DBUG_VOID_RETURN;
 }
 
 
@@ -909,28 +885,29 @@ Event_db_repository::drop_schema_events(
       table       mysql.event TABLE
       field       Which field of the row to use for matching
       field_value The value that should match
-
-  RETURN VALUE
-     0  OK
-    !0  Error from ha_delete_row
 */
 
-int
+void
 Event_db_repository::drop_events_by_field(THD *thd,  
                                           enum enum_events_table_field field,
-                                          LEX_STRING field_value)
+                                          const LEX_STRING field_value)
 {
   int ret= 0;
   TABLE *table= NULL;
-  Open_tables_state backup;
   READ_RECORD read_record_info;
   DBUG_ENTER("Event_db_repository::drop_events_by_field");  
   DBUG_PRINT("enter", ("field=%d field_value=%s", field, field_value.str));
 
   if (open_event_table(thd, TL_WRITE, &table))
   {
-    my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
-    DBUG_RETURN(1);
+    /*
+      Currently being used only for DROP DATABASE - In this case we don't need
+      error message since the OK packet has been sent. But for DROP USER we
+      could need it.
+
+      my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
+    */
+    DBUG_VOID_RETURN;
   }
 
   /* only enabled events are in memory, so we go now and delete the rest */
@@ -939,22 +916,20 @@ Event_db_repository::drop_events_by_fiel
   {
     char *et_field= get_field(thd->mem_root, table->field[field]);
 
-    LEX_STRING et_field_lex= {et_field, strlen(et_field)};
+    LEX_STRING et_field_lex= { et_field, strlen(et_field) };
     DBUG_PRINT("info", ("Current event %s name=%s", et_field,
                get_field(thd->mem_root, table->field[ET_FIELD_NAME])));
 
     if (!sortcmp_lex_string(et_field_lex, field_value, system_charset_info))
     {
       DBUG_PRINT("info", ("Dropping"));
-      if ((ret= table->file->ha_delete_row(table->record[0])))
-        my_error(ER_EVENT_DROP_FAILED, MYF(0),
-                 get_field(thd->mem_root, table->field[ET_FIELD_NAME]));
+      ret= table->file->ha_delete_row(table->record[0]);
     }
   }
   end_read_record(&read_record_info);
-  thd->version--;   /* Force close to free memory */
+  close_thread_tables(thd);
 
-  DBUG_RETURN(ret);
+  DBUG_VOID_RETURN;
 }
 
 
@@ -964,10 +939,10 @@ Event_db_repository::drop_events_by_fiel
 
   SYNOPSIS
     Event_db_repository::load_named_event()
-      thd      [in]  THD
+      thd      [in]  Thread context
       dbname   [in]  Event's db name
       name     [in]  Event's name
-      etn_new  [out] The loaded event
+      etn      [out] The loaded event
 
   RETURN VALUE
     FALSE  OK
@@ -975,8 +950,9 @@ Event_db_repository::drop_events_by_fiel
 */
 
 bool
-Event_db_repository::load_named_event(THD *thd, LEX_STRING dbname,
-                                      LEX_STRING name, Event_basic *etn)
+Event_db_repository::load_named_event(THD *thd, const LEX_STRING dbname,
+                                      const LEX_STRING name,
+                                      Event_basic * const etn)
 {
   TABLE *table= NULL;
   int ret= 0;

--- 1.8/sql/event_db_repository.h	2006-08-16 19:55:26 +02:00
+++ 1.9/sql/event_db_repository.h	2006-08-16 19:55:26 +02:00
@@ -47,9 +47,6 @@ events_table_index_read_for_db(THD *thd,
 int
 events_table_scan_all(THD *thd, TABLE *schema_table, TABLE *event_table);
 
-int
-fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */);
-
 class Event_basic;
 class Event_parse_data;
 
@@ -58,43 +55,46 @@ class Event_db_repository
 public:
   Event_db_repository(){}
 
-  int
-  create_event(THD *thd, Event_parse_data *parse_data, my_bool create_if_not,
-               uint *rows_affected);
+  bool
+  create_event(THD *thd, Event_parse_data * const parse_data,
+               my_bool create_if_not, uint *rows_affected);
 
   bool
-  update_event(THD *thd, Event_parse_data *parse_data, LEX_STRING *new_dbname,
-               LEX_STRING *new_name);
+  update_event(THD *thd, Event_parse_data * const parse_data,
+               const LEX_STRING * const new_dbname,
+               const LEX_STRING * const new_name);
 
   bool 
-  drop_event(THD *thd, LEX_STRING db, LEX_STRING name, bool drop_if_exists,
-             uint *rows_affected);
+  drop_event(THD *thd, const LEX_STRING db, const LEX_STRING name,
+             bool drop_if_exists, uint *rows_affected);
 
-  int
-  drop_schema_events(THD *thd, LEX_STRING schema);
+  void
+  drop_schema_events(THD *thd, const LEX_STRING schema);
 
   bool
-  find_named_event(THD *thd, LEX_STRING db, LEX_STRING name, TABLE *table);
+  find_named_event(THD *thd, const LEX_STRING db, const LEX_STRING name,
+                   TABLE * const table);
 
   bool
-  load_named_event(THD *thd, LEX_STRING dbname, LEX_STRING name, Event_basic *et);
+  load_named_event(THD *thd, const LEX_STRING dbname, const LEX_STRING name,
+                   Event_basic * const et);
 
 
   int
   open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
 
-  int
-  fill_schema_events(THD *thd, TABLE_LIST *tables, char *db);
+  bool
+  fill_schema_events(THD *thd, TABLE_LIST *tables, const char *db);
 
 private:
-  int
+  void
   drop_events_by_field(THD *thd, enum enum_events_table_field field,
-                       LEX_STRING field_value);
-  int
+                       const LEX_STRING field_value);
+  bool
   index_read_for_db_for_i_s(THD *thd, TABLE *schema_table, TABLE *event_table,
-                            char *db);
+                            const char *db);
 
-  int
+  bool
   table_scan_all_for_i_s(THD *thd, TABLE *schema_table, TABLE *event_table);
 
   static bool

--- 1.11/sql/event_queue.cc	2006-08-16 19:55:26 +02:00
+++ 1.12/sql/event_queue.cc	2006-08-16 19:55:26 +02:00
@@ -73,35 +73,6 @@ event_queue_element_compare_q(void *vptr
 }
 
 
-pthread_handler_t
-event_queue_loader_thread(void *arg)
-{
-  /* needs to be first for thread_stack */
-  THD *thd= (THD *)((struct event_queue_param *) arg)->thd;
-  struct event_queue_param *param= (struct event_queue_param *) arg;
-  thd->thread_stack= (char *) &thd;
-
-  if (post_init_event_thread(thd))
-    goto end;
-
-  DBUG_ENTER("event_queue_loader_thread");
-
-
-  pthread_mutex_lock(&param->LOCK_loaded);
-  param->queue->check_system_tables(thd);
-  param->queue->load_events_from_db(thd);
-
-  param->loading_finished= TRUE;
-  pthread_cond_signal(&param->COND_loaded);
-
-  pthread_mutex_unlock(&param->LOCK_loaded);
-
-end:
-  deinit_event_thread(thd);
-  DBUG_RETURN(0);                               // Against gcc warnings
-}
-
-
 /*
   Constructor of class Event_queue.
 
@@ -150,7 +121,12 @@ Event_queue::deinit_mutexes()
 
 
 /*
-  Inits the queue
+  This is a queue's constructor. Until this method is called, the
+  queue is unusable.  We don't use a C++ constructor instead in
+  order to be able to check the return value. The queue is
+  initialized once at server startup.  Initialization can fail in
+  case of a failure reading events from the database or out of
+  memory.
 
   SYNOPSIS
     Event_queue::init()
@@ -161,9 +137,9 @@ Event_queue::deinit_mutexes()
 */
 
 bool
-Event_queue::init_queue(Event_db_repository *db_repo, Event_scheduler *sched)
+Event_queue::init_queue(THD *thd, Event_db_repository *db_repo,
+                        Event_scheduler *sched)
 {
-  THD *new_thd;
   pthread_t th;
   bool res;
   struct event_queue_param *event_queue_param_value= NULL;
@@ -186,43 +162,16 @@ Event_queue::init_queue(Event_db_reposit
   if (sizeof(my_time_t) != sizeof(time_t))
   {
     sql_print_error("SCHEDULER: sizeof(my_time_t) != sizeof(time_t) ."
-                    "The scheduler may not work correctly. Stopping.");
+                    "The scheduler may not work correctly. Stopping");
     DBUG_ASSERT(0);
     goto err;
   }
 
-  if (!(new_thd= new THD))
-    goto err;
-
-  pre_init_event_thread(new_thd);
-  new_thd->security_ctx->set_user((char*)"event_scheduler_loader");
-
-  event_queue_param_value= (struct event_queue_param *)
-                          my_malloc(sizeof(struct event_queue_param), MYF(0));
-
-  event_queue_param_value->thd= new_thd;
-  event_queue_param_value->queue= this;
-  event_queue_param_value->loading_finished= FALSE;
-  pthread_mutex_init(&event_queue_param_value->LOCK_loaded, MY_MUTEX_INIT_FAST);
-  pthread_cond_init(&event_queue_param_value->COND_loaded, NULL);
-
-  pthread_mutex_lock(&event_queue_param_value->LOCK_loaded);
-  DBUG_PRINT("info", ("Forking new thread for scheduduler. THD=0x%lx", new_thd));
-  if (!(res= pthread_create(&th, &connection_attrib, event_queue_loader_thread,
-                            (void*)event_queue_param_value)))
-  {
-    do {
-      pthread_cond_wait(&event_queue_param_value->COND_loaded,
-                        &event_queue_param_value->LOCK_loaded);
-    } while (event_queue_param_value->loading_finished == FALSE);
-  }
-
-  pthread_mutex_unlock(&event_queue_param_value->LOCK_loaded);
-  pthread_mutex_destroy(&event_queue_param_value->LOCK_loaded);
-  pthread_cond_destroy(&event_queue_param_value->COND_loaded);
-  my_free((char *)event_queue_param_value, MYF(0));
-
+  res= load_events_from_db(thd);
   UNLOCK_QUEUE_DATA();
+  if (res)
+    deinit_queue();
+
   DBUG_RETURN(res);
 
 err:
@@ -267,7 +216,8 @@ Event_queue::deinit_queue()
 */
 
 int
-Event_queue::create_event(THD *thd, LEX_STRING dbname, LEX_STRING name)
+Event_queue::create_event(THD *thd, const LEX_STRING dbname,
+                          const LEX_STRING name)
 {
   int res;
   Event_queue_element *new_element;
@@ -312,20 +262,21 @@ Event_queue::create_event(THD *thd, LEX_
 */
 
 int
-Event_queue::update_event(THD *thd, LEX_STRING dbname, LEX_STRING name,
-                          LEX_STRING *new_schema, LEX_STRING *new_name)
+Event_queue::update_event(THD *thd,
+                          const LEX_STRING dbname, const LEX_STRING name,
+                          const LEX_STRING * const new_schema,
+                          const LEX_STRING * const new_name)
 {
   int res;
-  Event_queue_element *old_element= NULL,
-                      *new_element;
+  Event_queue_element *new_element;
 
   DBUG_ENTER("Event_queue::update_event");
   DBUG_PRINT("enter", ("thd=0x%lx et=[%s.%s]", thd, dbname.str, name.str));
 
   new_element= new Event_queue_element();
 
-  res= db_repository->load_named_event(thd, new_schema? *new_schema:dbname,
-                                       new_name? *new_name:name, new_element);
+  res= db_repository->load_named_event(thd, new_schema ? *new_schema:dbname,
+                                       new_name ? *new_name:name, new_element);
   if (res)
   {
     delete new_element;
@@ -345,16 +296,12 @@ Event_queue::update_event(THD *thd, LEX_
     new_element->compute_next_execution_time();
 
   LOCK_QUEUE_DATA();
-  if (!(old_element= find_n_remove_event(dbname, name)))
-  {
-    DBUG_PRINT("info", ("%s.%s not cached, probably was DISABLED",
-                        dbname.str, name.str));
-  }
+  find_n_remove_event(dbname, name);
+
   /* If not disabled event */
   if (new_element)
   {
-    DBUG_PRINT("info", ("new event in the Q 0x%lx old 0x%lx",
-                        new_element, old_element));
+    DBUG_PRINT("info", ("new event in the Q 0x%lx", new_element));
     queue_insert_safe(&queue, (byte *) new_element);
   }
   dbug_dump_queue(thd->query_start());
@@ -363,8 +310,6 @@ Event_queue::update_event(THD *thd, LEX_
   if (new_element)
     notify_observers();
 
-  if (old_element)
-    delete old_element;
 end:
   DBUG_PRINT("info", ("res=%d", res));
   DBUG_RETURN(res);
@@ -382,22 +327,16 @@ end:
 */
 
 void
-Event_queue::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name)
+Event_queue::drop_event(THD *thd, const LEX_STRING dbname, const LEX_STRING name)
 {
   int res;
-  Event_queue_element *element;
   DBUG_ENTER("Event_queue::drop_event");
   DBUG_PRINT("enter", ("thd=0x%lx name=0x%lx", thd, name));
 
   LOCK_QUEUE_DATA();
-  element= find_n_remove_event(dbname, name);
+  find_n_remove_event(dbname, name);
   dbug_dump_queue(thd->query_start());
   UNLOCK_QUEUE_DATA();
-
-  if (element)
-    delete element;
-  else
-    DBUG_PRINT("info", ("No such event found, probably DISABLED"));
   
   /*
     We don't signal here because the scheduler will catch the change
@@ -426,13 +365,13 @@ Event_queue::drop_event(THD *thd, LEX_ST
 */
 
 void
-Event_queue::drop_matching_events(THD *thd, LEX_STRING pattern,
-                           bool (*comparator)(LEX_STRING, Event_basic *))
+Event_queue::drop_matching_events(THD *thd, const LEX_STRING pattern,
+             bool (*comparator)(const LEX_STRING, const Event_basic * const))
 {
+  uint i= 0;
   DBUG_ENTER("Event_queue::drop_matching_events");
   DBUG_PRINT("enter", ("pattern=%s", pattern.str));
 
-  uint i= 0;
   while (i < queue.elements)
   {
     Event_queue_element *et= (Event_queue_element *) queue_element(&queue, i);
@@ -440,10 +379,10 @@ Event_queue::drop_matching_events(THD *t
     if (comparator(pattern, et))
     {
       /*
-        The queue is ordered. If we remove an element, then all elements after
-        it will shift one position to the left, if we imagine it as an array
-        from left to the right. In this case we should not increment the 
-        counter and the (i < queue.elements) condition is ok.
+        The queue is ordered. If we remove an element, then all elements
+        after it will shift one position to the left, if we imagine it as
+        an array from left to the right. In this case we should not
+        increment the counter and the (i < queue.elements) condition is ok.
       */
       queue_remove(&queue, i);
       delete et;
@@ -453,12 +392,12 @@ Event_queue::drop_matching_events(THD *t
   }
   /*
     We don't call notify_observers() . If we remove the top event:
-    1. The queue is empty. The scheduler will wake up at some time and realize
-       that the queue is empty. If create_event() comes inbetween it will
-       signal the scheduler
-    2. The queue is not empty, but the next event after the previous top, won't
-       be executed any time sooner than the element we removed. Hence, we may
-       not notify the scheduler and it will realize the change when it
+    1. The queue is empty. The scheduler will wake up at some time and
+       realize that the queue is empty. If create_event() comes inbetween
+       it will signal the scheduler
+    2. The queue is not empty, but the next event after the previous top,
+       won't be executed any time sooner than the element we removed. Hence,
+       we may not notify the scheduler and it will realize the change when it
        wakes up from timedwait.
   */
 
@@ -472,15 +411,12 @@ Event_queue::drop_matching_events(THD *t
 
   SYNOPSIS
     Event_queue::drop_schema_events()
-      thd        THD
-      db         The schema name
-
-  RETURN VALUE
-    >=0  Number of dropped events
+      thd        HD
+      schema    The schema name
 */
 
 void
-Event_queue::drop_schema_events(THD *thd, LEX_STRING schema)
+Event_queue::drop_schema_events(THD *thd, const LEX_STRING schema)
 {
   DBUG_ENTER("Event_queue::drop_schema_events");
   LOCK_QUEUE_DATA();
@@ -516,17 +452,13 @@ Event_queue::notify_observers()
       db    The schema of the event to find
       name  The event to find
 
-  RETURN VALUE
-    NULL       Not found
-    otherwise  Address
-
   NOTE
     The caller should do the locking also the caller is responsible for
     actual signalling in case an event is removed from the queue.
 */
 
-Event_queue_element *
-Event_queue::find_n_remove_event(LEX_STRING db, LEX_STRING name)
+void
+Event_queue::find_n_remove_event(const LEX_STRING db, const LEX_STRING name)
 {
   uint i;
   DBUG_ENTER("Event_queue::find_n_remove_event");
@@ -539,11 +471,12 @@ Event_queue::find_n_remove_event(LEX_STR
     if (event_basic_identifier_equal(db, name, et))
     {
       queue_remove(&queue, i);
-      DBUG_RETURN(et);
+      delete et;
+      break;
     }
   }
 
-  DBUG_RETURN(NULL);
+  DBUG_VOID_RETURN;
 }
 
 
@@ -583,7 +516,7 @@ Event_queue::load_events_from_db(THD *th
 
   if ((ret= db_repository->open_event_table(thd, TL_READ, &table)))
   {
-    sql_print_error("SCHEDULER: Table mysql.event is damaged. Can not open.");
+    sql_print_error("SCHEDULER: Table mysql.event is damaged. Can not open");
     DBUG_RETURN(EVEX_OPEN_TABLE_FAILED);
   }
 
@@ -625,14 +558,17 @@ Event_queue::load_events_from_db(THD *th
 
       temp_job_data.load_from_row(table);
 
-      /* We load only on scheduler root just to check whether the body compiles */
+      /*
+        We load only on scheduler root just to check whether the body
+        compiles.
+      */
       switch (ret= temp_job_data.compile(thd, thd->mem_root)) {
       case EVEX_MICROSECOND_UNSUP:
         sql_print_error("SCHEDULER: mysql.event is tampered. MICROSECOND is not "
                         "supported but found in mysql.event");
         break;
       case EVEX_COMPILE_ERROR:
-        sql_print_error("SCHEDULER: Error while compiling %s.%s. Aborting load.",
+        sql_print_error("SCHEDULER: Error while compiling %s.%s. Aborting load",
                         et->dbname.str, et->name.str);
         break;
       default:
@@ -663,12 +599,10 @@ end:
   else
   {
     ret= 0;
-    sql_print_information("SCHEDULER: Loaded %d event%s", count, (count == 1)?"":"s");
+    sql_print_information("SCHEDULER: Loaded %d event%s", count,
+                          (count == 1)?"":"s");
   }
 
-  /* Force close to free memory */
-  thd->version--;
-
   close_thread_tables(thd);
 
   DBUG_PRINT("info", ("Status code %d. Loaded %d event(s)", ret, count));
@@ -677,71 +611,6 @@ end:
 
 
 /*
-  Opens mysql.db and mysql.user and checks whether:
-    1. mysql.db has column Event_priv at column 20 (0 based);
-    2. mysql.user has column Event_priv at column 29 (0 based);
-
-  SYNOPSIS
-    Event_queue::check_system_tables()
-      thd  Thread
-
-  RETURN VALUE
-    FALSE  OK
-    TRUE   Error
-*/
-
-void
-Event_queue::check_system_tables(THD *thd)
-{
-  TABLE_LIST tables;
-  bool not_used;
-  Open_tables_state backup;
-  bool ret;
-
-  DBUG_ENTER("Event_queue::check_system_tables");
-  DBUG_PRINT("enter", ("thd=0x%lx", thd));
-
-  thd->reset_n_backup_open_tables_state(&backup);
-
-  bzero((char*) &tables, sizeof(tables));
-  tables.db= (char*) "mysql";
-  tables.table_name= tables.alias= (char*) "db";
-  tables.lock_type= TL_READ;
-
-  if ((ret= simple_open_n_lock_tables(thd, &tables)))
-  {
-    sql_print_error("Cannot open mysql.db");
-    goto end;
-  }
-  ret= table_check_intact(tables.table, MYSQL_DB_FIELD_COUNT,
-                          mysql_db_table_fields, &mysql_db_table_last_check,
-                          ER_CANNOT_LOAD_FROM_TABLE);
-  close_thread_tables(thd);
-
-  bzero((char*) &tables, sizeof(tables));
-  tables.db= (char*) "mysql";
-  tables.table_name= tables.alias= (char*) "user";
-  tables.lock_type= TL_READ;
-
-  if (simple_open_n_lock_tables(thd, &tables))
-    sql_print_error("Cannot open mysql.db");
-  else
-  {
-    if (tables.table->s->fields < 29 ||
-        strncmp(tables.table->field[29]->field_name,
-                STRING_WITH_LEN("Event_priv")))
-      sql_print_error("mysql.user has no `Event_priv` column at position 29");
-    close_thread_tables(thd);
-  }
-
-end:
-  thd->restore_backup_open_tables_state(&backup);
-
-  DBUG_VOID_RETURN;
-}
-
-
-/*
   Recalculates activation times in the queue. There is one reason for
   that. Because the values (execute_at) by which the queue is ordered are
   changed by calls to compute_next_execution_time() on a request from the
@@ -782,7 +651,7 @@ Event_queue::recalculate_activation_time
     Event_queue::empty_queue()
 
   NOTE
-    Should be called with LOCK_event_queue locked  
+    Should be called with LOCK_event_queue locked
 */
 
 void
@@ -812,7 +681,7 @@ Event_queue::empty_queue()
 */
 
 void
-Event_queue::dbug_dump_queue(time_t now)
+Event_queue::dbug_dump_queue(time_t now) const
 {
 #ifndef DBUG_OFF
   Event_queue_element *et;
@@ -1013,7 +882,7 @@ Event_queue::unlock_data(const char *fun
 */
 
 bool
-Event_queue::dump_internal_status(THD *thd)
+Event_queue::dump_internal_status(THD *thd) const
 {
   DBUG_ENTER("Event_queue::dump_internal_status");
 #ifndef DBUG_OFF

--- 1.9/sql/event_queue.h	2006-08-16 19:55:26 +02:00
+++ 1.10/sql/event_queue.h	2006-08-16 19:55:26 +02:00
@@ -31,33 +31,31 @@ public:
 
   void
   init_mutexes();
-  
+
   void
   deinit_mutexes();
-  
+
   bool
-  init_queue(Event_db_repository *db_repo, Event_scheduler *sched);
-  
+  init_queue(THD *thd, Event_db_repository *db_repo, Event_scheduler *sched);
+
   void
   deinit_queue();
 
   /* Methods for queue management follow */
 
   int
-  create_event(THD *thd, LEX_STRING dbname, LEX_STRING name);
+  create_event(THD *thd, const LEX_STRING dbname, const LEX_STRING name);
 
   int
-  update_event(THD *thd, LEX_STRING dbname, LEX_STRING name,
-               LEX_STRING *new_schema, LEX_STRING *new_name);
+  update_event(THD *thd, const LEX_STRING dbname, const LEX_STRING name,
+               const LEX_STRING * const new_schema,
+               const LEX_STRING * const new_name);
 
   void
-  drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name);
+  drop_event(THD *thd, const LEX_STRING dbname, const LEX_STRING name);
 
   void
-  drop_schema_events(THD *thd, LEX_STRING schema);
-
-  void
-  check_system_tables(THD *thd);
+  drop_schema_events(THD *thd, const LEX_STRING schema);
 
   void
   recalculate_activation_times(THD *thd);
@@ -66,19 +64,19 @@ public:
   get_top_for_execution_if_time(THD *thd, time_t now, Event_job_data **job_data,
                                 struct timespec *abstime);
   bool
-  dump_internal_status(THD *thd);
+  dump_internal_status(THD *thd) const;
 
   int
   load_events_from_db(THD *thd);
 
 protected:
-  Event_queue_element *
-  find_n_remove_event(LEX_STRING db, LEX_STRING name);
+  void
+  find_n_remove_event(const LEX_STRING db, const LEX_STRING name);
 
 
   void
-  drop_matching_events(THD *thd, LEX_STRING pattern,
-                       bool (*)(LEX_STRING, Event_basic *));
+  drop_matching_events(THD *thd, const LEX_STRING pattern,
+                       bool (*)(const LEX_STRING, const Event_basic * const));
 
   void
   empty_queue();
@@ -87,7 +85,7 @@ protected:
   notify_observers();
 
   void
-  dbug_dump_queue(time_t now);
+  dbug_dump_queue(time_t now) const;
 
   /* LOCK_event_queue is the mutex which protects the access to the queue. */
   pthread_mutex_t LOCK_event_queue;
@@ -107,7 +105,7 @@ protected:
   const char* mutex_last_attempted_lock_in_func;
   bool mutex_queue_data_locked;
   bool mutex_queue_data_attempting_lock;
-  
+
   /* helper functions for working with mutexes & conditionals */
   void
   lock_data(const char *func, uint line);

--- 1.20/sql/event_scheduler.cc	2006-08-16 19:55:26 +02:00
+++ 1.21/sql/event_scheduler.cc	2006-08-16 19:55:26 +02:00
@@ -61,7 +61,7 @@ struct scheduler_param {
 */
 
 static void
-evex_print_warnings(THD *thd, Event_job_data *et)
+evex_print_warnings(THD *thd, const Event_job_data * const et)
 {
   MYSQL_ERROR *err;
   DBUG_ENTER("evex_print_warnings");
@@ -253,7 +253,7 @@ event_worker_thread(void *arg)
 {
   /* needs to be first for thread_stack */
   THD *thd; 
-  Event_job_data *event= (Event_job_data *)arg;
+  Event_job_data * const event= (Event_job_data *)arg;
   int ret;
 
   thd= event->thd;
@@ -384,7 +384,7 @@ Event_scheduler::start()
 
   if (!(new_thd= new THD))
   {
-    sql_print_error("SCHEDULER: Cannot init manager event thread.");
+    sql_print_error("SCHEDULER: Cannot init manager event thread");
     ret= TRUE;
     goto end;
   }
@@ -441,7 +441,7 @@ end:
 bool
 Event_scheduler::run(THD *thd)
 {
-  int res;
+  int res= FALSE;
   struct timespec abstime;
   Event_job_data *job_data;
   DBUG_ENTER("Event_scheduler::run");
@@ -464,7 +464,7 @@ Event_scheduler::run(THD *thd)
                                              &job_data, &abstime))
     {
       sql_print_information("SCHEDULER: Serious error during getting next"
-                            " event to execute. Stopping.");
+                            " event to execute. Stopping");
       break;
     }
 
@@ -532,7 +532,7 @@ Event_scheduler::execute_top(THD *thd, E
   pthread_t th;
   int res= 0;
   DBUG_ENTER("Event_scheduler::execute_top");
-  if (!(new_thd= new THD))
+  if (!(new_thd= new THD()))
     goto error;
 
   pre_init_event_thread(new_thd);

--- 1.15/sql/event_scheduler.h	2006-08-16 19:55:26 +02:00
+++ 1.16/sql/event_scheduler.h	2006-08-16 19:55:26 +02:00
@@ -50,12 +50,12 @@ public:
   stop();
 
   /*
-    Need to be public because has to be called from the function 
+    Need to be public because has to be called from the function
     passed to pthread_create.
   */
   bool
   run(THD *thd);
-  
+
   void 
   init_scheduler(Event_queue *queue);
 
@@ -64,7 +64,7 @@ public:
 
   void
   init_mutexes();
-  
+
   void
   deinit_mutexes();
 
@@ -85,7 +85,7 @@ private:
 
   /* helper functions */
   bool
-  execute_top(THD *thd, Event_job_data *job_data);
+  execute_top(THD *thd, Event_job_data * const job_data);
 
   /* helper functions for working with mutexes & conditionals */
   void
@@ -112,7 +112,7 @@ private:
   ulong thread_id;
 
   pthread_cond_t COND_state;
-  
+
   Event_queue *queue;
 
   uint mutex_last_locked_at_line;
@@ -121,7 +121,7 @@ private:
   const char* mutex_last_unlocked_in_func;
   bool mutex_scheduler_data_locked;
   bool waiting_on_cond;
-  
+
   ulonglong started_events;
 
 private:

--- 1.74/sql/event_data_objects.cc	2006-08-16 19:55:26 +02:00
+++ 1.75/sql/event_data_objects.cc	2006-08-16 19:55:26 +02:00
@@ -59,19 +59,17 @@ Event_parse_data::new_instance(THD *thd)
 */
 
 Event_parse_data::Event_parse_data()
+  :on_completion(ON_COMPLETION_DROP), status(ENABLED),
+   item_starts(NULL), item_ends(NULL), item_execute_at(NULL),
+   starts_null(TRUE), ends_null(TRUE), execute_at_null(TRUE),
+   item_expression(NULL), expression(0)
 {
   DBUG_ENTER("Event_parse_data::Event_parse_data");
 
-  item_execute_at= item_expression= item_starts= item_ends= NULL;
-  status= ENABLED;
-  on_completion= ON_COMPLETION_DROP;
-  expression= 0;
-
   /* Actually in the parser STARTS is always set */
   set_zero_time(&starts, MYSQL_TIMESTAMP_DATETIME);
   set_zero_time(&ends, MYSQL_TIMESTAMP_DATETIME);
   set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME);
-  starts_null= ends_null= execute_at_null= TRUE;
 
   body.str= comment.str= NULL;
   body.length= comment.length= 0;
@@ -161,7 +159,7 @@ Event_parse_data::init_body(THD *thd)
     */
     if ((*(body_end - 1) == '*') && (*body_end == '/'))
     {
-      DBUG_PRINT("info", ("consumend one '*" "/' comment in the query '%s'", 
+      DBUG_PRINT("info", ("consumend one '*" "/' comment in the query '%s'",
           body_begin));
       body.length-= 2;
       body_end-= 2;
@@ -217,7 +215,7 @@ Event_parse_data::init_execute_at(THD *t
   DBUG_ASSERT(starts_null && ends_null);
 
   /* let's check whether time is in the past */
-  thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp, 
+  thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp,
                                             (my_time_t) thd->query_start());
 
   if ((not_used= item_execute_at->get_date(&ltime, TIME_NO_ZERO_DATE)))
@@ -512,7 +510,7 @@ error_bad_params:
 */
 
 void
-Event_parse_data::report_bad_value(const char *item_name, Item *bad_item)
+Event_parse_data::report_bad_value(const char *item_name, Item * const bad_item)
 {
   char buff[120];
   String str(buff,(uint32) sizeof(buff), system_charset_info);
@@ -736,8 +734,8 @@ Event_timed::~Event_timed()
     Event_job_data::Event_job_data()
 */
 
-Event_job_data::Event_job_data():
-  thd(NULL), sphead(NULL), sql_mode(0)
+Event_job_data::Event_job_data()
+  :thd(NULL), sphead(NULL), sql_mode(0)
 {
 }
 
@@ -1073,7 +1071,7 @@ bool get_next_time(TIME *next, TIME *sta
   {
     longlong seconds_diff;
     long microsec_diff;
-    
+
     if (calc_time_diff(time_now, start, 1, &seconds_diff, &microsec_diff))
     {
       DBUG_PRINT("error", ("negative difference"));
@@ -1115,14 +1113,16 @@ bool get_next_time(TIME *next, TIME *sta
     interval.month= (diff_months / months)*months;
     /*
       Check if the same month as last_exec (always set - prerequisite)
-      An event happens at most once per month so there is no way to schedule
-      it two times for the current month. This saves us from two calls to
-      date_add_interval() if the event was just executed.  But if the scheduler
-      is started and there was at least 1 scheduled date skipped this one does
-      not help and two calls to date_add_interval() will be done, which is a
-      bit more expensive but compared to the rareness of the case is neglectable.
+      An event happens at most once per month so there is no way to
+      schedule it two times for the current month. This saves us from two
+      calls to date_add_interval() if the event was just executed.  But if
+      the scheduler is started and there was at least 1 scheduled date
+      skipped this one does not help and two calls to date_add_interval()
+      will be done, which is a bit more expensive but compared to the
+      rareness of the case is neglectable.
     */
-    if (time_now->year==last_exec->year && time_now->month==last_exec->month)
+    if (time_now->year == last_exec->year &&
+        time_now->month == last_exec->month)
       interval.month+= months;
 
     tmp= *start;
@@ -1289,7 +1289,7 @@ Event_queue_element::compute_next_execut
     }
     goto ret;
   }
-  else if (starts_null && ends_null) 
+  else if (starts_null && ends_null)
   {
     /* starts is always set, so this is a dead branch !! */
     DBUG_PRINT("info", ("Neither STARTS nor ENDS are set"));
@@ -1333,7 +1333,7 @@ Event_queue_element::compute_next_execut
 
       {
         TIME next_exec;
-        if (get_next_time(&next_exec, &starts, &time_now, 
+        if (get_next_time(&next_exec, &starts, &time_now,
                           last_executed.year? &last_executed:&starts,
                           expression, interval))
           goto err;
@@ -1454,7 +1454,8 @@ Event_queue_element::drop(THD *thd)
 
   RETURN VALUE
     FALSE   OK
-    TRUE    Error while opening mysql.event for writing or during write on disk
+    TRUE    Error while opening mysql.event for writing or during
+            write on disk
 */
 
 bool
@@ -1530,7 +1531,7 @@ done:
 */
 
 int
-Event_timed::get_create_event(THD *thd, String *buf)
+Event_timed::get_create_event(THD *thd, String *buf) const
 {
   int multipl= 0;
   char tmp_buf[2 * STRING_BUFFER_USUAL_SIZE];
@@ -1605,7 +1606,7 @@ Event_timed::get_create_event(THD *thd, 
 */
 
 int
-Event_job_data::get_fake_create_event(THD *thd, String *buf)
+Event_job_data::get_fake_create_event(THD *thd, String *buf) const
 {
   DBUG_ENTER("Event_job_data::get_create_event");
   buf->append(STRING_WITH_LEN("CREATE EVENT anonymous ON SCHEDULE "
@@ -1645,9 +1646,9 @@ Event_job_data::execute(THD *thd)
   event_change_security_context(thd, definer_user, definer_host, dbname,
                                 &save_ctx);
   /*
-    THD::~THD will clean this or if there is DROP DATABASE in the SP then
-    it will be free there. It should not point to our buffer which is allocated
-    on a mem_root.
+    THD::~THD will clean this or if there is DROP DATABASE in the
+    SP then it will be free there. It should not point to our buffer
+    which is allocated on a mem_root.
   */
   thd->db= my_strdup(dbname.str, MYF(0));
   thd->db_length= dbname.length;
@@ -1719,7 +1720,6 @@ Event_job_data::compile(THD *thd, MEM_RO
 
   switch (get_fake_create_event(thd, &show_create)) {
   case EVEX_MICROSECOND_UNSUP:
-    sql_print_error("Scheduler");
     DBUG_RETURN(EVEX_MICROSECOND_UNSUP);
   case 0:
     break;
@@ -1769,7 +1769,8 @@ Event_job_data::compile(THD *thd, MEM_RO
       Free lex associated resources
       QQ: Do we really need all this stuff here?
     */
-    sql_print_error("error during compile of %s.%s or thd->is_fatal_error=%d",
+    sql_print_error("SCHEDULER: Error during compilation of %s.%s or "
+                    "thd->is_fatal_error=%d",
                     dbname.str, name.str, thd->is_fatal_error);
 
     lex.unit.cleanup();
@@ -1825,17 +1826,20 @@ done:
 */
 
 bool
-event_basic_db_equal(LEX_STRING db, Event_basic *et)
+event_basic_db_equal(const LEX_STRING db, const Event_basic * const et)
 {
   return !sortcmp_lex_string(et->dbname, db, system_charset_info);
 }
 
 
 /*
-  Checks whether two events are equal by identifiers
+  Checks whether an event has equal `db` and `name`
 
   SYNOPSIS
     event_basic_identifier_equal()
+      db   Schema
+      name Name
+      et   The event object
 
   RETURN VALUE
     TRUE   Equal
@@ -1843,15 +1847,17 @@ event_basic_db_equal(LEX_STRING db, Even
 */
 
 bool
-event_basic_identifier_equal(LEX_STRING db, LEX_STRING name, Event_basic *b)
+event_basic_identifier_equal(const LEX_STRING db, const LEX_STRING name,
+                             const Event_basic * const et)
 {
-  return !sortcmp_lex_string(name, b->name, system_charset_info) &&
-         !sortcmp_lex_string(db, b->dbname, system_charset_info);
+  return !sortcmp_lex_string(name, et->name, system_charset_info) &&
+         !sortcmp_lex_string(db, et->dbname, system_charset_info);
 }
 
 
 /*
-  Switches the security context
+  Switches the security context.
+
   SYNOPSIS
     event_change_security_context()
       thd     Thread
@@ -1859,7 +1865,7 @@ event_basic_identifier_equal(LEX_STRING 
       host    The host of the user
       db      The schema for which the security_ctx will be loaded
       backup  Where to store the old context
-  
+
   RETURN VALUE
     FALSE  OK
     TRUE   Error (generates error too)
@@ -1887,7 +1893,8 @@ event_change_security_context(THD *thd, 
 
 
 /*
-  Restores the security context
+  Restores the security context.
+
   SYNOPSIS
     event_restore_security_context()
       thd     Thread

--- 1.12/sql/event_data_objects.h	2006-08-16 19:55:26 +02:00
+++ 1.13/sql/event_data_objects.h	2006-08-16 19:55:26 +02:00
@@ -37,7 +37,7 @@ public:
   LEX_STRING dbname;
   LEX_STRING name;
   LEX_STRING definer;// combination of user and host
-  
+
   Event_basic();
   virtual ~Event_basic();
 
@@ -90,7 +90,7 @@ public:
 
   Event_queue_element();
   virtual ~Event_queue_element();
-  
+
   virtual int
   load_from_row(TABLE *table);
 
@@ -154,7 +154,7 @@ public:
   load_from_row(TABLE *table);
 
   int
-  get_create_event(THD *thd, String *buf);
+  get_create_event(THD *thd, String *buf) const;
 };
 
 
@@ -185,9 +185,9 @@ public:
   compile(THD *thd, MEM_ROOT *mem_root);
 private:
   int
-  get_fake_create_event(THD *thd, String *buf);
+  get_fake_create_event(THD *thd, String *buf) const;
 
-  Event_job_data(const Event_job_data &);	/* Prevent use of these */
+  Event_job_data(const Event_job_data &);       /* Prevent use of these */
   void operator=(Event_job_data &);
 };
 
@@ -237,7 +237,7 @@ public:
   new_instance(THD *thd);
 
   bool
-  check_parse_data(THD *);
+  check_parse_data(THD *thd);
 
   void
   init_body(THD *thd);
@@ -266,7 +266,7 @@ private:
   ~Event_parse_data();
 
   void
-  report_bad_value(const char *item_name, Item *bad_item);
+  report_bad_value(const char *item_name, Item * const bad_item);
 
   Event_parse_data(const Event_parse_data &);	/* Prevent use of these */
   void operator=(Event_parse_data &);
@@ -275,11 +275,12 @@ private:
 
 /* Compares only the schema part of the identifier */
 bool
-event_basic_db_equal(LEX_STRING db, Event_basic *et);
+event_basic_db_equal(const LEX_STRING db, const Event_basic * const et);
 
 /* Compares the whole identifier*/
 bool
-event_basic_identifier_equal(LEX_STRING db, LEX_STRING name, Event_basic *b);
+event_basic_identifier_equal(const LEX_STRING db, const LEX_STRING name,
+                             const Event_basic * const b);
 
 
 #endif /* _EVENT_DATA_OBJECTS_H_ */

--- 1.118/sql/share/errmsg.txt	2006-08-16 19:55:26 +02:00
+++ 1.119/sql/share/errmsg.txt	2006-08-16 19:55:26 +02:00
@@ -5851,3 +5851,5 @@ ER_CANT_DROP_LOG_TABLE
         eng "Cannot drop log table if log is enabled"
 ER_EVENT_RECURSIVITY_FORBIDDEN
         eng "Recursivity of EVENT DDL statements is forbidden when body is present"
+ER_EVENTS_DB_ERROR
+        eng "Cannot proceed because the tables used by events were found damaged at server start"

--- 1.183/sql/set_var.cc	2006-08-16 19:55:26 +02:00
+++ 1.184/sql/set_var.cc	2006-08-16 19:55:26 +02:00
@@ -3978,7 +3978,7 @@ byte *sys_var_event_scheduler::value_ptr
 {
   if (Events::opt_event_scheduler == 0)
     thd->sys_var_tmp.long_value= 0;
-  else if (Events::get_instance()->is_started())
+  else if (Events::get_instance()->is_execution_of_events_started())
     thd->sys_var_tmp.long_value= 1;
   else
     thd->sys_var_tmp.long_value= 2;
Thread
bk commit into 5.1 tree (andrey:1.2278)ahristov16 Aug