List:Commits« Previous MessageNext Message »
From:konstantin Date:March 21 2007 8:36pm
Subject:bk commit into 5.1 tree (kostja:1.2507)
View as plain text  
Below is the list of changes that have just been committed into a local
5.1 repository of kostja. When kostja does a push these changes will
be propagated to the main repository and, within 24 hours after the
push, to the public repository.
For information on how to access the public repository
see http://dev.mysql.com/doc/mysql/en/installing-source-tree.html

ChangeSet@stripped, 2007-03-21 23:36:32+03:00, kostja@stripped +18 -0
  A set of changes aiming to make the Event Scheduler more user-friendly
  when there are no up-to-date system tables to support it:
   - initialize the scheduler before reporting "Ready for connections".
     This ensures that warnings, if any, are printed before "Ready for
     connections", and this message is not mangled.
   - do not abort the scheduler if there are no system tables
   - check the tables once at start up, remember the status and disable
     the scheduler if the tables are not up to date.
     If one attempts to use the scheduler with bad tables,
     issue an error message.
  
  Collateral clean ups in the events code.

  sql/event_data_objects.cc@stripped, 2007-03-21 23:36:27+03:00, kostja@stripped +11 -48
    Move the functionality that updates mysql.event table to 
    Event_db_repository. In evetns, we try to keep all system
    tables I/O in one place.
    Change module prefix in error messages: SCHEDULER -> Event Scheduler, 
    to not collide with the recently introduced thread scheduler module.

  sql/event_db_repository.cc@stripped, 2007-03-21 23:36:27+03:00, kostja@stripped +150 -8
    Do not check mysql.event table on every access. Since we do not
    parameterize this check, checking at every access leads to unexpected
    errors at unexpected times.
    E.g. before this change one could get the following warning (sic, not
    an error):
    Error: mysql.event table is damaged.
    when issuing
    DROP DATABASE IF EXISTS foo;
    and foo does not exist.
    The warning would be produced regardless of the value of
    --event-scheduler option.
    
    Accept two new methods that work with system tables moved from other
    event scheduler subsystems.

  sql/event_db_repository.h@stripped, 2007-03-21 23:36:27+03:00, kostja@stripped +16 -3
    Add declarations for new methods.

  sql/event_queue.cc@stripped, 2007-03-21 23:36:27+03:00, kostja@stripped +8 -26
    Remove init_mutexes, deinit_mutexes, they are not needed anymore.
    
    Change module prefix in error messages: SCHEDULER -> Event Scheduler,
    to not collide with the recently introduced thread scheduler module.

  sql/event_queue.h@stripped, 2007-03-21 23:36:27+03:00, kostja@stripped +2 -7
    Update declarations.

  sql/event_scheduler.cc@stripped, 2007-03-21 23:36:27+03:00, kostja@stripped +30 -59
    Change module prefix in error messages: SCHEDULER -> Event Scheduler,
    to not collide with the recently introduced thread scheduler module.

  sql/event_scheduler.h@stripped, 2007-03-21 23:36:27+03:00, kostja@stripped +12 -19
    Add comments, update declarations.

  sql/events.cc@stripped, 2007-03-21 23:36:27+03:00, kostja@stripped +229 -231
    Change module prefix in error messages: SCHEDULER -> Event Scheduler,
    to not collide with the recently introduced thread scheduler module.

  sql/events.h@stripped, 2007-03-21 23:36:27+03:00, kostja@stripped +57 -43
    Add comments. Update declarations. 
    Use static methods to implement singleton pattern.

  sql/mysqld.cc@stripped, 2007-03-21 23:36:28+03:00, kostja@stripped +8 -38
    Move some code to methods of Events class
    Initialize the event scheduler before happily reporting that we're ready
    to accept connections - we may request unireg_abort if Events::init
    failed. 

  sql/set_var.cc@stripped, 2007-03-21 23:36:28+03:00, kostja@stripped +6 -25
    Move some functionality to Events module.

  sql/share/errmsg.txt@stripped, 2007-03-21 23:36:28+03:00, kostja@stripped +4 -4
    Update error messages to use better English and suggest the right
    upgrade procedure to the user.

  sql/sql_db.cc@stripped, 2007-03-21 23:36:28+03:00, kostja@stripped +1 -1
    New invocation scheme.

  sql/sql_parse.cc@stripped, 2007-03-21 23:36:28+03:00, kostja@stripped +13 -12
    Do not include an unused header. Supply LEX_STRING instead of sp_name
    to make Events module not dependant on sp_head.h, where sp_name is
    declared.

  sql/sql_servers.cc@stripped, 2007-03-21 23:36:28+03:00, kostja@stripped +1 -1
    It's not a fatal error when mysql.servers does not exist.

  sql/sql_test.cc@stripped, 2007-03-21 23:36:28+03:00, kostja@stripped +1 -1
    New invocation scheme.

  sql/table.cc@stripped, 2007-03-21 23:36:28+03:00, kostja@stripped +96 -114
    Rewrite table_check_intact to:
     - not call my_error, since it's useless
     - not update last invocation time, since it's got issues with
       concurrency and this function is never used under heavy load anyway.

  sql/table.h@stripped, 2007-03-21 23:36:28+03:00, kostja@stripped +16 -2
    Add a helper method to quickly initialize TABLE_LIST for 
    simple_open_and_lock_tables.
    New declarations 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:	kostja
# Host:	bodhi.local
# Root:	/opt/local/work/mysql-5.1-events-cleanup

--- 1.622/sql/mysqld.cc	2007-03-20 00:37:31 +03:00
+++ 1.623/sql/mysqld.cc	2007-03-21 23:36:28 +03:00
@@ -890,7 +890,7 @@
   }
   (void) pthread_mutex_unlock(&LOCK_thread_count); // For unlink from list
 
-  Events::get_instance()->deinit();
+  Events::deinit();
   end_slave();
 
   if (thread_count)
@@ -1335,7 +1335,7 @@
   (void) pthread_mutex_destroy(&LOCK_bytes_sent);
   (void) pthread_mutex_destroy(&LOCK_bytes_received);
   (void) pthread_mutex_destroy(&LOCK_user_conn);
-  Events::get_instance()->destroy_mutexes();
+  Events::destroy_mutexes();
 #ifdef HAVE_OPENSSL
   (void) pthread_mutex_destroy(&LOCK_des_key_file);
 #ifndef HAVE_YASSL
@@ -3062,7 +3062,7 @@
   (void) pthread_mutex_init(&LOCK_server_started, MY_MUTEX_INIT_FAST);
   (void) pthread_cond_init(&COND_server_started,NULL);
   sp_cache_init();
-  Events::get_instance()->init_mutexes();
+  Events::init_mutexes();
   /* Parameter for threads created for connections */
   (void) pthread_attr_init(&connection_attrib);
   (void) pthread_attr_setdetachstate(&connection_attrib,
@@ -3841,21 +3841,15 @@
   create_shutdown_thread();
   create_maintenance_thread();
 
+  if (Events::init(opt_noacl))
+    unireg_abort(1);
+
   sql_print_information(ER(ER_STARTUP),my_progname,server_version,
                         ((unix_sock == INVALID_SOCKET) ? (char*) ""
                                                        : mysqld_unix_port),
                          mysqld_port,
                          MYSQL_COMPILATION_COMMENT);
 
-  if (!opt_noacl)
-  {
-    if (Events::get_instance()->init())
-      unireg_abort(1);
-  }
-  else
-  {
-    Events::opt_event_scheduler = Events::EVENTS_DISABLED; 
-  }
 
   /* Signal threads waiting for server to be started */
   pthread_mutex_lock(&LOCK_server_started);
@@ -7568,32 +7562,8 @@
   }
 #endif
   case OPT_EVENT_SCHEDULER:
-    if (!argument)
-      Events::opt_event_scheduler= Events::EVENTS_DISABLED;
-    else
-    {
-      int type;
-      /* 
-        type=     5          1   2      3   4
-             (DISABLE ) - (OFF | ON) - (0 | 1)
-      */
-      switch ((type=find_type(argument, &Events::opt_typelib, 1))) {
-      case 0:
-	fprintf(stderr, "Unknown option to event-scheduler: %s\n",argument);
-	exit(1);
-      case 5: /* OPT_DISABLED */
-        Events::opt_event_scheduler= Events::EVENTS_DISABLED;
-        break;
-      case 2: /* OPT_ON  */
-      case 4: /* 1   */
-        Events::opt_event_scheduler= Events::EVENTS_ON;
-        break;
-      case 1: /* OPT_OFF */
-      case 3: /*  0  */
-        Events::opt_event_scheduler= Events::EVENTS_OFF;
-        break;
-      }
-    }
+    if (Events::set_opt_event_scheduler(argument))
+      exit(1);
     break;
   case (int) OPT_SKIP_NEW:
     opt_specialflag|= SPECIAL_NO_NEW_FUNC;

--- 1.147/sql/sql_db.cc	2006-12-23 22:19:53 +03:00
+++ 1.148/sql/sql_db.cc	2007-03-21 23:36:28 +03:00
@@ -953,7 +953,7 @@
 
 exit:
   (void)sp_drop_db_routines(thd, db); /* QQ Ignore errors for now  */
-  Events::get_instance()->drop_schema_events(thd, db);
+  Events::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.648/sql/sql_parse.cc	2007-03-20 00:37:33 +03:00
+++ 1.649/sql/sql_parse.cc	2007-03-21 23:36:28 +03:00
@@ -26,7 +26,6 @@
 #include "sp.h"
 #include "sp_cache.h"
 #include "events.h"
-#include "event_data_objects.h"
 #include "sql_trigger.h"
 
 /* Used in error handling only */
@@ -3151,13 +3150,16 @@
 
     switch (lex->sql_command) {
     case SQLCOM_CREATE_EVENT:
-      res= Events::get_instance()->
-            create_event(thd, lex->event_parse_data,
-                         lex->create_info.options & HA_LEX_CREATE_IF_NOT_EXISTS);
+    {
+      bool if_not_exists= (lex->create_info.options &
+                           HA_LEX_CREATE_IF_NOT_EXISTS);
+      res= Events::create_event(thd, lex->event_parse_data, if_not_exists);
       break;
+    }
     case SQLCOM_ALTER_EVENT:
-      res= Events::get_instance()->update_event(thd, lex->event_parse_data,
-                                                lex->spname);
+      res= Events::update_event(thd, lex->event_parse_data,
+                                lex->spname ? &lex->spname->m_db : NULL,
+                                lex->spname ? &lex->spname->m_name : NULL);
       break;
     default:
       DBUG_ASSERT(0);
@@ -3196,14 +3198,13 @@
     }
 
     if (lex->sql_command == SQLCOM_SHOW_CREATE_EVENT)
-      res= Events::get_instance()->show_create_event(thd, lex->spname->m_db,
-                                                     lex->spname->m_name);
+      res= Events::show_create_event(thd, lex->spname->m_db,
+                                     lex->spname->m_name);
     else
     {
-      if (!(res= Events::get_instance()->drop_event(thd,
-                                                    lex->spname->m_db,
-                                                    lex->spname->m_name,
-                                                    lex->drop_if_exists)))
+      if (!(res= Events::drop_event(thd, lex->spname->m_db,
+                                    lex->spname->m_name,
+                                    lex->drop_if_exists)))
         send_ok(thd);
     }
     break;

--- 1.51/sql/sql_test.cc	2007-02-23 14:13:50 +03:00
+++ 1.52/sql/sql_test.cc	2007-03-21 23:36:28 +03:00
@@ -537,6 +537,6 @@
 	 (long) (thread_count * thread_stack + info.hblkhd + info.arena));
 #endif
 
-  Events::get_instance()->dump_internal_status();
+  Events::dump_internal_status();
   puts("");
 }

--- 1.281/sql/table.cc	2007-03-20 00:37:36 +03:00
+++ 1.282/sql/table.cc	2007-03-21 23:36:28 +03:00
@@ -2432,153 +2432,135 @@
 }
 
 
-/*
+/**
   Checks whether a table is intact. Should be done *just* after the table has
   been opened.
-  
+
   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
 
   RETURNS
     FALSE  OK
-    TRUE   There was an error
+    TRUE   There was an error. An error message is output to the
+           error log.  We do not push an error message into the
+           error stack because this function is currently only
+           called at start up, and such errors never reach the user.
 */
 
 my_bool
 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)
+                   const TABLE_FIELD_W_TYPE *table_def)
 {
   uint i;
   my_bool error= FALSE;
   my_bool fields_diff_count;
   DBUG_ENTER("table_check_intact");
-  DBUG_PRINT("info",("table: %s  expected_count: %d  last_create_time: %ld",
-                     table->alias, table_f_count, *last_create_time));
-  
-  if ((fields_diff_count= (table->s->fields != table_f_count)) ||
-      (*last_create_time != table->file->stats.create_time))
+  DBUG_PRINT("info",("table: %s  expected_count: %d",
+                     table->alias, table_f_count));
+
+  fields_diff_count= (table->s->fields != table_f_count);
+  if (fields_diff_count)
   {
-    DBUG_PRINT("info", ("I am suspecting, checking table"));
-    if (fields_diff_count)
+    DBUG_PRINT("info", ("Column count has changed, checking the definition"));
+
+    /* previous MySQL version */
+    if (MYSQL_VERSION_ID > table->s->mysql_version)
     {
-      /* previous MySQL version */
-      error= TRUE;
-      if (MYSQL_VERSION_ID > table->s->mysql_version)
-      {
-        my_error(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE, MYF(0), table->alias,
-                 table_f_count, table->s->fields, table->s->mysql_version,
-                 MYSQL_VERSION_ID);
-        sql_print_error(ER(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE),
-                        table->alias, table_f_count, table->s->fields,
-                        table->s->mysql_version, MYSQL_VERSION_ID);
-        DBUG_RETURN(error);
+      sql_print_error(ER(ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE),
+                      table->alias, table_f_count, table->s->fields,
+                      table->s->mysql_version, MYSQL_VERSION_ID);
+      DBUG_RETURN(TRUE);
+    }
+    else if (MYSQL_VERSION_ID == table->s->mysql_version)
+    {
+      sql_print_error(ER(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED), table->alias,
+                      table_f_count, table->s->fields);
+      DBUG_RETURN(TRUE);
+    }
+    /*
+      Something has definitely changed, but we're running an older
+      version of MySQL with new system tables.
+      Let's check column definitions. If a column was added at
+      the end of the table, then we don't care much since such change
+      is backward compatible.
+    */
+  }
+  char buffer[STRING_BUFFER_USUAL_SIZE];
+  for (i=0 ; i < table_f_count; i++, table_def++)
+  {
+    String sql_type(buffer, sizeof(buffer), system_charset_info);
+    sql_type.length(0);
+    if (i < table->s->fields)
+    {
+      Field *field= table->field[i];
 
-      }
-      else if (MYSQL_VERSION_ID == table->s->mysql_version)
-      {
-        my_error(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED,MYF(0), table->alias,
-                 table_f_count, table->s->fields);
-        sql_print_error(ER(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED), table->alias,
-                        table_f_count, table->s->fields);
-      }
-      else
+      if (strncmp(field->field_name, table_def->name.str,
+                  table_def->name.length))
       {
         /*
-          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.
+          Name changes are not fatal, we use ordinal numbers to access columns.
+          Still this can be a sign of a tampered table, output an error
+          to the error log.
         */
-        error= FALSE;
+        sql_print_error("(%s) Expected field %s at position %d, found %s",
+                        table->alias, table_def->name.str, i,
+                        field->field_name);
       }
-    }
-    /* 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);
+      field->sql_type(sql_type);
       /*
-        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)
+        Generally, if column types don't match, then something is
+        wrong.
+
+        However, we only compare column definitions up to the
+        length of the original definition, since we consider the
+        following definitions compatible:
+
+        1. DATETIME and DATETIM
+        2. INT(11) and INT(11
+        3. SET('one', 'two') and SET('one', 'two', 'more')
+
+        For SETs or ENUMs, if the same prefix is there it's OK to
+        add more elements - they will get higher ordinal numbers and
+        the new table definition is backward compatible with the
+        original one.
+       */
+      if (strncmp(sql_type.c_ptr_safe(), table_def->type.str,
+                  table_def->type.length - 1))
       {
-        Field *field= table->field[i];
-        if (strncmp(field->field_name, table_def->name.str,
-                                       table_def->name.length))
-        {
-          sql_print_error("(%s) Expected field %s at position %d, found %s",
-                          table->alias, table_def->name.str, i,
-                          field->field_name);
-        }
-                        
-        /*
-          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
-          3. set('one','two') -> set('one','two'  
-             so for sets if the same prefix is there it's ok if more are
-             added as part of the set. The same is valid for enum. So a new
-             table running on a old server will be valid.
-        */ 
-        field->sql_type(sql_type);
-        if (strncmp(sql_type.c_ptr_safe(), table_def->type.str,
-                    table_def->type.length - 1))
-        {
-          sql_print_error("(%s) Expected field %s at position %d to have type "
-                          "%s, found %s", table->alias, table_def->name.str,
-                          i, table_def->type.str, sql_type.c_ptr_safe()); 
-          error= TRUE;
-        }
-        else if (table_def->cset.str && !field->has_charset())
-        {
-          sql_print_error("(%s) Expected field %s at position %d to have "
-                          "character set '%s' but found no such", table->alias,
-                          table_def->name.str, i, table_def->cset.str);        
-          error= TRUE;
-        }
-        else if (table_def->cset.str && 
-                 strcmp(field->charset()->csname, table_def->cset.str))
-        {
-          sql_print_error("(%s) Expected field %s at position %d to have "
-                          "character set '%s' but found '%s'", table->alias,
-                          table_def->name.str, i, table_def->cset.str,
-                          field->charset()->csname);
-          error= TRUE;
-        }
+        sql_print_error("(%s) Expected field %s at position %d to have type "
+                        "%s, found %s", table->alias, table_def->name.str,
+                        i, table_def->type.str, sql_type.c_ptr_safe()); 
+        error= TRUE;
       }
-      else
+      else if (table_def->cset.str && !field->has_charset())
       {
-        sql_print_error("(%s) Expected field %s at position %d to have type %s "
-                        " but no field found.", table->alias,
-                        table_def->name.str, i, table_def->type.str);
-        error= TRUE;        
+        sql_print_error("(%s) Expected field %s at position %d to have "
+                        "character set '%s' but found no such", table->alias,
+                        table_def->name.str, i, table_def->cset.str);
+        error= TRUE;
+      }
+      else if (table_def->cset.str &&
+               strcmp(field->charset()->csname, table_def->cset.str))
+      {
+        sql_print_error("(%s) Expected field %s at position %d to have "
+                        "character set '%s' but found '%s'", table->alias,
+                        table_def->name.str, i, table_def->cset.str,
+                        field->charset()->csname);
+        error= TRUE;
       }
     }
-    if (!error)
-      *last_create_time= table->file->stats.create_time;
-    else if (!fields_diff_count && error_num)
-      my_error(error_num,MYF(0), table->alias, table_f_count, table->s->fields);
-  }
-  else
-  {
-    DBUG_PRINT("info", ("Table seems ok without thorough checking."));
-    *last_create_time= table->file->stats.create_time;
+    else
+    {
+      sql_print_error("(%s) Expected field %s at position %d to have type %s "
+                      " but no field found.", table->alias,
+                      table_def->name.str, i, table_def->type.str);
+      error= TRUE;
+    }
   }
-   
-  DBUG_RETURN(error);  
+  DBUG_RETURN(error);
 }
 
 

--- 1.163/sql/table.h	2007-03-17 02:13:19 +03:00
+++ 1.164/sql/table.h	2007-03-21 23:36:28 +03:00
@@ -684,6 +684,21 @@
 typedef struct st_table_list
 {
   st_table_list() {}                          /* Remove gcc warning */
+
+  /**
+    Prepare TABLE_LIST that consists of one table instance to use in
+    simple_open_and_lock_tables
+  */
+  inline void init_one_table(const char *db_name_arg,
+                             const char *table_name_arg,
+                             enum thr_lock_type lock_type_arg)
+  {
+    bzero((char*) this, sizeof(*this));
+    db= (char*) db_name_arg;
+    table_name= alias= (char*) table_name_arg;
+    lock_type= lock_type_arg;
+  }
+
   /*
     List of tables local to a subquery (used by SQL_LIST). Considers
     views as leaves (unlike 'next_leaf' below). Created at parse time
@@ -1092,8 +1107,7 @@
 
 my_bool
 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);
+                   const TABLE_FIELD_W_TYPE *table_def);
 
 static inline my_bitmap_map *tmp_use_all_columns(TABLE *table,
                                                  MY_BITMAP *bitmap)

--- 1.71/sql/events.cc	2007-03-16 17:31:04 +03:00
+++ 1.72/sql/events.cc	2007-03-21 23:36:27 +03:00
@@ -19,7 +19,6 @@
 #include "event_db_repository.h"
 #include "event_queue.h"
 #include "event_scheduler.h"
-#include "sp_head.h"
 
 /*
  TODO list :
@@ -91,20 +90,91 @@
 };
 
 
-static
-Event_queue events_event_queue;
+enum Events::enum_opt_event_scheduler
+Events::opt_event_scheduler= Events::EVENTS_OFF;
 
-static
-Event_scheduler events_event_scheduler;
+Event_queue *Events::event_queue;
+Event_scheduler *Events::scheduler;
+Event_db_repository *Events::db_repository;
+pthread_mutex_t Events::LOCK_event_metadata;
+bool Events::check_system_tables_error;
+
+/**
+  @brief Initialize the start up option of the Events scheduler.
+
+  Do not initialize the scheduler subsystem yet - the initialization
+  is split into steps as it has to fit into the common MySQL
+  initialization framework.
+  No locking as this is called only at start up.
 
+  @retval TRUE  unknown option value
+  @retval FALSE success
+*/
+
+bool
+Events::set_opt_event_scheduler(const char *argument)
+{
+  if (argument == NULL)
+    opt_event_scheduler= Events::EVENTS_DISABLED;
+  else
+  {
+    int type;
+    /*
+      type=   1   2      3   4      5
+           (OFF | ON) - (0 | 1) (DISABLE )
+    */
+    const static enum enum_opt_event_scheduler type2state[]=
+    { EVENTS_OFF, EVENTS_ON, EVENTS_OFF, EVENTS_ON, EVENTS_DISABLED };
+
+    type= find_type((char *) argument, &opt_typelib, 1);
+
+    DBUG_ASSERT(type >= 0 && type <= 5); /* guaranteed by find_type */
+
+    if (type == 0);
+    {
+      fprintf(stderr, "Unknown option to event-scheduler: %s\n", argument);
+      return TRUE;
+    }
+    opt_event_scheduler= type2state[type-1];
+  }
+  return FALSE;
+}
+
+
+/**
+  Return a string representation of the current scheduler mode.
+*/
+
+const char *
+Events::get_opt_event_scheduler_str()
+{
+  const char *str;
+
+  pthread_mutex_lock(&LOCK_event_metadata);
+  str= opt_typelib.type_names[(int) opt_event_scheduler];
+  pthread_mutex_unlock(&LOCK_event_metadata);
+
+  return str;
+}
 
-Event_db_repository events_event_db_repository;
 
-Events Events::singleton;
+/**
+  Push an error into the error stack if the system tables are
+  not up to date.
+*/
+
+bool Events::check_if_system_tables_error()
+{
+  DBUG_ENTER("Events::check_if_system_tables_error");
 
-enum Events::enum_opt_event_scheduler Events::opt_event_scheduler=
-     Events::EVENTS_OFF;
+  if (check_system_tables_error)
+  {
+    my_error(ER_EVENTS_DB_ERROR, MYF(0));
+    DBUG_RETURN(TRUE);
+  }
 
+  DBUG_RETURN(FALSE);
+}
 
 /*
   Compares 2 LEX strings regarding case.
@@ -129,24 +199,6 @@
 
 
 /*
-  Accessor for the singleton instance.
-
-  SYNOPSIS
-    Events::get_instance()
-
-  RETURN VALUE
-    address
-*/
-
-Events *
-Events::get_instance()
-{
-  DBUG_ENTER("Events::get_instance");
-  DBUG_RETURN(&singleton);
-}
-
-
-/*
   Reconstructs interval expression from interval type and expression
   value that is in form of a value of the smalles entity:
   For
@@ -278,22 +330,6 @@
   return 0;
 }
 
-/*
-  Constructor of Events class. It's called when events.o
-  is loaded. Assigning addressed of static variables in this
-  object file.
-
-  SYNOPSIS
-    Events::Events()
-*/
-
-Events::Events()
-{
-  scheduler=     &events_event_scheduler;
-  event_queue=   &events_event_queue;
-  db_repository= &events_event_db_repository;
-}
-
 
 /*
   The function exported to the world for creating of events.
@@ -318,11 +354,9 @@
 {
   int ret;
   DBUG_ENTER("Events::create_event");
-  if (unlikely(check_system_tables_error))
-  {
-    my_error(ER_EVENTS_DB_ERROR, MYF(0));
+
+  if (check_if_system_tables_error())
     DBUG_RETURN(TRUE);
-  }
 
   pthread_mutex_lock(&LOCK_event_metadata);
   /* On error conditions my_error() is called so no need to handle here */
@@ -340,13 +374,12 @@
       DBUG_ASSERT(ret == OP_LOAD_ERROR);
       delete new_element;
     }
-    else
+    else if (event_queue)
       event_queue->create_event(thd, new_element);
   }
   pthread_mutex_unlock(&LOCK_event_metadata);
 
   DBUG_RETURN(ret);
-  
 }
 
 
@@ -370,18 +403,16 @@
 */
 
 bool
-Events::update_event(THD *thd, Event_parse_data *parse_data, sp_name *rename_to)
+Events::update_event(THD *thd, Event_parse_data *parse_data,
+                     LEX_STRING *new_dbname, LEX_STRING *new_name)
 {
   int ret;
   Event_queue_element *new_element;
+
   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;
-  if (unlikely(check_system_tables_error))
-  {
-    my_error(ER_EVENTS_DB_ERROR, MYF(0));
+
+  if (check_if_system_tables_error())
     DBUG_RETURN(TRUE);
-  }
 
   pthread_mutex_lock(&LOCK_event_metadata);
   /* On error conditions my_error() is called so no need to handle here */
@@ -398,7 +429,7 @@
       DBUG_ASSERT(ret == OP_LOAD_ERROR);
       delete new_element;   
     }
-    else
+    else if (event_queue)
       event_queue->update_event(thd, parse_data->dbname, parse_data->name,
                                 new_element);
   }
@@ -429,24 +460,29 @@
 {
   int ret;
   DBUG_ENTER("Events::drop_event");
-  if (unlikely(check_system_tables_error))
-  {
-    my_error(ER_EVENTS_DB_ERROR, MYF(0));
+
+  if (check_if_system_tables_error())
     DBUG_RETURN(TRUE);
-  }
 
   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)))
-    event_queue->drop_event(thd, dbname, name);
+  {
+    if (event_queue)
+      event_queue->drop_event(thd, dbname, name);
+  }
   pthread_mutex_unlock(&LOCK_event_metadata);
   DBUG_RETURN(ret);
 }
 
 
-/*
+/**
   Drops all events from a schema
 
+  @note We allow to drop all the events in the schema even if the
+  scheduler is disabled. This is to not produce any warnings
+  in case of DROP DATABASE and a disabled scheduler.
+
   SYNOPSIS
     Events::drop_schema_events()
       thd  Thread
@@ -457,17 +493,18 @@
 Events::drop_schema_events(THD *thd, char *db)
 {
   LEX_STRING const db_lex= { db, strlen(db) };
-  
-  DBUG_ENTER("Events::drop_schema_events");  
+
+  DBUG_ENTER("Events::drop_schema_events");
   DBUG_PRINT("enter", ("dropping events from %s", db));
-  if (unlikely(check_system_tables_error))
-  {
-    my_error(ER_EVENTS_DB_ERROR, MYF(0));
-    DBUG_VOID_RETURN;
-  }
+
+  /*
+    sic: no check if the scheduler is disabled or system tables
+    are damaged, as intended.
+  */
 
   pthread_mutex_lock(&LOCK_event_metadata);
-  event_queue->drop_schema_events(thd, db_lex);
+  if (event_queue)
+    event_queue->drop_schema_events(thd, db_lex);
   db_repository->drop_schema_events(thd, db_lex);
   pthread_mutex_unlock(&LOCK_event_metadata);
 
@@ -493,17 +530,17 @@
 {
   CHARSET_INFO *scs= system_charset_info;
   int ret;
-  Event_timed *et= new Event_timed();
+  Event_timed *et;
 
   DBUG_ENTER("Events::show_create_event");
   DBUG_PRINT("enter", ("name: %s@%s", dbname.str, name.str));
-  if (unlikely(check_system_tables_error))
-  {
-    my_error(ER_EVENTS_DB_ERROR, MYF(0));
+
+  if (check_if_system_tables_error())
     DBUG_RETURN(TRUE);
-  }
 
-  ret= db_repository->load_named_event(thd, dbname, name, et);
+  et= new Event_timed;
+
+  ret= et == NULL || db_repository->load_named_event(thd, dbname, name, et);
 
   if (!ret)
   {
@@ -578,12 +615,9 @@
 {
   char *db= NULL;
   DBUG_ENTER("Events::fill_schema_events");
-  Events *myself= get_instance();
-  if (unlikely(myself->check_system_tables_error))
-  {
-    my_error(ER_EVENTS_DB_ERROR, MYF(0));
+
+  if (check_if_system_tables_error())
     DBUG_RETURN(TRUE);
-  }
 
   /*
     If it's SHOW EVENTS then thd->lex->select_lex.db is guaranteed not to
@@ -597,7 +631,7 @@
       DBUG_RETURN(1);
     db= thd->lex->select_lex.db;
   }
-  DBUG_RETURN(myself->db_repository->fill_schema_events(thd, tables, db));
+  DBUG_RETURN(db_repository->fill_schema_events(thd, tables, db));
 }
 
 
@@ -616,14 +650,17 @@
 */
 
 bool
-Events::init()
+Events::init(my_bool opt_noacl)
 {
   THD *thd;
   bool res= FALSE;
+
   DBUG_ENTER("Events::init");
 
-  if (opt_event_scheduler == Events::EVENTS_DISABLED)
-    DBUG_RETURN(FALSE);
+  /* Disable the scheduler if running with --skip-grant-tables */
+  if (opt_noacl)
+    opt_event_scheduler= EVENTS_DISABLED;
+
 
   /* We need a temporary THD during boot */
   if (!(thd= new THD()))
@@ -639,29 +676,65 @@
   thd->thread_stack= (char*) &thd;
   thd->store_globals();
 
-  if (check_system_tables(thd))
+  /*
+    We will need Event_db_repository anyway, even if the scheduler is
+    disabled - to perform events DDL.
+  */
+  if (!(db_repository= new Event_db_repository))
   {
-    check_system_tables_error= TRUE;
-    sql_print_error("SCHEDULER: The system tables are damaged. "
-                    "The scheduler subsystem will be unusable during this run.");
-    goto end;
+    res= 1; /* fatal error: request unireg_abort */
+    goto error;
   }
-  check_system_tables_error= FALSE;
 
-  if (event_queue->init_queue(thd) || load_events_from_db(thd))
+  /*
+    Since we allow event DDL even if the scheduler is disabled,
+    check the system tables, as we might need them. Do not print
+    an error message if the scheduler was disabled.
+  */
+  if (Event_db_repository::check_system_tables(thd))
   {
-    sql_print_error("SCHEDULER: Error while loading from disk.");
+    sql_print_error("Event Scheduler: An error occurred when initializing "
+                    "system tables.%s",
+                    opt_event_scheduler == EVENTS_DISABLED ?
+                    "" : " Disabling the Event Scheduler.");
+
+    /* Disable the scheduler since the system tables are not up to date */
+    opt_event_scheduler= EVENTS_DISABLED;
+    check_system_tables_error= TRUE;
     goto end;
   }
 
-  scheduler->init_scheduler(event_queue);
+  /*
+    Was disabled explicitly from the command line, or because we're running
+    with --skip-grant-tables, or because we have no system tables.
+  */
+  if (opt_event_scheduler == Events::EVENTS_DISABLED)
+    goto end;
+
 
   DBUG_ASSERT(opt_event_scheduler == Events::EVENTS_ON ||
               opt_event_scheduler == Events::EVENTS_OFF);
-  if (opt_event_scheduler == Events::EVENTS_ON)
-    res= scheduler->start();
 
-  Event_worker_thread::init(this, db_repository);
+  if (!(event_queue= new Event_queue) ||
+      !(scheduler= new Event_scheduler(event_queue)))
+  {
+    res= 1; /* fatal error: request unireg_abort */
+    goto error;
+  }
+
+  if (event_queue->init_queue(thd) || load_events_from_db(thd) ||
+      opt_event_scheduler == EVENTS_ON && scheduler->start())
+  {
+    sql_print_error("Event Scheduler: Error while loading from disk.");
+    res= 1; /* fatal error: request unireg_abort */
+    goto error;
+  }
+
+  Event_worker_thread::init(db_repository);
+error:
+  delete event_queue;
+  delete scheduler;
+  delete db_repository;
 end:
   delete thd;
   /* Remember that we don't have a THD */
@@ -685,19 +758,23 @@
 Events::deinit()
 {
   DBUG_ENTER("Events::deinit");
-  if (likely(!check_system_tables_error))
+
+  if (opt_event_scheduler != EVENTS_DISABLED)
   {
     scheduler->stop();
-    scheduler->deinit_scheduler();
-
     event_queue->deinit_queue();
+
+    delete event_queue;
+    delete scheduler;
   }
 
+  delete db_repository;
+
   DBUG_VOID_RETURN;
 }
 
 
-/*
+/**
   Inits Events mutexes
 
   SYNOPSIS
@@ -709,8 +786,6 @@
 Events::init_mutexes()
 {
   pthread_mutex_init(&LOCK_event_metadata, MY_MUTEX_INIT_FAST);
-  event_queue->init_mutexes();
-  scheduler->init_mutexes();
 }
 
 
@@ -724,8 +799,6 @@
 void
 Events::destroy_mutexes()
 {
-  event_queue->deinit_mutexes();
-  scheduler->deinit_mutexes();
   pthread_mutex_destroy(&LOCK_event_metadata);
 }
 
@@ -748,9 +821,16 @@
   puts("LLA = Last Locked At  LUA = Last Unlocked At");
   puts("WOC = Waiting On Condition  DL = Data Locked");
 
-  scheduler->dump_internal_status();
-  event_queue->dump_internal_status();
+  pthread_mutex_lock(&LOCK_event_metadata);
+  if (opt_event_scheduler == EVENTS_DISABLED)
+    puts("The Event Scheduler is disabled");
+  else
+  {
+    scheduler->dump_internal_status();
+    event_queue->dump_internal_status();
+  }
 
+  pthread_mutex_unlock(&LOCK_event_metadata);
   DBUG_VOID_RETURN;
 }
 
@@ -759,7 +839,7 @@
   Starts execution of events by the scheduler
 
   SYNOPSIS
-    Events::start_execution_of_events()
+    Events::start_or_stop_event_scheduler()
 
   RETURN VALUE
     FALSE  OK
@@ -767,135 +847,48 @@
 */
 
 bool
-Events::start_execution_of_events()
+Events::start_or_stop_event_scheduler(enum enum_opt_event_scheduler new_state)
 {
-  DBUG_ENTER("Events::start_execution_of_events");
-  if (unlikely(check_system_tables_error))
-  {
-    my_error(ER_EVENTS_DB_ERROR, MYF(0));
-    DBUG_RETURN(TRUE);
-  }
-  DBUG_RETURN(scheduler->start());
-}
-
+  bool ret= FALSE;
 
-/*
-  Stops execution of events by the scheduler.
-  Already running events will not be stopped. If the user needs
-  them stopped manual intervention is needed.
+  DBUG_ENTER("Events::start_or_stop_event_scheduler");
 
-  SYNOPSIS
-    Events::stop_execution_of_events()
+  DBUG_ASSERT(new_state == Events::EVENTS_ON ||
+              new_state == Events::EVENTS_OFF);
 
-  RETURN VALUE
-    FALSE  OK
-    TRUE   Error
-*/
-
-bool
-Events::stop_execution_of_events()
-{
-  DBUG_ENTER("Events::stop_execution_of_events");
-  if (unlikely(check_system_tables_error))
-  {
-    my_error(ER_EVENTS_DB_ERROR, MYF(0));
+  /*
+    If the scheduler was disabled because there are no/bad
+    system tables, produce a more meaningful error message
+    than ER_OPTION_PREVENTS_STATEMENT
+  */
+  if (check_if_system_tables_error())
     DBUG_RETURN(TRUE);
-  }
-  DBUG_RETURN(scheduler->stop());
-}
-
-
-/*
-  Checks whether the scheduler is running or not.
-
-  SYNOPSIS
-    Events::is_started()
-
-  RETURN VALUE
-    TRUE   Yes
-    FALSE  No
-*/
-
-bool
-Events::is_execution_of_events_started()
-{
-  DBUG_ENTER("Events::is_execution_of_events_started");
-  if (unlikely(check_system_tables_error))
-  {
-    my_error(ER_EVENTS_DB_ERROR, MYF(0));
-    DBUG_RETURN(FALSE);
-  }
-  DBUG_RETURN(scheduler->is_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;
-  Open_tables_state backup;
-  bool ret= FALSE;
-
-  DBUG_ENTER("Events::check_system_tables");
-  DBUG_PRINT("enter", ("thd: 0x%lx", (long) 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;
+  pthread_mutex_lock(&LOCK_event_metadata);
 
-  if ((ret= simple_open_n_lock_tables(thd, &tables)))
+  if (opt_event_scheduler == EVENTS_DISABLED)
   {
-    sql_print_error("SCHEDULER: Cannot open mysql.db");
-    ret= TRUE;
+    my_error(ER_OPTION_PREVENTS_STATEMENT,
+             MYF(0), "--event-scheduler=DISABLED or --skip-grant-tables");
+    ret= 1;
+    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("SCHEDULER: Cannot open mysql.user");
-    ret= TRUE;
-  }
+  if (new_state == EVENTS_ON)
+    ret= scheduler->start();
   else
+    ret= scheduler->stop();
+
+  if (ret)
   {
-    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);
+    my_error(ER_EVENT_SET_VAR_ERROR, MYF(0));
+    goto end;
   }
 
-  thd->restore_backup_open_tables_state(&backup);
+  opt_event_scheduler= new_state;
 
+end:
+  pthread_mutex_unlock(&LOCK_event_metadata);
   DBUG_RETURN(ret);
 }
 
@@ -934,7 +927,8 @@
 
   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("Event Scheduler: "
+                    "Failed to open table mysql.event");
     DBUG_RETURN(EVEX_OPEN_TABLE_FAILED);
   }
 
@@ -951,8 +945,9 @@
 
     if ((ret= et->load_from_row(thd, table)))
     {
-      sql_print_error("SCHEDULER: Error while loading from mysql.event. "
-                      "Table probably corrupted");
+      sql_print_error("Event Scheduler: "
+                      "Error while reading from mysql.event. "
+                      "The table is probably corrupted");
       break;
     }
     if (et->status != Event_queue_element::ENABLED)
@@ -965,7 +960,8 @@
     /* let's find when to be executed */
     if (et->compute_next_execution_time())
     {
-      sql_print_error("SCHEDULER: Error while computing execution time of %s.%s."
+      sql_print_error("Event Scheduler: Error while computing execution "
+                      "time of %s.%s."
                       " Skipping", et->dbname.str, et->name.str);
       continue;
     }
@@ -982,11 +978,13 @@
       */
       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");
+        sql_print_error("Event 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("Event Scheduler: "
+                        "Error while compiling %s.%s. Aborting the load",
                         et->dbname.str, et->name.str);
         break;
       default:
@@ -1018,7 +1016,7 @@
   else
   {
     ret= 0;
-    sql_print_information("SCHEDULER: Loaded %d event%s", count,
+    sql_print_information("Event Scheduler: Loaded %d event%s", count,
                           (count == 1)?"":"s");
   }
 

--- 1.52/sql/events.h	2007-01-29 20:46:26 +03:00
+++ 1.53/sql/events.h	2007-03-21 23:36:27 +03:00
@@ -15,11 +15,9 @@
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
-class sp_name;
 class Event_parse_data;
 class Event_db_repository;
 class Event_queue;
-class Event_queue_element;
 class Event_scheduler;
 
 /* Return codes */
@@ -38,6 +36,26 @@
 int
 sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs);
 
+/**
+  @class Events -- a facade to the functionality of the Event Scheduler.
+
+  Every public operation against the scheduler has to be executed via the
+  interface provided by a static method of this class. No instance of this
+  class is ever created and it has no non-static data members.
+
+  The life cycle of the Events module is the following:
+
+  At server start up:
+     set_opt_event_scheduler() -> init_mutexes() -> init()
+  When the server is running:
+     create_event(), drop_event(), start_or_stop_event_scheduler(), etc
+  At shutdown:
+     deinit(), destroy_mutexes().
+
+  The peculiar initialization and shutdown cycle is an adaptation to the
+  outside server startup/shutdown framework and mimics the rest of MySQL
+  subsystems (ACL, time zone tables, etc).
+*/
 
 class Events
 {
@@ -50,47 +68,48 @@
     EVENTS_DISABLED= 4
   };
 
-  static enum_opt_event_scheduler opt_event_scheduler;
-  static TYPELIB opt_typelib;
   static TYPELIB var_typelib;
 
-  bool
-  init();
+  static bool
+  set_opt_event_scheduler(const char *argument);
 
-  void
-  deinit();
+  static const char *
+  get_opt_event_scheduler_str();
 
-  void
-  init_mutexes();
+  /* A hack needed for Event_queue_element */
+  static Event_db_repository *
+  get_db_repository()
+  { return db_repository; }
 
-  void
-  destroy_mutexes();
+  static bool
+  init(my_bool opt_noacl);
 
-  bool
-  start_execution_of_events();
+  static void
+  deinit();
 
-  bool
-  stop_execution_of_events();
+  static void
+  init_mutexes();
 
-  bool
-  is_execution_of_events_started();
+  static void
+  destroy_mutexes();
 
-  static Events *
-  get_instance();
+  static bool
+  start_or_stop_event_scheduler(enum enum_opt_event_scheduler new_state);
 
-  bool
+  static bool
   create_event(THD *thd, Event_parse_data *parse_data, bool if_exists);
 
-  bool
-  update_event(THD *thd, Event_parse_data *parse_data, sp_name *rename_to);
+  static bool
+  update_event(THD *thd, Event_parse_data *parse_data,
+               LEX_STRING *new_db_name, LEX_STRING *new_name);
 
-  bool
+  static bool
   drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists);
 
-  void
+  static void
   drop_schema_events(THD *thd, char *db);
 
-  bool
+  static bool
   show_create_event(THD *thd, LEX_STRING dbname, LEX_STRING name);
 
   /* Needed for both SHOW CREATE EVENT and INFORMATION_SCHEMA */
@@ -101,30 +120,25 @@
   static int
   fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */);
 
-  void
+  static void
   dump_internal_status();
 
+
 private:
-  bool
-  check_system_tables(THD *thd);
+  static bool check_if_system_tables_error();
 
-  int
+  static int
   load_events_from_db(THD *thd);
 
-  /* Singleton DP is used */
-  Events();
-  ~Events(){}
-
-  /* Singleton instance */
-  static Events singleton;
-
-  Event_queue         *event_queue;
-  Event_scheduler     *scheduler;
-  Event_db_repository *db_repository;
-
-  pthread_mutex_t LOCK_event_metadata;
+private:
+  static bool check_system_tables_error;
+  static TYPELIB opt_typelib;
+  static enum_opt_event_scheduler opt_event_scheduler;
+  static Event_queue         *event_queue;
+  static Event_scheduler     *scheduler;
+  static Event_db_repository *db_repository;
 
-  bool check_system_tables_error;
+  static pthread_mutex_t LOCK_event_metadata;
 
   /* Prevent use of these */
   Events(const Events &);

--- 1.24/sql/event_db_repository.cc	2007-03-20 00:37:25 +03:00
+++ 1.25/sql/event_db_repository.cc	2007-03-21 23:36:27 +03:00
@@ -468,14 +468,6 @@
   if (simple_open_n_lock_tables(thd, &tables))
     DBUG_RETURN(1);
 
-  if (table_check_intact(tables.table, ET_FIELD_COUNT,
-                         event_table_fields,
-                         &mysql_event_last_create_time,
-                         ER_CANNOT_LOAD_FROM_TABLE))
-  {
-    close_thread_tables(thd);
-    DBUG_RETURN(2);
-  }
   *table= tables.table;
   tables.table->use_all_columns();
   DBUG_RETURN(0);
@@ -1003,3 +995,153 @@
 
   DBUG_RETURN(ret);
 }
+
+
+/**
+  Update the event record in mysql.event table with a changed status
+  and/or last execution time.
+*/
+
+bool
+Event_db_repository::
+update_timing_fields_for_event(THD *thd,
+                               LEX_STRING event_db_name,
+                               LEX_STRING event_name,
+                               bool update_last_executed,
+                               my_time_t last_executed,
+                               bool update_status,
+                               ulonglong status)
+{
+  TABLE *table;
+  Field **fields;
+  Open_tables_state backup;
+  int ret= FALSE;
+
+  DBUG_ENTER("Event_db_repository::update_timing_fields_for_event");
+
+  thd->reset_n_backup_open_tables_state(&backup);
+
+  if (open_event_table(thd, TL_WRITE, &table))
+  {
+    ret= TRUE;
+    goto done;
+  }
+  fields= table->field;
+  if ((ret= find_named_event(thd, event_db_name, event_name, table)))
+    goto done;
+
+  store_record(table, record[1]);
+  /* Don't update create on row update. */
+  table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
+
+  if (update_last_executed)
+  {
+    TIME time;
+    my_tz_UTC->gmt_sec_to_TIME(&time, last_executed);
+
+    fields[ET_FIELD_LAST_EXECUTED]->set_notnull();
+    fields[ET_FIELD_LAST_EXECUTED]->store_time(&time,
+                                               MYSQL_TIMESTAMP_DATETIME);
+  }
+  if (update_status)
+  {
+    fields[ET_FIELD_STATUS]->set_notnull();
+    fields[ET_FIELD_STATUS]->store(status, TRUE);
+  }
+
+  if ((table->file->ha_update_row(table->record[1], table->record[0])))
+    ret= TRUE;
+
+done:
+  close_thread_tables(thd);
+  thd->restore_backup_open_tables_state(&backup);
+
+  DBUG_RETURN(ret);
+}
+
+
+/**
+  Open mysql.db, mysql.user and mysql.event and checks whether:
+    - mysql.db exists and is up to date (or from a newer version of MySQL),
+    - mysql.user has column Event_priv at an expected position,
+    - mysql.event exists and is up to date (or from a newer version of
+      MySQL)
+
+  This function is called only when the server is started.
+
+  @retval FALSE  OK
+  @retval TRUE   Error, an error message is output to the error log.
+*/
+
+bool
+Event_db_repository::check_system_tables(THD *thd)
+{
+  TABLE_LIST tables;
+  Open_tables_state backup;
+  int ret= FALSE;
+  const int event_priv_column_position= 29;
+
+  DBUG_ENTER("Event_db_repository::check_system_tables");
+  DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd));
+
+  thd->reset_n_backup_open_tables_state(&backup);
+
+  /* Check mysql.db */
+  tables.init_one_table("mysql", "db", TL_READ);
+
+  if (simple_open_n_lock_tables(thd, &tables))
+  {
+    ret= 1;
+    sql_print_error("Cannot open mysql.db");
+  }
+  else
+  {
+    if (table_check_intact(tables.table, MYSQL_DB_FIELD_COUNT,
+                           mysql_db_table_fields))
+      ret= 1;
+    /* in case of an error, the message is printed inside table_check_intact */
+
+    close_thread_tables(thd);
+  }
+  /* Check mysql.user */
+  tables.init_one_table("mysql", "user", TL_READ);
+
+  if (simple_open_n_lock_tables(thd, &tables))
+  {
+    ret= 1;
+    sql_print_error("Cannot open mysql.user");
+  }
+  else
+  {
+    if (tables.table->s->fields < event_priv_column_position ||
+        strncmp(tables.table->field[event_priv_column_position]->field_name,
+                STRING_WITH_LEN("Event_priv")))
+    {
+      sql_print_error("mysql.user has no `Event_priv` column at position %d",
+                      event_priv_column_position);
+      ret= 1;
+    }
+    close_thread_tables(thd);
+  }
+  /* Check mysql.event */
+  tables.init_one_table("mysql", "event", TL_READ);
+
+  if (simple_open_n_lock_tables(thd, &tables))
+  {
+    ret= 1;
+    sql_print_error("Cannot open mysql.event");
+  }
+  else
+  {
+    if (table_check_intact(tables.table, ET_FIELD_COUNT, event_table_fields))
+      ret= 1;
+    /* in case of an error, the message is printed inside table_check_intact */
+    close_thread_tables(thd);
+  }
+
+  thd->restore_backup_open_tables_state(&backup);
+
+  DBUG_RETURN(test(ret));
+}
+
+

--- 1.13/sql/event_db_repository.h	2007-03-16 17:31:04 +03:00
+++ 1.14/sql/event_db_repository.h	2007-03-21 23:36:27 +03:00
@@ -15,6 +15,12 @@
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
+/*
+  This is a private header file of Events module. Please do not include it
+  directly. All public declarations of Events module should be stored in
+  events.h and event_data_objects.h.
+*/
+
 #define EVEX_OPEN_TABLE_FAILED  -1
 
 enum enum_events_table_field
@@ -80,6 +86,16 @@
   int
   fill_schema_events(THD *thd, TABLE_LIST *tables, const char *db);
 
+  bool
+  update_timing_fields_for_event(THD *thd,
+                                 LEX_STRING event_db_name,
+                                 LEX_STRING event_name,
+                                 bool update_last_executed,
+                                 my_time_t last_executed,
+                                 bool update_status,
+                                 ulonglong status);
+
+  static bool check_system_tables(THD *thd);
 private:
   void
   drop_events_by_field(THD *thd, enum enum_events_table_field field,
@@ -90,9 +106,6 @@
 
   bool
   table_scan_all_for_i_s(THD *thd, TABLE *schema_table, TABLE *event_table);
-
-  static bool
-  check_system_tables(THD *thd);
 
   /* Prevent use of these */
   Event_db_repository(const Event_db_repository &);

--- 1.27/sql/event_queue.cc	2007-03-20 00:37:25 +03:00
+++ 1.28/sql/event_queue.cc	2007-03-21 23:36:27 +03:00
@@ -82,38 +82,19 @@
 Event_queue::Event_queue()
   :mutex_last_unlocked_at_line(0), mutex_last_locked_at_line(0),
    mutex_last_attempted_lock_at_line(0),
-   mutex_queue_data_locked(FALSE), mutex_queue_data_attempting_lock(FALSE)
+   mutex_queue_data_locked(FALSE),
+   mutex_queue_data_attempting_lock(FALSE),
+   next_activation_at(0)
 {
   mutex_last_unlocked_in_func= mutex_last_locked_in_func=
     mutex_last_attempted_lock_in_func= "";
-  next_activation_at= 0;
-}
-
-
-/*
-  Inits mutexes.
 
-  SYNOPSIS
-    Event_queue::init_mutexes()
-*/
-
-void
-Event_queue::init_mutexes()
-{
   pthread_mutex_init(&LOCK_event_queue, MY_MUTEX_INIT_FAST);
   pthread_cond_init(&COND_queue_state, NULL);
 }
 
 
-/*
-  Destroys mutexes.
-
-  SYNOPSIS
-    Event_queue::deinit_mutexes()
-*/
-
-void
-Event_queue::deinit_mutexes()
+Event_queue::~Event_queue()
 {
   pthread_mutex_destroy(&LOCK_event_queue);
   pthread_cond_destroy(&COND_queue_state);
@@ -148,7 +129,7 @@
                     0 /*max_on_top*/, event_queue_element_compare_q,
                     NULL, EVENT_QUEUE_EXTENT))
   {
-    sql_print_error("SCHEDULER: Can't initialize the execution queue");
+    sql_print_error("Event Scheduler: Can't initialize the execution queue");
     goto err;
   }
 
@@ -463,7 +444,8 @@
   uint i;
   DBUG_ENTER("Event_queue::empty_queue");
   DBUG_PRINT("enter", ("Purging the queue. %u element(s)", queue.elements));
-  sql_print_information("SCHEDULER: Purging queue. %u events", queue.elements);
+  sql_print_information("Event Scheduler: Purging the queue. %u events",
+                        queue.elements);
   /* empty the queue */
   for (i= 0; i < queue.elements; ++i)
   {
@@ -596,7 +578,7 @@
     if (top->status == Event_queue_element::DISABLED)
     {
       DBUG_PRINT("info", ("removing from the queue"));
-      sql_print_information("SCHEDULER: Last execution of %s.%s. %s",
+      sql_print_information("Event Scheduler: Last execution of %s.%s. %s",
                             top->dbname.str, top->name.str,
                             top->dropped? "Dropping.":"");
       delete top;

--- 1.15/sql/event_queue.h	2007-03-16 17:31:04 +03:00
+++ 1.16/sql/event_queue.h	2007-03-21 23:36:27 +03:00
@@ -25,16 +25,11 @@
 {
 public:
   Event_queue();
-
-  void
-  init_mutexes();
-
-  void
-  deinit_mutexes();
+  ~Event_queue();
 
   bool
   init_queue(THD *thd);
-  
+
   void
   deinit_queue();
 

--- 1.37/sql/event_scheduler.cc	2007-03-16 17:31:04 +03:00
+++ 1.38/sql/event_scheduler.cc	2007-03-21 23:36:27 +03:00
@@ -37,7 +37,6 @@
 
 
 Event_db_repository *Event_worker_thread::db_repository;
-Events *Event_worker_thread::events_facade;
 
 
 static
@@ -78,7 +77,7 @@
   char prefix_buf[5 * STRING_BUFFER_USUAL_SIZE];
   String prefix(prefix_buf, sizeof(prefix_buf), system_charset_info);
   prefix.length(0);
-  prefix.append("SCHEDULER: [");
+  prefix.append("Event Scheduler: [");
 
   append_identifier(thd, &prefix, et->definer.str, et->definer.length);
   prefix.append("][", 2);
@@ -304,7 +303,8 @@
     goto end;
   }
 
-  sql_print_information("SCHEDULER: [%s.%s of %s] executing in thread %lu. ",
+  sql_print_information("Event Scheduler: "
+                        "[%s.%s of %s] executing in thread %lu. ",
                         job_data->dbname.str, job_data->name.str,
                         job_data->definer.str, thd->thread_id);
 
@@ -314,23 +314,25 @@
 
   print_warnings(thd, job_data);
 
-  sql_print_information("SCHEDULER: [%s.%s of %s] executed in thread %lu. "
+  sql_print_information("Event Scheduler: "
+                        "[%s.%s of %s] executed in thread %lu. "
                         "RetCode=%d", job_data->dbname.str, job_data->name.str,
                         job_data->definer.str, thd->thread_id, ret);
   if (ret == EVEX_COMPILE_ERROR)
-    sql_print_information("SCHEDULER: COMPILE ERROR for event %s.%s of %s",
+    sql_print_information("Event Scheduler: "
+                          "COMPILE ERROR for event %s.%s of %s",
                           job_data->dbname.str, job_data->name.str,
                           job_data->definer.str);
   else if (ret == EVEX_MICROSECOND_UNSUP)
-    sql_print_information("SCHEDULER: MICROSECOND is not supported");
+    sql_print_information("Event Scheduler: MICROSECOND is not supported");
 
 end:
   delete job_data;
 
   if (event->dropped)
   {
-    sql_print_information("SCHEDULER: Dropping %s.%s", event->dbname.str,
-                          event->name.str);
+    sql_print_information("Event Scheduler: Dropping %s.%s",
+                          event->dbname.str, event->name.str);
     /*
       Using db_repository can lead to a race condition because we access
       the table without holding LOCK_metadata.
@@ -346,7 +348,7 @@
       problem. However, this comes at the price of introduction bi-directional
       association between class Events and class Event_worker_thread.
     */
-    events_facade->drop_event(thd, event->dbname, event->name, FALSE);
+    Events::drop_event(thd, event->dbname, event->name, FALSE);
   }
   DBUG_PRINT("info", ("Done with Event %s.%s", event->dbname.str,
              event->name.str));
@@ -357,54 +359,18 @@
 }
 
 
-/*
-  Performs initialization of the scheduler data, outside of the
-  threading primitives.
-
-  SYNOPSIS
-    Event_scheduler::init_scheduler()
-*/
-
-void
-Event_scheduler::init_scheduler(Event_queue *q)
-{
-  LOCK_DATA();
-  queue= q;
-  started_events= 0;
-  scheduler_thd= NULL;
-  state= INITIALIZED;
-  UNLOCK_DATA();
-}
-
-
-void
-Event_scheduler::deinit_scheduler() {}
-
-
-/*
-  Inits scheduler's threading primitives.
-
-  SYNOPSIS
-    Event_scheduler::init_mutexes()
-*/
-
-void
-Event_scheduler::init_mutexes()
+Event_scheduler::Event_scheduler(Event_queue *queue_arg)
+  :state(UNINITIALIZED),
+  queue(queue_arg),
+  started_events(0),
+  scheduler_thd(NULL)
 {
   pthread_mutex_init(&LOCK_scheduler_state, MY_MUTEX_INIT_FAST);
   pthread_cond_init(&COND_state, NULL);
 }
 
 
-/*
-  Deinits scheduler's threading primitives.
-
-  SYNOPSIS
-    Event_scheduler::deinit_mutexes()
-*/
-
-void
-Event_scheduler::deinit_mutexes()
+Event_scheduler::~Event_scheduler()
 {
   pthread_mutex_destroy(&LOCK_scheduler_state);
   pthread_cond_destroy(&COND_state);
@@ -442,7 +408,7 @@
 
   if (!(new_thd= new THD))
   {
-    sql_print_error("SCHEDULER: Cannot init manager event thread");
+    sql_print_error("Event Scheduler: Cannot init manager event thread");
     ret= TRUE;
     goto end;
   }
@@ -458,7 +424,7 @@
   scheduler_thd= new_thd;
   DBUG_PRINT("info", ("Setting state go RUNNING"));
   state= RUNNING;
-  DBUG_PRINT("info", ("Forking new thread for scheduduler. THD: 0x%lx", (long) new_thd));
+  DBUG_PRINT("info", ("Forking new thread for scheduler. THD: 0x%lx", (long) new_thd));
   if (pthread_create(&th, &connection_attrib, event_scheduler_thread,
                     (void*)scheduler_param_value))
   {
@@ -501,7 +467,7 @@
   int res= FALSE;
   DBUG_ENTER("Event_scheduler::run");
 
-  sql_print_information("SCHEDULER: Manager thread started with id %lu",
+  sql_print_information("Event Scheduler: Manager thread started with id %lu",
                         thd->thread_id);
   /*
     Recalculate the values in the queue because there could have been stops
@@ -516,7 +482,8 @@
     /* Gets a minimized version */
     if (queue->get_top_for_execution_if_time(thd, &event_name))
     {
-      sql_print_information("SCHEDULER: Serious error during getting next "
+      sql_print_information("Event Scheduler: "
+                            "Serious error during getting next "
                             "event to execute. Stopping");
       break;
     }
@@ -540,7 +507,7 @@
   state= INITIALIZED;
   pthread_cond_signal(&COND_state);
   UNLOCK_DATA();
-  sql_print_information("SCHEDULER: Stopped");
+  sql_print_information("Event Scheduler: Stopped");
 
   DBUG_RETURN(res);
 }
@@ -631,10 +598,13 @@
 }
 
 
-/*
+/**
   Stops the scheduler (again). Waits for acknowledgement from the
   scheduler that it has stopped - synchronous stopping.
 
+  Already running events will not be stopped. If the user needs
+  them stopped manual intervention is needed.
+
   SYNOPSIS
     Event_scheduler::stop()
 
@@ -676,13 +646,14 @@
     /* Lock from delete */
     pthread_mutex_lock(&scheduler_thd->LOCK_delete);
     /* This will wake up the thread if it waits on Queue's conditional */
-    sql_print_information("SCHEDULER: Killing manager thread %lu",
+    sql_print_information("Event Scheduler: Killing manager thread %lu",
                           scheduler_thd->thread_id);
     scheduler_thd->awake(THD::KILL_CONNECTION);
     pthread_mutex_unlock(&scheduler_thd->LOCK_delete);
 
     /* thd could be 0x0, when shutting down */
-    sql_print_information("SCHEDULER: Waiting the manager thread to reply");
+    sql_print_information("Event Scheduler: "
+                          "Waiting the manager thread to reply");
     COND_STATE_WAIT(thd, NULL, "Waiting scheduler to stop");
   } while (state == STOPPING);
   DBUG_PRINT("info", ("Manager thread has cleaned up. Set state to INIT"));

--- 1.20/sql/event_scheduler.h	2007-01-29 20:46:26 +03:00
+++ 1.21/sql/event_scheduler.h	2007-03-21 23:36:27 +03:00
@@ -15,6 +15,12 @@
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
+/*
+  This file is internal to Events module. Please do not include it directly.
+  All public declarations of Events module are in events.h and
+  event_data_objects.h.
+*/
+
 
 class Event_queue;
 class Event_job_data;
@@ -31,14 +37,13 @@
 deinit_event_thread(THD *thd);
 
 
-class Event_worker_thread 
+class Event_worker_thread
 {
 public:
   static void
-  init(Events *events, Event_db_repository *db_repo)
+  init(Event_db_repository *db_repository_arg)
   {
-    db_repository= db_repo;
-    events_facade= events;
+    db_repository= db_repository_arg;
   }
 
   void
@@ -56,8 +61,9 @@
 class Event_scheduler
 {
 public:
-  Event_scheduler():state(UNINITIALIZED){}
-  ~Event_scheduler(){}
+  Event_scheduler(Event_queue *event_queue_arg);
+  ~Event_scheduler();
+
 
   /* State changing methods follow */
 
@@ -74,19 +80,6 @@
   bool
   run(THD *thd);
 
-  void 
-  init_scheduler(Event_queue *queue);
-
-  void
-  deinit_scheduler();
-
-  void
-  init_mutexes();
-
-  void
-  deinit_mutexes();
-
-  /* Information retrieving methods follow */
   bool
   is_running();
 

--- 1.88/sql/event_data_objects.cc	2007-03-20 00:42:03 +03:00
+++ 1.89/sql/event_data_objects.cc	2007-03-21 23:36:27 +03:00
@@ -20,8 +20,6 @@
 #include "event_db_repository.h"
 #include "sp_head.h"
 
-/* That's a provisional solution */
-extern Event_db_repository events_event_db_repository;
 
 #define EVEX_MAX_INTERVAL_VALUE 1000000000L
 
@@ -1595,10 +1593,8 @@
 bool
 Event_queue_element::update_timing_fields(THD *thd)
 {
-  TABLE *table;
-  Field **fields;
-  Open_tables_state backup;
-  int ret= FALSE;
+  Event_db_repository *db_repository= Events::get_db_repository();
+  int ret;
 
   DBUG_ENTER("Event_queue_element::update_timing_fields");
 
@@ -1608,46 +1604,13 @@
   if (!(status_changed || last_executed_changed))
     DBUG_RETURN(0);
 
-  thd->reset_n_backup_open_tables_state(&backup);
-
-  if (events_event_db_repository.open_event_table(thd, TL_WRITE, &table))
-  {
-    ret= TRUE;
-    goto done;
-  }
-  fields= table->field;
-  if ((ret= events_event_db_repository.
-                                 find_named_event(thd, dbname, name, table)))
-    goto done;
-
-  store_record(table,record[1]);
-  /* Don't update create on row update. */
-  table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
-
-  if (last_executed_changed)
-  {
-    TIME time;
-    my_tz_UTC->gmt_sec_to_TIME(&time, last_executed);
-
-    fields[ET_FIELD_LAST_EXECUTED]->set_notnull();
-    fields[ET_FIELD_LAST_EXECUTED]->store_time(&time,
-                                               MYSQL_TIMESTAMP_DATETIME);
-    last_executed_changed= FALSE;
-  }
-  if (status_changed)
-  {
-    fields[ET_FIELD_STATUS]->set_notnull();
-    fields[ET_FIELD_STATUS]->store((longlong)status, TRUE);
-    status_changed= FALSE;
-  }
-
-  if ((table->file->ha_update_row(table->record[1], table->record[0])))
-    ret= TRUE;
-
-done:
-  close_thread_tables(thd);
-  thd->restore_backup_open_tables_state(&backup);
-
+  ret= db_repository->update_timing_fields_for_event(thd,
+                                                     dbname, name,
+                                                     last_executed_changed,
+                                                     last_executed,
+                                                     status_changed,
+                                                     (ulonglong) status);
+  last_executed_changed= status_changed= FALSE;
   DBUG_RETURN(ret);
 }
 
@@ -1927,8 +1890,8 @@
                           thd->is_fatal_error));
     lex.unit.cleanup();
 
-    sql_print_error("SCHEDULER: Error during compilation of %s.%s or "
-                    "thd->is_fatal_error: %d",
+    sql_print_error("Event Scheduler: "
+                    "Error during compilation of %s.%s or a fatal error: %d",
                     dbname.str, name.str, thd->is_fatal_error);
 
     ret= EVEX_COMPILE_ERROR;

--- 1.149/sql/share/errmsg.txt	2007-03-20 00:37:37 +03:00
+++ 1.150/sql/share/errmsg.txt	2007-03-21 23:36:28 +03:00
@@ -5881,10 +5881,10 @@
         eng "No datetime expression provided"
         ger "Kein DATETIME-Ausdruck angegeben"
 ER_COL_COUNT_DOESNT_MATCH_CORRUPTED
-        eng "Column count of mysql.%s is wrong. Expected %d, found %d. Table probably corrupted"
+        eng "Column count of mysql.%s is wrong. Expected %d, found %d. The table is probably corrupted"
 ER_CANNOT_LOAD_FROM_TABLE
-        eng "Cannot load from mysql.%s. Table probably corrupted. See error log."
+        eng "Cannot load from mysql.%s. The table is probably corrupted. Please see the error log for details"
 ER_EVENT_CANNOT_DELETE
         eng "Failed to delete the event from mysql.event"
@@ -5914,8 +5914,8 @@
         eng "Upholding foreign key constraints for table '%.64s', entry '%-.64s', key %d would lead to a duplicate entry"
 ER_COL_COUNT_DOESNT_MATCH_PLEASE_UPDATE
-        eng "Column count of mysql.%s is wrong. Expected %d, found %d. Created with MySQL %d, now running %d. Please use scripts/mysql_fix_privilege_tables"
-        ger "Spaltenanzahl von mysql.%s falsch. %d erwartet, aber %d erhalten. Erzeugt mit MySQL %d, jetzt unter %d. Bitte benutzen Sie scripts/mysql_fix_privilege_tables, um den Fehler zu beheben"
+        eng "Column count of mysql.%s is wrong. Expected %d, found %d. Created with MySQL %d, now running %d. Please use mysql_upgrade program."
+        ger "Spaltenanzahl von mysql.%s falsch. %d erwartet, aber %d erhalten. Erzeugt mit MySQL %d, jetzt unter %d. Bitte benutzen Sie mysql_upgrade, um den Fehler zu beheben"
 ER_REMOVED_SPACES
         eng "Leading spaces are removed from name '%s'"

--- 1.222/sql/set_var.cc	2007-03-20 00:37:31 +03:00
+++ 1.223/sql/set_var.cc	2007-03-21 23:36:28 +03:00
@@ -4009,24 +4009,13 @@
   int res;
   /* here start the thread if not running. */
   DBUG_ENTER("sys_var_event_scheduler::update");
-  if (Events::opt_event_scheduler == Events::EVENTS_DISABLED)
-  {
-    my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--event-scheduler=DISABLED or --skip-grant-tables");
-    DBUG_RETURN(TRUE);
-  }
-
   DBUG_PRINT("info", ("new_value: %d", (int) var->save_result.ulong_value));
 
-  if (var->save_result.ulong_value == Events::EVENTS_ON)
-    res= Events::get_instance()->start_execution_of_events();
-  else if (var->save_result.ulong_value == Events::EVENTS_OFF)
-    res= Events::get_instance()->stop_execution_of_events();
-  else
-  {
-    assert(0);                                  // Impossible
-  }
-  if (res)
-    my_error(ER_EVENT_SET_VAR_ERROR, MYF(0));
+  enum Events::enum_opt_event_scheduler
+    new_state=
+    (enum Events::enum_opt_event_scheduler) var->save_result.ulong_value;
+
+  res= Events::start_or_stop_event_scheduler(new_state);
 
   DBUG_RETURN((bool) res);
 }
@@ -4035,15 +4024,7 @@
 byte *sys_var_event_scheduler::value_ptr(THD *thd, enum_var_type type,
                                          LEX_STRING *base)
 {
-  int state;
-  if (Events::opt_event_scheduler == Events::EVENTS_DISABLED)
-    state= Events::EVENTS_DISABLED;              // This should be DISABLED
-  else if (Events::get_instance()->is_execution_of_events_started())
-    state= Events::EVENTS_ON;                    // This should be ON
-  else
-    state= Events::EVENTS_OFF;                   // This should be OFF
-
-  return (byte*) Events::opt_typelib.type_names[state];
+  return (byte *) Events::get_opt_event_scheduler_str();
 }
 
 

--- 1.8/sql/sql_servers.cc	2007-03-17 02:13:19 +03:00
+++ 1.9/sql/sql_servers.cc	2007-03-21 23:36:28 +03:00
@@ -208,7 +208,7 @@
 
   if (simple_open_n_lock_tables(thd, tables))
   {
-    sql_print_error("Fatal error: Can't open and lock privilege tables: %s",
+    sql_print_error("Can't open and lock privilege tables: %s",
 		    thd->net.last_error);
     goto end;
   }
Thread
bk commit into 5.1 tree (kostja:1.2507)konstantin21 Mar