List:Commits« Previous MessageNext Message »
From:ahristov Date:June 27 2006 11:28pm
Subject:bk commit into 5.1 tree (andrey:1.2215)
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
  1.2215 06/06/28 01:28:03 andrey@lmy004. +17 -0
  WL#3337 (Events new architecture)
  5th cut, moved DB related code to Event_db_repository and
  updated accordingly the remanining code.
  Moved change/restore_security_context() to class THD
  Removed events_priv.h
  Next step is to reorganize create/update_event() and parsing for them.
  But probably some other refactoring could be done in the meanwhile.
  The changes so far pass the test suite.

  sql/sql_show.cc
    1.356 06/06/28 01:27:53 andrey@lmy004. +2 -2
    reorganize Events code

  sql/sql_parse.cc
    1.568 06/06/28 01:27:53 andrey@lmy004. +11 -9
    reorganize Events code

  sql/sql_db.cc
    1.138 06/06/28 01:27:52 andrey@lmy004. +1 -1
    reorganize Events code

  sql/sql_class.h
    1.302 06/06/28 01:27:52 andrey@lmy004. +8 -0
    add ::change_security_context() and restore_security_context()

  sql/sql_class.cc
    1.268 06/06/28 01:27:52 andrey@lmy004. +57 -0
    add ::change_security_context() and restore_security_context()

  sql/set_var.cc
    1.178 06/06/28 01:27:52 andrey@lmy004. +1 -1
    reorganize events code

  sql/mysqld.cc
    1.564 06/06/28 01:27:52 andrey@lmy004. +1 -1
    reorganize events code

  sql/events.h
    1.34 06/06/28 01:27:52 andrey@lmy004. +56 -39
    reorganize events code

  sql/events.cc
    1.48 06/06/28 01:27:52 andrey@lmy004. +32 -780
    reorganize events code

  sql/event_scheduler.h
    1.7 06/06/28 01:27:52 andrey@lmy004. +15 -22
    reorganize events code

  sql/event_scheduler.cc
    1.10 06/06/28 01:27:52 andrey@lmy004. +19 -72
    reorganize events code

  sql/event_db_repository.h
    1.2 06/06/28 01:27:52 andrey@lmy004. +82 -0
    reorganize events code

  sql/event_db_repository.cc
    1.2 06/06/28 01:27:52 andrey@lmy004. +854 -0
    reorganize events code

  sql/event_data_objects.h
    1.5 06/06/28 01:27:52 andrey@lmy004. +32 -0
    reorganize events code

  sql/event_data_objects.cc
    1.61 06/06/28 01:27:52 andrey@lmy004. +38 -50
    reorganize events code

  sql/Makefile.am
    1.147 06/06/28 01:27:52 andrey@lmy004. +1 -1
    events_priv.h is no more

  BitKeeper/deleted/.del-events_priv.h~2e8bce2cf35997df
    1.26 06/06/28 00:09:26 andrey@lmy004. +0 -0
    Delete: sql/events_priv.h

# 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:	lmy004.
# Root:	/work/mysql-5.1-runtime-wl3337

--- 1.146/sql/Makefile.am	2006-06-27 08:48:37 +02:00
+++ 1.147/sql/Makefile.am	2006-06-28 01:27:52 +02:00
@@ -64,7 +64,7 @@ noinst_HEADERS =	item.h item_func.h item
 			tztime.h my_decimal.h\
 			sp_head.h sp_pcontext.h sp_rcontext.h sp.h sp_cache.h \
 			parse_file.h sql_view.h	sql_trigger.h \
-			sql_array.h sql_cursor.h events.h events_priv.h \
+			sql_array.h sql_cursor.h events.h \
 			sql_plugin.h authors.h sql_partition.h event_data_objects.h \
                         event_queue.h event_db_repository.h \
 			partition_info.h partition_element.h event_scheduler.h \

--- 1.563/sql/mysqld.cc	2006-06-22 16:59:52 +02:00
+++ 1.564/sql/mysqld.cc	2006-06-28 01:27:52 +02:00
@@ -886,7 +886,7 @@ static void close_connections(void)
   }
   (void) pthread_mutex_unlock(&LOCK_thread_count); // For unlink from list
 
-  Events::shutdown();
+  Events::deinit();
   end_slave();
 
   if (thread_count)

--- 1.267/sql/sql_class.cc	2006-06-19 12:14:21 +02:00
+++ 1.268/sql/sql_class.cc	2006-06-28 01:27:52 +02:00
@@ -2048,6 +2048,63 @@ bool Security_context::set_user(char *us
   return user == 0;
 }
 
+/*
+  Switches the security context
+  SYNOPSIS
+    THD::change_security_context()
+      user    The user
+      host    The host of the user
+      db      The schema for which the security_ctx will be loaded
+      s_ctx   Security context to load state into
+      backup  Where to store the old context
+  
+  RETURN VALUE
+    FALSE  OK
+    TRUE   Error (generates error too)
+*/
+
+bool
+THD::change_security_context(LEX_STRING user, LEX_STRING host,
+                             LEX_STRING db, Security_context *s_ctx,
+                             Security_context **backup)
+{
+  DBUG_ENTER("change_security_context");
+  DBUG_PRINT("info",("%s@%s@%s", user.str, host.str, db.str));
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+  s_ctx->init();
+  *backup= 0;
+  if (acl_getroot_no_password(s_ctx, user.str, host.str, host.str, db.str))
+  {
+    my_error(ER_NO_SUCH_USER, MYF(0), user.str, host.str);
+    DBUG_RETURN(TRUE);
+  }
+  *backup= security_ctx;
+  security_ctx= s_ctx;
+#endif
+  DBUG_RETURN(FALSE);
+}
+
+
+/*
+  Restores the security context
+  SYNOPSIS
+    restore_security_context()
+      thd     Thread
+      backup  Context to switch to
+*/
+
+void
+THD::restore_security_context(Security_context *backup)
+{
+  DBUG_ENTER("restore_security_context");
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+  if (backup)
+    security_ctx= backup;
+#endif
+  DBUG_VOID_RETURN;
+}
+
+
 /****************************************************************************
   Handling of open and locked tables states.
 

--- 1.301/sql/sql_class.h	2006-06-22 13:27:43 +02:00
+++ 1.302/sql/sql_class.h	2006-06-28 01:27:52 +02:00
@@ -868,6 +868,14 @@ public:
   char   *db, *catalog;
   Security_context main_security_ctx;
   Security_context *security_ctx;
+  
+  bool
+  change_security_context(LEX_STRING user, LEX_STRING host,
+                          LEX_STRING db, Security_context *s_ctx,
+                          Security_context **backup);  
+
+  void
+  restore_security_context(Security_context *backup);
 
   /* remote (peer) port */
   uint16 peer_port;

--- 1.137/sql/sql_db.cc	2006-06-20 17:09:40 +02:00
+++ 1.138/sql/sql_db.cc	2006-06-28 01:27:52 +02:00
@@ -904,7 +904,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::drop_schema_events(thd, db);
+  error= 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 SELECT DATABASE()

--- 1.567/sql/sql_parse.cc	2006-06-27 11:51:01 +02:00
+++ 1.568/sql/sql_parse.cc	2006-06-28 01:27:53 +02:00
@@ -3847,13 +3847,14 @@ end_with_restore_list:
 
       switch (lex->sql_command) {
       case SQLCOM_CREATE_EVENT:
-        res= Events::create_event(thd, lex->et, lex->event_parse_data,
-                                  (uint) lex->create_info.options,
-                                  &rows_affected);
+        res= Events::get_instance()->
+                  create_event(thd, lex->et, lex->event_parse_data,
+                               (uint) lex->create_info.options, &rows_affected);
         break;
       case SQLCOM_ALTER_EVENT:
-        res= Events::update_event(thd, lex->et, lex->event_parse_data,
-                                  lex->spname, &rows_affected);
+        res= Events::get_instance()->
+                  update_event(thd, lex->et, lex->event_parse_data,
+                               lex->spname, &rows_affected);
         break;
       default:;
       }
@@ -3895,7 +3896,7 @@ end_with_restore_list:
     }
 
     if (lex->sql_command == SQLCOM_SHOW_CREATE_EVENT)
-      res= Events::show_create_event(thd, lex->spname);
+      res= Events::get_instance()->show_create_event(thd, lex->spname);
     else
     {
       uint rows_affected= 1;
@@ -3904,8 +3905,9 @@ end_with_restore_list:
         res= -1;
         break;
       }
-      if (!(res= Events::drop_event(thd, lex->spname, lex->drop_if_exists,
-                                    &rows_affected)))
+      if (!(res= Events::get_instance()->drop_event(thd, lex->spname,
+                                                    lex->drop_if_exists,
+                                                    &rows_affected)))
         send_ok(thd, rows_affected);     
     }
     break;
@@ -3913,7 +3915,7 @@ end_with_restore_list:
 #ifndef DBUG_OFF
   case SQLCOM_SHOW_SCHEDULER_STATUS:
   {
-    res= Events::dump_internal_status(thd);
+    res= Events::get_instance()->dump_internal_status(thd);
     break;
   }
 #endif

--- 1.355/sql/sql_show.cc	2006-06-27 08:48:38 +02:00
+++ 1.356/sql/sql_show.cc	2006-06-28 01:27:53 +02:00
@@ -4324,7 +4324,7 @@ int events_table_index_read_for_db(THD *
 
   DBUG_PRINT("info", ("Using prefix scanning on PK"));
   event_table->file->ha_index_init(0, 1);
-  event_table->field[Events::FIELD_DB]->
+  event_table->field[ET_FIELD_DB]->
         store(thd->lex->select_lex.db, strlen(thd->lex->select_lex.db), scs);
   key_info= event_table->key_info;
   key_len= key_info->key_part[0].store_length;
@@ -4443,7 +4443,7 @@ int fill_schema_events(THD *thd, TABLE_L
               thd->lex->select_lex.db:"(null)"));
 
   thd->reset_n_backup_open_tables_state(&backup);
-  if (Events::open_event_table(thd, TL_READ, &event_table))
+  if (Events::get_instance()->open_event_table(thd, TL_READ, &event_table))
   {
     sql_print_error("Table mysql.event is damaged.");
     thd->restore_backup_open_tables_state(&backup);

--- 1.47/sql/events.cc	2006-06-27 11:51:01 +02:00
+++ 1.48/sql/events.cc	2006-06-28 01:27:52 +02:00
@@ -15,11 +15,10 @@
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
 #include "mysql_priv.h"
-#include "events_priv.h"
 #include "events.h"
 #include "event_data_objects.h"
 #include "event_scheduler.h"
-#include "sp.h"
+#include "event_db_repository.h"
 #include "sp_head.h"
 
 /*
@@ -48,10 +47,6 @@ Warning:
 */
 
 
-MEM_ROOT evex_mem_root;
-time_t mysql_event_last_create_time= 0L;
-
-
 const char *event_scheduler_state_names[]=
     { "OFF", "0", "ON", "1", "SUSPEND", "2", NullS };
 
@@ -63,104 +58,10 @@ TYPELIB Events::opt_typelib=
   NULL
 };
 
+Events Events::singleton;
 
 ulong Events::opt_event_scheduler= 2;
 
-static
-TABLE_FIELD_W_TYPE event_table_fields[Events::FIELD_COUNT] = {
-  {
-    {(char *) STRING_WITH_LEN("db")},
-    {(char *) STRING_WITH_LEN("char(64)")},
-    {(char *) STRING_WITH_LEN("utf8")}
-  }, 
-  {
-    {(char *) STRING_WITH_LEN("name")},
-    {(char *) STRING_WITH_LEN("char(64)")},
-    {(char *) STRING_WITH_LEN("utf8")}
-  },
-  {
-    {(char *) STRING_WITH_LEN("body")},
-    {(char *) STRING_WITH_LEN("longblob")},
-    {NULL, 0}
-  }, 
-  {
-    {(char *) STRING_WITH_LEN("definer")},
-    {(char *) STRING_WITH_LEN("char(77)")},
-    {(char *) STRING_WITH_LEN("utf8")}
-  },
-  {
-    {(char *) STRING_WITH_LEN("execute_at")},
-    {(char *) STRING_WITH_LEN("datetime")},
-    {NULL, 0}
-  }, 
-  {
-    {(char *) STRING_WITH_LEN("interval_value")},
-    {(char *) STRING_WITH_LEN("int(11)")},
-    {NULL, 0}
-  },
-  {
-    {(char *) STRING_WITH_LEN("interval_field")},
-    {(char *) STRING_WITH_LEN("enum('YEAR','QUARTER','MONTH','DAY',"
-    "'HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR',"
-    "'DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND',"
-    "'DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND',"
-    "'SECOND_MICROSECOND')")},
-    {NULL, 0}
-  }, 
-  {
-    {(char *) STRING_WITH_LEN("created")},
-    {(char *) STRING_WITH_LEN("timestamp")},
-    {NULL, 0}
-  },
-  {
-    {(char *) STRING_WITH_LEN("modified")},
-    {(char *) STRING_WITH_LEN("timestamp")},
-    {NULL, 0}
-  }, 
-  {
-    {(char *) STRING_WITH_LEN("last_executed")},
-    {(char *) STRING_WITH_LEN("datetime")},
-    {NULL, 0}
-  },
-  {
-    {(char *) STRING_WITH_LEN("starts")},
-    {(char *) STRING_WITH_LEN("datetime")},
-    {NULL, 0}
-  }, 
-  {
-    {(char *) STRING_WITH_LEN("ends")},
-    {(char *) STRING_WITH_LEN("datetime")},
-    {NULL, 0}
-  },
-  {
-    {(char *) STRING_WITH_LEN("status")},
-    {(char *) STRING_WITH_LEN("enum('ENABLED','DISABLED')")},
-    {NULL, 0}
-  }, 
-  {
-    {(char *) STRING_WITH_LEN("on_completion")},
-    {(char *) STRING_WITH_LEN("enum('DROP','PRESERVE')")},
-    {NULL, 0}
-  },
-  {
-    {(char *) STRING_WITH_LEN("sql_mode")},
-    {(char *) STRING_WITH_LEN("set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES',"
-    "'IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION',"
-    "'NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB',"
-    "'NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40',"
-    "'ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES',"
-    "'STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES',"
-    "'ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER',"
-    "'HIGH_NOT_PRECEDENCE')")},
-    {NULL, 0}
-  },
-  {
-    {(char *) STRING_WITH_LEN("comment")},
-    {(char *) STRING_WITH_LEN("char(64)")},
-    {(char *) STRING_WITH_LEN("utf8")}
-  }
-};
-
 
 /*
   Compares 2 LEX strings regarding case.
@@ -188,6 +89,14 @@ int sortcmp_lex_string(LEX_STRING s, LEX
 }
 
 
+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:
@@ -207,9 +116,8 @@ int sortcmp_lex_string(LEX_STRING s, LEX
 */
 
 int
-Events::reconstruct_interval_expression(String *buf,
-                                                  interval_type interval,
-                                                  longlong expression)
+Events::reconstruct_interval_expression(String *buf, interval_type interval,
+                                        longlong expression)
 {
   ulonglong expr= expression;
   char tmp_buff[128], *end;
@@ -341,545 +249,7 @@ int
 Events::open_event_table(THD *thd, enum thr_lock_type lock_type,
                                    TABLE **table)
 {
-  TABLE_LIST tables;
-  DBUG_ENTER("open_events_table");
-
-  bzero((char*) &tables, sizeof(tables));
-  tables.db= (char*) "mysql";
-  tables.table_name= tables.alias= (char*) "event";
-  tables.lock_type= lock_type;
-
-  if (simple_open_n_lock_tables(thd, &tables))
-    DBUG_RETURN(1);
-  
-  if (table_check_intact(tables.table, Events::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);
-}
-
-
-/*
-  Find row in open mysql.event table representing event
-
-  SYNOPSIS
-    evex_db_find_event_aux()
-      thd    Thread context
-      et     event_timed object containing dbname & name
-      table  TABLE object for open mysql.event table.
-
-  RETURN VALUE
-    0                  - Routine found
-    EVEX_KEY_NOT_FOUND - No routine with given name
-*/
-
-inline int
-evex_db_find_event_aux(THD *thd, Event_timed *et, TABLE *table)
-{
-  return evex_db_find_event_by_name(thd, et->dbname, et->name, table);
-}
-
-
-/*
-  Find row in open mysql.event table representing event
-
-  SYNOPSIS
-    evex_db_find_event_by_name()
-      thd    Thread context
-      dbname Name of event's database
-      rname  Name of the event inside the db  
-      table  TABLE object for open mysql.event table.
-
-  RETURN VALUE
-    0                  - Routine found
-    EVEX_KEY_NOT_FOUND - No routine with given name
-*/
-
-int
-evex_db_find_event_by_name(THD *thd, const LEX_STRING dbname,
-                          const LEX_STRING ev_name,
-                          TABLE *table)
-{
-  byte key[MAX_KEY_LENGTH];
-  DBUG_ENTER("evex_db_find_event_by_name");
-  DBUG_PRINT("enter", ("name: %.*s", ev_name.length, ev_name.str));
-
-  /*
-    Create key to find row. We have to use field->store() to be able to
-    handle VARCHAR and CHAR fields.
-    Assumption here is that the two first fields in the table are
-    'db' and 'name' and the first key is the primary key over the
-    same fields.
-  */
-  if (dbname.length > table->field[Events::FIELD_DB]->field_length ||
-      ev_name.length > table->field[Events::FIELD_NAME]->field_length)
-      
-    DBUG_RETURN(EVEX_KEY_NOT_FOUND);
-
-  table->field[Events::FIELD_DB]->store(dbname.str, dbname.length,
-                                        &my_charset_bin);
-  table->field[Events::FIELD_NAME]->store(ev_name.str, ev_name.length,
-                                          &my_charset_bin);
-
-  key_copy(key, table->record[0], table->key_info,
-           table->key_info->key_length);
-
-  if (table->file->index_read_idx(table->record[0], 0, key,
-                                 table->key_info->key_length,
-                                  HA_READ_KEY_EXACT))
-  {
-    DBUG_PRINT("info", ("Row not found"));
-    DBUG_RETURN(EVEX_KEY_NOT_FOUND);
-  }
-
-  DBUG_PRINT("info", ("Row found!"));
-  DBUG_RETURN(0);
-}
-
-
-/*
-  Puts some data common to CREATE and ALTER EVENT into a row.
-
-  SYNOPSIS
-    evex_fill_row()
-      thd    THD
-      table  the row to fill out
-      et     Event's data
-
-  RETURN VALUE
-    0 - OK
-    EVEX_GENERAL_ERROR    - bad data
-    EVEX_GET_FIELD_FAILED - field count does not match. table corrupted?
-
-  DESCRIPTION 
-    Used both when an event is created and when it is altered.
-*/
-
-static int
-evex_fill_row(THD *thd, TABLE *table, Event_timed *et, my_bool is_update)
-{
-  CHARSET_INFO *scs= system_charset_info;
-  enum Events::enum_table_field field_num;
-
-  DBUG_ENTER("evex_fill_row");
-
-  DBUG_PRINT("info", ("dbname=[%s]", et->dbname.str));
-  DBUG_PRINT("info", ("name  =[%s]", et->name.str));
-  DBUG_PRINT("info", ("body  =[%s]", et->body.str));
-
-  if (table->field[field_num= Events::FIELD_DEFINER]->
-                  store(et->definer.str, et->definer.length, scs))
-    goto err_truncate;
-
-  if (table->field[field_num= Events::FIELD_DB]->
-                  store(et->dbname.str, et->dbname.length, scs))
-    goto err_truncate;
-
-  if (table->field[field_num= Events::FIELD_NAME]->
-                  store(et->name.str, et->name.length, scs))
-    goto err_truncate;
-
-  /* both ON_COMPLETION and STATUS are NOT NULL thus not calling set_notnull()*/
-  table->field[Events::FIELD_ON_COMPLETION]->
-                                       store((longlong)et->on_completion, true);
-
-  table->field[Events::FIELD_STATUS]->store((longlong)et->status, true);
-
-  /*
-    Change the SQL_MODE only if body was present in an ALTER EVENT and of course
-    always during CREATE EVENT.
-  */ 
-  if (et->body.str)
-  {
-    table->field[Events::FIELD_SQL_MODE]->
-                               store((longlong)thd->variables.sql_mode, true);
-
-    if (table->field[field_num= Events::FIELD_BODY]->
-                     store(et->body.str, et->body.length, scs))
-      goto err_truncate;
-  }
-
-  if (et->expression)
-  {
-    table->field[Events::FIELD_INTERVAL_EXPR]->set_notnull();
-    table->field[Events::FIELD_INTERVAL_EXPR]->
-                                          store((longlong)et->expression, true);
-
-    table->field[Events::FIELD_TRANSIENT_INTERVAL]->set_notnull();
-    /*
-      In the enum (C) intervals start from 0 but in mysql enum valid values start
-      from 1. Thus +1 offset is needed!
-    */
-    table->field[Events::FIELD_TRANSIENT_INTERVAL]->
-                                         store((longlong)et->interval+1, true);
-
-    table->field[Events::FIELD_EXECUTE_AT]->set_null();
-
-    if (!et->starts_null)
-    {
-      table->field[Events::FIELD_STARTS]->set_notnull();
-      table->field[Events::FIELD_STARTS]->
-                            store_time(&et->starts, MYSQL_TIMESTAMP_DATETIME);
-    }	   
-
-    if (!et->ends_null)
-    {
-      table->field[Events::FIELD_ENDS]->set_notnull();
-      table->field[Events::FIELD_ENDS]->
-                            store_time(&et->ends, MYSQL_TIMESTAMP_DATETIME);
-    }
-  }
-  else if (et->execute_at.year)
-  {
-    table->field[Events::FIELD_INTERVAL_EXPR]->set_null();
-    table->field[Events::FIELD_TRANSIENT_INTERVAL]->set_null();
-    table->field[Events::FIELD_STARTS]->set_null();
-    table->field[Events::FIELD_ENDS]->set_null();
-    
-    table->field[Events::FIELD_EXECUTE_AT]->set_notnull();
-    table->field[Events::FIELD_EXECUTE_AT]->
-                        store_time(&et->execute_at, MYSQL_TIMESTAMP_DATETIME);
-  }
-  else
-  {
-    DBUG_ASSERT(is_update);
-    /*
-      it is normal to be here when the action is update
-      this is an error if the action is create. something is borked
-    */
-  }
-    
-  ((Field_timestamp *)table->field[Events::FIELD_MODIFIED])->set_time();
-
-  if (et->comment.str)
-  {
-    if (table->field[field_num= Events::FIELD_COMMENT]->
-                 store(et->comment.str, et->comment.length, scs))
-      goto err_truncate;
-  }
-
-  DBUG_RETURN(0);
-err_truncate:
-  my_error(ER_EVENT_DATA_TOO_LONG, MYF(0), table->field[field_num]->field_name);
-  DBUG_RETURN(EVEX_GENERAL_ERROR);
-}
-
-
-/*
-  Creates an event in mysql.event
-
-  SYNOPSIS
-    db_create_event()
-      thd             THD
-      et              Event_timed object containing information for the event
-      create_if_not   If an warning should be generated in case event exists
-      rows_affected   How many rows were affected
-
-  RETURN VALUE
-                     0 - OK
-    EVEX_GENERAL_ERROR - Failure
-
-  DESCRIPTION 
-    Creates an event. Relies on evex_fill_row which is shared with
-    db_update_event. The name of the event is inside "et".
-*/
-
-int
-db_create_event(THD *thd, Event_timed *et, my_bool create_if_not,
-                uint *rows_affected)
-{
-  int ret= 0;
-  CHARSET_INFO *scs= system_charset_info;
-  TABLE *table;
-  char olddb[128];
-  bool dbchanged= false;
-  DBUG_ENTER("db_create_event");
-  DBUG_PRINT("enter", ("name: %.*s", et->name.length, et->name.str));
-
-  *rows_affected= 0;
-  DBUG_PRINT("info", ("open mysql.event for update"));
-  if (Events::open_event_table(thd, TL_WRITE, &table))
-  {
-    my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
-    goto err;
-  }
-
-  DBUG_PRINT("info", ("check existance of an event with the same name"));
-  if (!evex_db_find_event_aux(thd, et, table))
-  {
-    if (create_if_not)
-    {
-      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
-                          ER_EVENT_ALREADY_EXISTS, ER(ER_EVENT_ALREADY_EXISTS),
-                          et->name.str);
-      goto ok;
-    }
-    my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), et->name.str);
-    goto err;
-  }
-
-  DBUG_PRINT("info", ("non-existant, go forward"));
-  if ((ret= sp_use_new_db(thd, et->dbname.str,olddb, sizeof(olddb),0,
-                          &dbchanged)))
-  {
-    my_error(ER_BAD_DB_ERROR, MYF(0));
-    goto err;
-  }
-
-  restore_record(table, s->default_values);     // Get default values for fields
-
-  if (system_charset_info->cset->numchars(system_charset_info, et->dbname.str,
-                                    et->dbname.str + et->dbname.length)
-                                    > EVEX_DB_FIELD_LEN)
-  {
-    my_error(ER_TOO_LONG_IDENT, MYF(0), et->dbname.str);
-    goto err;
-  }
-  if (system_charset_info->cset->numchars(system_charset_info, et->name.str,
-                                    et->name.str + et->name.length)
-                                    > EVEX_DB_FIELD_LEN)
-  {
-    my_error(ER_TOO_LONG_IDENT, MYF(0), et->name.str);
-    goto err;
-  }
-
-  if (et->body.length > table->field[Events::FIELD_BODY]->field_length)
-  {
-    my_error(ER_TOO_LONG_BODY, MYF(0), et->name.str);
-    goto err;
-  }
-
-  if (!(et->expression) && !(et->execute_at.year))
-  {
-    DBUG_PRINT("error", ("neither expression nor execute_at are set!"));
-    my_error(ER_EVENT_NEITHER_M_EXPR_NOR_M_AT, MYF(0));
-    goto err;
-  }
-
-  ((Field_timestamp *)table->field[Events::FIELD_CREATED])->set_time();
-
-  /*
-    evex_fill_row() calls my_error() in case of error so no need to
-    handle it here
-  */
-  if ((ret= evex_fill_row(thd, table, et, false)))
-    goto err; 
-
-  if (table->file->ha_write_row(table->record[0]))
-  {
-    my_error(ER_EVENT_STORE_FAILED, MYF(0), et->name.str, ret);
-    goto err;
-  }
-
-#ifdef USE_THIS_CODE_AS_TEMPLATE_WHEN_EVENT_REPLICATION_IS_AGREED
-  if (mysql_bin_log.is_open())
-  {
-    thd->clear_error();
-    /* Such a statement can always go directly to binlog, no trans cache */
-    thd->binlog_query(THD::MYSQL_QUERY_TYPE, thd->query, thd->query_length,
-                      FALSE, FALSE);
-  }
-#endif
-
-  *rows_affected= 1;
-ok:
-  if (dbchanged)
-    (void) mysql_change_db(thd, olddb, 1);
-  if (table)
-    close_thread_tables(thd);
-  DBUG_RETURN(EVEX_OK);
-
-err:
-  if (dbchanged)
-    (void) mysql_change_db(thd, olddb, 1);
-  if (table)
-    close_thread_tables(thd);
-  DBUG_RETURN(EVEX_GENERAL_ERROR);
-}
-
-
-/*
-  Used to execute ALTER EVENT. Pendant to Events::update_event().
-
-  SYNOPSIS
-    db_update_event()
-      thd      THD
-      sp_name  the name of the event to alter
-      et       event's data
-
-  RETURN VALUE
-    0  OK
-    EVEX_GENERAL_ERROR  Error occured (my_error() called)
-
-  NOTES
-    sp_name is passed since this is the name of the event to
-    alter in case of RENAME TO.
-*/
-
-static int
-db_update_event(THD *thd, Event_timed *et, sp_name *new_name)
-{
-  CHARSET_INFO *scs= system_charset_info;
-  TABLE *table;
-  int ret= EVEX_OPEN_TABLE_FAILED;
-  DBUG_ENTER("db_update_event");
-  DBUG_PRINT("enter", ("dbname: %.*s", et->dbname.length, et->dbname.str));
-  DBUG_PRINT("enter", ("name: %.*s", et->name.length, et->name.str));
-  DBUG_PRINT("enter", ("user: %.*s", et->definer.length, et->definer.str));
-  if (new_name)
-    DBUG_PRINT("enter", ("rename to: %.*s", new_name->m_name.length,
-                                            new_name->m_name.str));
-
-  if (Events::open_event_table(thd, TL_WRITE, &table))
-  {
-    my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
-    goto err;
-  }
-  
-  /* first look whether we overwrite */
-  if (new_name)
-  {
-    if (!sortcmp_lex_string(et->name, new_name->m_name, scs) &&
-        !sortcmp_lex_string(et->dbname, new_name->m_db, scs))
-    {
-      my_error(ER_EVENT_SAME_NAME, MYF(0), et->name.str);
-      goto err;    
-    }
-  
-    if (!evex_db_find_event_by_name(thd,new_name->m_db,new_name->m_name,table))
-    {
-      my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), new_name->m_name.str);
-      goto err;
-    }  
-  }
-  /*
-    ...and then if there is such an event. Don't exchange the blocks
-    because you will get error 120 from table handler because new_name will
-    overwrite the key and SE will tell us that it cannot find the already found
-    row (copied into record[1] later
-  */
-  if (EVEX_KEY_NOT_FOUND == evex_db_find_event_aux(thd, et, table))
-  {
-    my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), et->name.str);
-    goto err;
-  }
-
-  store_record(table,record[1]);
-
-  /* Don't update create on row update. */
-  table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
-
-  /*
-    evex_fill_row() calls my_error() in case of error so no need to
-    handle it here
-  */
-  if ((ret= evex_fill_row(thd, table, et, true)))
-    goto err;
-
-  if (new_name)
-  {    
-    table->field[Events::FIELD_DB]->
-      store(new_name->m_db.str, new_name->m_db.length, scs);
-    table->field[Events::FIELD_NAME]->
-      store(new_name->m_name.str, new_name->m_name.length, scs);
-  }
-
-  if ((ret= table->file->ha_update_row(table->record[1], table->record[0])))
-  {
-    my_error(ER_EVENT_STORE_FAILED, MYF(0), et->name.str, ret);
-    goto err;
-  }
-
-  /* close mysql.event or we crash later when loading the event from disk */
-  close_thread_tables(thd);
-  DBUG_RETURN(0);
-
-err:
-  if (table)
-    close_thread_tables(thd);
-  DBUG_RETURN(EVEX_GENERAL_ERROR);
-}
-
-
-/*
-  Looks for a named event in mysql.event and in case of success returns
-  an object will data loaded from the table.
-
-  SYNOPSIS
-    db_find_event()
-      thd      THD
-      name     the name of the event to find
-      ett      event's data if event is found
-      tbl      TABLE object to use when not NULL
-
-  NOTES
-    1) Use sp_name for look up, return in **ett if found
-    2) tbl is not closed at exit
-
-  RETURN VALUE
-    0  ok     In this case *ett is set to the event
-    #  error  *ett == 0
-*/
-
-int
-db_find_event(THD *thd, sp_name *name, Event_timed **ett, TABLE *tbl,
-              MEM_ROOT *root)
-{
-  TABLE *table;
-  int ret;
-  Event_timed *et= NULL;
-  DBUG_ENTER("db_find_event");
-  DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
-
-  if (!root)
-    root= &evex_mem_root;
-
-  if (tbl)
-    table= tbl;
-  else if (Events::open_event_table(thd, TL_READ, &table))
-  {
-    my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
-    ret= EVEX_GENERAL_ERROR;
-    goto done;
-  }
-
-  if ((ret= evex_db_find_event_by_name(thd, name->m_db, name->m_name, table)))
-  {
-    my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name->m_name.str);
-    goto done;    
-  }
-  et= new Event_timed;
-  
-  /*
-    1)The table should not be closed beforehand.  ::load_from_row() only loads
-      and does not compile
-
-    2)::load_from_row() is silent on error therefore we emit error msg here
-  */
-  if ((ret= et->load_from_row(root, table)))
-  {
-    my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0));
-    goto done;
-  }
-
-done:
-  if (ret)
-  {
-    delete et;
-    et= 0;
-  }
-  /* don't close the table if we haven't opened it ourselves */
-  if (!tbl && table)
-    close_thread_tables(thd);
-  *ett= et;
-  DBUG_RETURN(ret);
+  return db_repository.open_event_table(thd, lock_type, table);
 }
 
 
@@ -913,9 +283,10 @@ Events::create_event(THD *thd, Event_tim
   DBUG_PRINT("enter", ("name: %*s options:%d", et->name.length,
                 et->name.str, create_options));
 
-  if (!(ret = db_create_event(thd, et,
-                             create_options & HA_LEX_CREATE_IF_NOT_EXISTS,
-                             rows_affected)))
+  if (!(ret= db_repository.
+                 create_event(thd, et,
+                              create_options & HA_LEX_CREATE_IF_NOT_EXISTS,
+                              rows_affected)))
   {
     Event_scheduler *scheduler= Event_scheduler::get_instance();
     if (scheduler->initialized() &&
@@ -960,7 +331,7 @@ Events::update_event(THD *thd, Event_tim
     crash later in the code when loading and compiling the new definition.
     Also on error conditions my_error() is called so no need to handle here
   */
-  if (!(ret= db_update_event(thd, et, new_name)))
+  if (!(ret= db_repository.update_event(thd, et, new_name)))
   {
     Event_scheduler *scheduler= Event_scheduler::get_instance();
     if (scheduler->initialized() &&
@@ -977,67 +348,6 @@ Events::update_event(THD *thd, Event_tim
   Drops an event
 
   SYNOPSIS
-    db_drop_event()
-      thd             THD
-      et              event's name
-      drop_if_exists  if set and the event not existing => warning onto the stack
-      rows_affected   affected number of rows is returned heres
-
-  RETURN VALUE
-    0   OK
-    !0  Error (my_error() called)
-*/
-
-int db_drop_event(THD *thd, LEX_STRING db, LEX_STRING name,
-                  bool drop_if_exists, uint *rows_affected)
-{
-  TABLE *table;
-  Open_tables_state backup;
-  int ret;
-
-  DBUG_ENTER("db_drop_event");
-  DBUG_PRINT("enter", ("db=%s name=%s", db.str, name.str));
-  ret= EVEX_OPEN_TABLE_FAILED;
-
-  thd->reset_n_backup_open_tables_state(&backup);
-  if (Events::open_event_table(thd, TL_WRITE, &table))
-  {
-    my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
-    goto done;
-  }
-
-  if (!(ret= evex_db_find_event_by_name(thd, db, name, table)))
-  {
-    if ((ret= table->file->ha_delete_row(table->record[0])))
-      my_error(ER_EVENT_CANNOT_DELETE, MYF(0));
-  }
-  else if (ret == EVEX_KEY_NOT_FOUND)
-  { 
-    if (drop_if_exists)
-    {
-      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
-                          ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST),
-                          "Event", name.str);
-      ret= 0;
-    } else
-      my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name.str);
-  }
-
-done:
-  /*
-    evex_drop_event() is used by Event_timed::drop therefore
-    we have to close our thread tables.
-  */
-  close_thread_tables(thd);
-  thd->restore_backup_open_tables_state(&backup);
-  DBUG_RETURN(ret);
-}
-
-
-/*
-  Drops an event
-
-  SYNOPSIS
     Events::drop_event()
       thd             THD
       name            event's name
@@ -1056,14 +366,14 @@ Events::drop_event(THD *thd, sp_name *na
   int ret;
 
   DBUG_ENTER("Events::drop_event");
-  if (!(ret= db_drop_event(thd, name->m_db, name->m_name, drop_if_exists,
-                           rows_affected)))
+
+  if (!(ret= db_repository.drop_event(thd, name->m_db, name->m_name,
+                                      drop_if_exists, rows_affected)))
   {
     Event_scheduler *scheduler= Event_scheduler::get_instance();
     if (scheduler->initialized() && (ret= scheduler->drop_event(thd, name)))
       my_error(ER_EVENT_MODIFY_QUEUE_ERROR, MYF(0), ret);
   }
-
   DBUG_RETURN(ret);
 }
 
@@ -1092,7 +402,7 @@ Events::show_create_event(THD *thd, sp_n
   DBUG_PRINT("enter", ("name: %*s", spn->m_name.length, spn->m_name.str));
 
   thd->reset_n_backup_open_tables_state(&backup);
-  ret= db_find_event(thd, spn, &et, NULL, thd->mem_root);
+  ret= db_repository.find_event(thd, spn, &et, NULL, thd->mem_root);
   thd->restore_backup_open_tables_state(&backup);
 
   if (!ret)
@@ -1164,75 +474,13 @@ Events::drop_schema_events(THD *thd, cha
   DBUG_PRINT("enter", ("dropping events from %s", db));
 
   Event_scheduler *scheduler= Event_scheduler::get_instance();
-  if (scheduler->initialized())
-    ret= scheduler->drop_schema_events(thd, &db_lex);
-  else
-    ret= db_drop_events_from_table(thd, &db_lex);
-
-  DBUG_RETURN(ret);
-}
-
-
-/*
-  Drops all events in the selected database, from mysql.event.
-
-  SYNOPSIS
-    evex_drop_db_events_from_table()
-      thd  Thread
-      db   Schema name
-
-  RETURN VALUE
-     0  OK
-    !0  Error from ha_delete_row
-*/
-
-int
-db_drop_events_from_table(THD *thd, LEX_STRING *db)
-{
-  int ret;
-  TABLE *table;
-  READ_RECORD read_record_info;
-  DBUG_ENTER("db_drop_events_from_table");  
-  DBUG_PRINT("info", ("dropping events from %s", db->str));
-
-  if ((ret= Events::open_event_table(thd, TL_WRITE, &table)))
-  {
-    if (my_errno != ENOENT)
-      sql_print_error("Table mysql.event is damaged. Got error %d on open",
-                      my_errno);
-    DBUG_RETURN(ret);
-  }
-  /* only enabled events are in memory, so we go now and delete the rest */
-  init_read_record(&read_record_info, thd, table, NULL, 1, 0);
-  while (!(read_record_info.read_record(&read_record_info)) && !ret)
-  {
-    char *et_db= get_field(thd->mem_root,
-                           table->field[Events::FIELD_DB]);
-
-    LEX_STRING et_db_lex= {et_db, strlen(et_db)};
-    DBUG_PRINT("info", ("Current event %s.%s", et_db,
-               get_field(thd->mem_root,
-               table->field[Events::FIELD_NAME])));
-
-    if (!sortcmp_lex_string(et_db_lex, *db, 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[Events::FIELD_NAME]));
-    }
-  }
-  end_read_record(&read_record_info);
-  thd->version--;   /* Force close to free memory */
-
-  close_thread_tables(thd);
+  ret= scheduler->drop_schema_events(thd, db_lex);
+  ret= db_repository.drop_schema_events(thd, db_lex);
 
   DBUG_RETURN(ret);
 }
 
 
-
 /*
   Inits the scheduler's structures.
 
@@ -1251,14 +499,17 @@ int
 Events::init()
 {
   int ret= 0;
+  Event_db_repository *db_repo;
   DBUG_ENTER("Events::init");
+  db_repo= &get_instance()->db_repository;
+  db_repo->init_repository();
 
   /* it should be an assignment! */
   if (opt_event_scheduler)
   {
     Event_scheduler *scheduler= Event_scheduler::get_instance();
     DBUG_ASSERT(opt_event_scheduler == 1 || opt_event_scheduler == 2);
-    DBUG_RETURN(scheduler->init() || 
+    DBUG_RETURN(scheduler->init(db_repo) || 
                 (opt_event_scheduler == 1? scheduler->start():
                                            scheduler->start_suspended()));
   }
@@ -1270,22 +521,23 @@ Events::init()
   Cleans up scheduler's resources. Called at server shutdown.
 
   SYNOPSIS
-    Events::shutdown()
+    Events::deinit()
 
   NOTES
     This function is not synchronized.
 */
 
 void
-Events::shutdown()
+Events::deinit()
 {
-  DBUG_ENTER("Events::shutdown");
+  DBUG_ENTER("Events::deinit");
   Event_scheduler *scheduler= Event_scheduler::get_instance();
   if (scheduler->initialized())
   {
     scheduler->stop();
     scheduler->destroy();
   }
+  get_instance()->db_repository.deinit_repository();
 
   DBUG_VOID_RETURN;
 }

--- 1.33/sql/events.h	2006-06-27 11:51:01 +02:00
+++ 1.34/sql/events.h	2006-06-28 01:27:52 +02:00
@@ -20,74 +20,91 @@ class sp_name;
 class Event_timed;
 class Event_parse_data;
 
+#include "event_db_repository.h"
+
+/* Return codes */
+enum enum_events_error_code
+{
+  OP_OK= 0,
+  OP_NOT_RUNNING,
+  OP_CANT_KILL,
+  OP_CANT_INIT,
+  OP_DISABLED_EVENT,
+  OP_LOAD_ERROR,
+  OP_ALREADY_EXISTS
+};
+
+int
+sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs);
+
+
 class Events
 {
 public:
+  /*
+    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_timed;
+
   static ulong opt_event_scheduler;
   static TYPELIB opt_typelib;
 
-  enum enum_table_field
-  {
-    FIELD_DB = 0,
-    FIELD_NAME,
-    FIELD_BODY,
-    FIELD_DEFINER,
-    FIELD_EXECUTE_AT,
-    FIELD_INTERVAL_EXPR,
-    FIELD_TRANSIENT_INTERVAL,
-    FIELD_CREATED,
-    FIELD_MODIFIED,
-    FIELD_LAST_EXECUTED,
-    FIELD_STARTS,
-    FIELD_ENDS,
-    FIELD_STATUS,
-    FIELD_ON_COMPLETION,
-    FIELD_SQL_MODE,
-    FIELD_COMMENT,
-    FIELD_COUNT /* a cool trick to count the number of fields :) */
-  };
-
   static int
+  init();
+  
+  static void
+  deinit();
+
+  static void
+  init_mutexes();
+  
+  static void
+  destroy_mutexes();
+
+  static Events*
+  get_instance();
+
+  int
   create_event(THD *thd, Event_timed *et, Event_parse_data *parse_data,
                uint create_options, uint *rows_affected);
 
-  static int
+  int
   update_event(THD *thd, Event_timed *et, Event_parse_data *parse_data,
                sp_name *new_name, uint *rows_affected);
 
-  static int
+  int
   drop_event(THD *thd, sp_name *name, bool drop_if_exists, uint *rows_affected);
 
-  static int
+  int
   open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
 
-  static int
+  int
   show_create_event(THD *thd, sp_name *spn);
 
+  /* Needed for both SHOW CREATE EVENT and INFORMATION_SCHEMA */
   static int
   reconstruct_interval_expression(String *buf, interval_type interval,
                                   longlong expression);
 
-  static int
+  int
   drop_schema_events(THD *thd, char *db);
   
-  static int
+  int
   dump_internal_status(THD *thd);
-  
-  static int
-  init();
-  
-  static void
-  shutdown();
-
-  static void
-  init_mutexes();
-  
-  static void
-  destroy_mutexes();
 
+  Event_db_repository db_repository;
 
 private:
+  /* Singleton DP is used */
+  Events(){}
+  ~Events(){}
+
+  /* Singleton instance */
+  static Events singleton;
+
+
   /* Prevent use of these */
   Events(const Events &);
   void operator=(Events &);

--- 1.1/sql/event_db_repository.cc	2006-06-27 08:48:38 +02:00
+++ 1.2/sql/event_db_repository.cc	2006-06-28 01:27:52 +02:00
@@ -17,3 +17,857 @@
 #include "mysql_priv.h"
 #include "event_db_repository.h"
 #include "event_data_objects.h"
+#include "sp_head.h"
+#include "sp.h"
+#include "events.h"
+
+#define EVEX_DB_FIELD_LEN 64
+#define EVEX_NAME_FIELD_LEN 64
+
+
+time_t mysql_event_last_create_time= 0L;
+
+static
+TABLE_FIELD_W_TYPE event_table_fields[ET_FIELD_COUNT] = {
+  {
+    {(char *) STRING_WITH_LEN("db")},
+    {(char *) STRING_WITH_LEN("char(64)")},
+    {(char *) STRING_WITH_LEN("utf8")}
+  }, 
+  {
+    {(char *) STRING_WITH_LEN("name")},
+    {(char *) STRING_WITH_LEN("char(64)")},
+    {(char *) STRING_WITH_LEN("utf8")}
+  },
+  {
+    {(char *) STRING_WITH_LEN("body")},
+    {(char *) STRING_WITH_LEN("longblob")},
+    {NULL, 0}
+  }, 
+  {
+    {(char *) STRING_WITH_LEN("definer")},
+    {(char *) STRING_WITH_LEN("char(77)")},
+    {(char *) STRING_WITH_LEN("utf8")}
+  },
+  {
+    {(char *) STRING_WITH_LEN("execute_at")},
+    {(char *) STRING_WITH_LEN("datetime")},
+    {NULL, 0}
+  }, 
+  {
+    {(char *) STRING_WITH_LEN("interval_value")},
+    {(char *) STRING_WITH_LEN("int(11)")},
+    {NULL, 0}
+  },
+  {
+    {(char *) STRING_WITH_LEN("interval_field")},
+    {(char *) STRING_WITH_LEN("enum('YEAR','QUARTER','MONTH','DAY',"
+    "'HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR',"
+    "'DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND',"
+    "'DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND',"
+    "'SECOND_MICROSECOND')")},
+    {NULL, 0}
+  }, 
+  {
+    {(char *) STRING_WITH_LEN("created")},
+    {(char *) STRING_WITH_LEN("timestamp")},
+    {NULL, 0}
+  },
+  {
+    {(char *) STRING_WITH_LEN("modified")},
+    {(char *) STRING_WITH_LEN("timestamp")},
+    {NULL, 0}
+  }, 
+  {
+    {(char *) STRING_WITH_LEN("last_executed")},
+    {(char *) STRING_WITH_LEN("datetime")},
+    {NULL, 0}
+  },
+  {
+    {(char *) STRING_WITH_LEN("starts")},
+    {(char *) STRING_WITH_LEN("datetime")},
+    {NULL, 0}
+  }, 
+  {
+    {(char *) STRING_WITH_LEN("ends")},
+    {(char *) STRING_WITH_LEN("datetime")},
+    {NULL, 0}
+  },
+  {
+    {(char *) STRING_WITH_LEN("status")},
+    {(char *) STRING_WITH_LEN("enum('ENABLED','DISABLED')")},
+    {NULL, 0}
+  }, 
+  {
+    {(char *) STRING_WITH_LEN("on_completion")},
+    {(char *) STRING_WITH_LEN("enum('DROP','PRESERVE')")},
+    {NULL, 0}
+  },
+  {
+    {(char *) STRING_WITH_LEN("sql_mode")},
+    {(char *) STRING_WITH_LEN("set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES',"
+    "'IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION',"
+    "'NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB',"
+    "'NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40',"
+    "'ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES',"
+    "'STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES',"
+    "'ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER',"
+    "'HIGH_NOT_PRECEDENCE')")},
+    {NULL, 0}
+  },
+  {
+    {(char *) STRING_WITH_LEN("comment")},
+    {(char *) STRING_WITH_LEN("char(64)")},
+    {(char *) STRING_WITH_LEN("utf8")}
+  }
+};
+
+
+/*
+  Puts some data common to CREATE and ALTER EVENT into a row.
+
+  SYNOPSIS
+    evex_fill_row()
+      thd    THD
+      table  the row to fill out
+      et     Event's data
+
+  RETURN VALUE
+    0 - OK
+    EVEX_GENERAL_ERROR    - bad data
+    EVEX_GET_FIELD_FAILED - field count does not match. table corrupted?
+
+  DESCRIPTION 
+    Used both when an event is created and when it is altered.
+*/
+
+static int
+evex_fill_row(THD *thd, TABLE *table, Event_timed *et, my_bool is_update)
+{
+  CHARSET_INFO *scs= system_charset_info;
+  enum enum_events_table_field field_num;
+
+  DBUG_ENTER("evex_fill_row");
+
+  DBUG_PRINT("info", ("dbname=[%s]", et->dbname.str));
+  DBUG_PRINT("info", ("name  =[%s]", et->name.str));
+  DBUG_PRINT("info", ("body  =[%s]", et->body.str));
+
+  if (table->field[field_num= ET_FIELD_DEFINER]->
+                  store(et->definer.str, et->definer.length, scs))
+    goto err_truncate;
+
+  if (table->field[field_num= ET_FIELD_DB]->
+                  store(et->dbname.str, et->dbname.length, scs))
+    goto err_truncate;
+
+  if (table->field[field_num= ET_FIELD_NAME]->
+                  store(et->name.str, et->name.length, scs))
+    goto err_truncate;
+
+  /* both ON_COMPLETION and STATUS are NOT NULL thus not calling set_notnull()*/
+  table->field[ET_FIELD_ON_COMPLETION]->
+                                       store((longlong)et->on_completion, true);
+
+  table->field[ET_FIELD_STATUS]->store((longlong)et->status, true);
+
+  /*
+    Change the SQL_MODE only if body was present in an ALTER EVENT and of course
+    always during CREATE EVENT.
+  */ 
+  if (et->body.str)
+  {
+    table->field[ET_FIELD_SQL_MODE]->
+                               store((longlong)thd->variables.sql_mode, true);
+
+    if (table->field[field_num= ET_FIELD_BODY]->
+                     store(et->body.str, et->body.length, scs))
+      goto err_truncate;
+  }
+
+  if (et->expression)
+  {
+    table->field[ET_FIELD_INTERVAL_EXPR]->set_notnull();
+    table->field[ET_FIELD_INTERVAL_EXPR]->
+                                          store((longlong)et->expression, true);
+
+    table->field[ET_FIELD_TRANSIENT_INTERVAL]->set_notnull();
+    /*
+      In the enum (C) intervals start from 0 but in mysql enum valid values start
+      from 1. Thus +1 offset is needed!
+    */
+    table->field[ET_FIELD_TRANSIENT_INTERVAL]->
+                                         store((longlong)et->interval+1, true);
+
+    table->field[ET_FIELD_EXECUTE_AT]->set_null();
+
+    if (!et->starts_null)
+    {
+      table->field[ET_FIELD_STARTS]->set_notnull();
+      table->field[ET_FIELD_STARTS]->
+                            store_time(&et->starts, MYSQL_TIMESTAMP_DATETIME);
+    }	   
+
+    if (!et->ends_null)
+    {
+      table->field[ET_FIELD_ENDS]->set_notnull();
+      table->field[ET_FIELD_ENDS]->
+                            store_time(&et->ends, MYSQL_TIMESTAMP_DATETIME);
+    }
+  }
+  else if (et->execute_at.year)
+  {
+    table->field[ET_FIELD_INTERVAL_EXPR]->set_null();
+    table->field[ET_FIELD_TRANSIENT_INTERVAL]->set_null();
+    table->field[ET_FIELD_STARTS]->set_null();
+    table->field[ET_FIELD_ENDS]->set_null();
+    
+    table->field[ET_FIELD_EXECUTE_AT]->set_notnull();
+    table->field[ET_FIELD_EXECUTE_AT]->
+                        store_time(&et->execute_at, MYSQL_TIMESTAMP_DATETIME);
+  }
+  else
+  {
+    DBUG_ASSERT(is_update);
+    /*
+      it is normal to be here when the action is update
+      this is an error if the action is create. something is borked
+    */
+  }
+    
+  ((Field_timestamp *)table->field[ET_FIELD_MODIFIED])->set_time();
+
+  if (et->comment.str)
+  {
+    if (table->field[field_num= ET_FIELD_COMMENT]->
+                 store(et->comment.str, et->comment.length, scs))
+      goto err_truncate;
+  }
+
+  DBUG_RETURN(0);
+err_truncate:
+  my_error(ER_EVENT_DATA_TOO_LONG, MYF(0), table->field[field_num]->field_name);
+  DBUG_RETURN(EVEX_GENERAL_ERROR);
+}
+
+
+/*
+  Find row in open mysql.event table representing event
+
+  SYNOPSIS
+    evex_db_find_event_by_name()
+      thd    Thread context
+      dbname Name of event's database
+      rname  Name of the event inside the db  
+      table  TABLE object for open mysql.event table.
+
+  RETURN VALUE
+    0                  - Routine found
+    EVEX_KEY_NOT_FOUND - No routine with given name
+*/
+
+int
+evex_db_find_event_by_name(THD *thd, const LEX_STRING dbname,
+                          const LEX_STRING ev_name,
+                          TABLE *table)
+{
+  return Events::get_instance()->db_repository.
+            find_event_by_name(thd, dbname, ev_name, table);
+}
+
+
+/*
+  Looks for a named event in mysql.event and in case of success returns
+  an object will data loaded from the table.
+
+  SYNOPSIS
+    db_find_event()
+      thd      THD
+      name     the name of the event to find
+      ett      event's data if event is found
+      tbl      TABLE object to use when not NULL
+
+  NOTES
+    1) Use sp_name for look up, return in **ett if found
+    2) tbl is not closed at exit
+
+  RETURN VALUE
+    0  ok     In this case *ett is set to the event
+    #  error  *ett == 0
+*/
+
+int
+Event_db_repository::find_event(THD *thd, sp_name *name, Event_timed **ett,
+                                TABLE *tbl, MEM_ROOT *root)
+{
+  TABLE *table;
+  int ret;
+  Event_timed *et= NULL;
+  DBUG_ENTER("db_find_event");
+  DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
+
+  if (tbl)
+    table= tbl;
+  else if (Events::get_instance()->db_repository.open_event_table(thd, TL_READ, &table))
+  {
+    my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
+    ret= EVEX_GENERAL_ERROR;
+    goto done;
+  }
+
+  if ((ret= evex_db_find_event_by_name(thd, name->m_db, name->m_name, table)))
+  {
+    my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name->m_name.str);
+    goto done;    
+  }
+  et= new Event_timed;
+  
+  /*
+    1)The table should not be closed beforehand.  ::load_from_row() only loads
+      and does not compile
+
+    2)::load_from_row() is silent on error therefore we emit error msg here
+  */
+  if ((ret= et->load_from_row(root, table)))
+  {
+    my_error(ER_CANNOT_LOAD_FROM_TABLE, MYF(0));
+    goto done;
+  }
+
+done:
+  if (ret)
+  {
+    delete et;
+    et= 0;
+  }
+  /* don't close the table if we haven't opened it ourselves */
+  if (!tbl && table)
+    close_thread_tables(thd);
+  *ett= et;
+  DBUG_RETURN(ret);
+}
+
+
+int
+Event_db_repository::init_repository()
+{
+  init_alloc_root(&repo_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
+  return 0;
+}
+
+
+void
+Event_db_repository::deinit_repository()
+{
+  free_root(&repo_root, MYF(0));
+}
+
+
+/*
+  Open mysql.event table for read
+
+  SYNOPSIS
+    Events::open_event_table()
+    thd         Thread context
+    lock_type   How to lock the table
+    table       We will store the open table here
+
+  RETURN VALUE
+    1   Cannot lock table
+    2   The table is corrupted - different number of fields
+    0   OK
+*/
+
+int
+Event_db_repository::open_event_table(THD *thd, enum thr_lock_type lock_type,
+                                      TABLE **table)
+{
+  TABLE_LIST tables;
+  DBUG_ENTER("Event_db_repository::open_event_table");
+
+  bzero((char*) &tables, sizeof(tables));
+  tables.db= (char*) "mysql";
+  tables.table_name= tables.alias= (char*) "event";
+  tables.lock_type= lock_type;
+
+  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);
+}
+
+
+/*
+  Creates an event in mysql.event
+
+  SYNOPSIS
+    Event_db_repository::create_event()
+      thd             THD
+      et              Event_timed object containing information for the event
+      create_if_not   If an warning should be generated in case event exists
+      rows_affected   How many rows were affected
+
+  RETURN VALUE
+                     0 - OK
+    EVEX_GENERAL_ERROR - Failure
+
+  DESCRIPTION 
+    Creates an event. Relies on evex_fill_row which is shared with
+    db_update_event. The name of the event is inside "et".
+*/
+
+int
+Event_db_repository::create_event(THD *thd, Event_timed *et,
+                                  my_bool create_if_not, uint *rows_affected)
+{
+  int ret= 0;
+  CHARSET_INFO *scs= system_charset_info;
+  TABLE *table;
+  char olddb[128];
+  bool dbchanged= false;
+  DBUG_ENTER("Event_db_repository::create_event");
+  DBUG_PRINT("enter", ("name: %.*s", et->name.length, et->name.str));
+
+  *rows_affected= 0;
+  DBUG_PRINT("info", ("open mysql.event for update"));
+  if (open_event_table(thd, TL_WRITE, &table))
+  {
+    my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
+    goto err;
+  }
+
+  DBUG_PRINT("info", ("check existance of an event with the same name"));
+  if (!evex_db_find_event_by_name(thd, et->dbname, et->name, table))
+  {
+    if (create_if_not)
+    {
+      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+                          ER_EVENT_ALREADY_EXISTS, ER(ER_EVENT_ALREADY_EXISTS),
+                          et->name.str);
+      goto ok;
+    }
+    my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), et->name.str);
+    goto err;
+  }
+
+  DBUG_PRINT("info", ("non-existant, go forward"));
+  if ((ret= sp_use_new_db(thd, et->dbname.str,olddb, sizeof(olddb),0,
+                          &dbchanged)))
+  {
+    my_error(ER_BAD_DB_ERROR, MYF(0));
+    goto err;
+  }
+
+  restore_record(table, s->default_values);     // Get default values for fields
+
+  if (system_charset_info->cset->numchars(system_charset_info, et->dbname.str,
+                                    et->dbname.str + et->dbname.length)
+                                    > EVEX_DB_FIELD_LEN)
+  {
+    my_error(ER_TOO_LONG_IDENT, MYF(0), et->dbname.str);
+    goto err;
+  }
+  if (system_charset_info->cset->numchars(system_charset_info, et->name.str,
+                                    et->name.str + et->name.length)
+                                    > EVEX_DB_FIELD_LEN)
+  {
+    my_error(ER_TOO_LONG_IDENT, MYF(0), et->name.str);
+    goto err;
+  }
+
+  if (et->body.length > table->field[ET_FIELD_BODY]->field_length)
+  {
+    my_error(ER_TOO_LONG_BODY, MYF(0), et->name.str);
+    goto err;
+  }
+
+  if (!(et->expression) && !(et->execute_at.year))
+  {
+    DBUG_PRINT("error", ("neither expression nor execute_at are set!"));
+    my_error(ER_EVENT_NEITHER_M_EXPR_NOR_M_AT, MYF(0));
+    goto err;
+  }
+
+  ((Field_timestamp *)table->field[ET_FIELD_CREATED])->set_time();
+
+  /*
+    evex_fill_row() calls my_error() in case of error so no need to
+    handle it here
+  */
+  if ((ret= evex_fill_row(thd, table, et, false)))
+    goto err; 
+
+  if (table->file->ha_write_row(table->record[0]))
+  {
+    my_error(ER_EVENT_STORE_FAILED, MYF(0), et->name.str, ret);
+    goto err;
+  }
+
+#ifdef USE_THIS_CODE_AS_TEMPLATE_WHEN_EVENT_REPLICATION_IS_AGREED
+  if (mysql_bin_log.is_open())
+  {
+    thd->clear_error();
+    /* Such a statement can always go directly to binlog, no trans cache */
+    thd->binlog_query(THD::MYSQL_QUERY_TYPE, thd->query, thd->query_length,
+                      FALSE, FALSE);
+  }
+#endif
+
+  *rows_affected= 1;
+ok:
+  if (dbchanged)
+    (void) mysql_change_db(thd, olddb, 1);
+  if (table)
+    close_thread_tables(thd);
+  DBUG_RETURN(EVEX_OK);
+
+err:
+  if (dbchanged)
+    (void) mysql_change_db(thd, olddb, 1);
+  if (table)
+    close_thread_tables(thd);
+  DBUG_RETURN(EVEX_GENERAL_ERROR);
+}
+
+
+/*
+  Used to execute ALTER EVENT. Pendant to Events::update_event().
+
+  SYNOPSIS
+    Event_db_repository::update_event()
+      thd      THD
+      sp_name  the name of the event to alter
+      et       event's data
+
+  RETURN VALUE
+    0  OK
+    EVEX_GENERAL_ERROR  Error occured (my_error() called)
+
+  NOTES
+    sp_name is passed since this is the name of the event to
+    alter in case of RENAME TO.
+*/
+
+int
+Event_db_repository::update_event(THD *thd, Event_timed *et, sp_name *new_name)
+{
+  CHARSET_INFO *scs= system_charset_info;
+  TABLE *table;
+  int ret= EVEX_OPEN_TABLE_FAILED;
+  DBUG_ENTER("Event_db_repository::update_event");
+  DBUG_PRINT("enter", ("dbname: %.*s", et->dbname.length, et->dbname.str));
+  DBUG_PRINT("enter", ("name: %.*s", et->name.length, et->name.str));
+  DBUG_PRINT("enter", ("user: %.*s", et->definer.length, et->definer.str));
+  if (new_name)
+    DBUG_PRINT("enter", ("rename to: %.*s", new_name->m_name.length,
+                                            new_name->m_name.str));
+
+  if (open_event_table(thd, TL_WRITE, &table))
+  {
+    my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
+    goto err;
+  }
+  
+  /* first look whether we overwrite */
+  if (new_name)
+  {
+    if (!sortcmp_lex_string(et->name, new_name->m_name, scs) &&
+        !sortcmp_lex_string(et->dbname, new_name->m_db, scs))
+    {
+      my_error(ER_EVENT_SAME_NAME, MYF(0), et->name.str);
+      goto err;    
+    }
+  
+    if (!evex_db_find_event_by_name(thd,new_name->m_db,new_name->m_name,table))
+    {
+      my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), new_name->m_name.str);
+      goto err;
+    }  
+  }
+  /*
+    ...and then if there is such an event. Don't exchange the blocks
+    because you will get error 120 from table handler because new_name will
+    overwrite the key and SE will tell us that it cannot find the already found
+    row (copied into record[1] later
+  */
+  if (EVEX_KEY_NOT_FOUND == find_event_by_name(thd, et->dbname, et->name, table))
+  {
+    my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), et->name.str);
+    goto err;
+  }
+
+  store_record(table,record[1]);
+
+  /* Don't update create on row update. */
+  table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
+
+  /*
+    evex_fill_row() calls my_error() in case of error so no need to
+    handle it here
+  */
+  if ((ret= evex_fill_row(thd, table, et, true)))
+    goto err;
+
+  if (new_name)
+  {    
+    table->field[ET_FIELD_DB]->
+      store(new_name->m_db.str, new_name->m_db.length, scs);
+    table->field[ET_FIELD_NAME]->
+      store(new_name->m_name.str, new_name->m_name.length, scs);
+  }
+
+  if ((ret= table->file->ha_update_row(table->record[1], table->record[0])))
+  {
+    my_error(ER_EVENT_STORE_FAILED, MYF(0), et->name.str, ret);
+    goto err;
+  }
+
+  /* close mysql.event or we crash later when loading the event from disk */
+  close_thread_tables(thd);
+  DBUG_RETURN(0);
+
+err:
+  if (table)
+    close_thread_tables(thd);
+  DBUG_RETURN(EVEX_GENERAL_ERROR);
+}
+
+
+/*
+  Drops an event
+
+  SYNOPSIS
+    Event_db_repository::drop_event()
+      thd             THD
+      db              database name
+      name            event's name
+      drop_if_exists  if set and the event not existing => warning onto the stack
+      rows_affected   affected number of rows is returned heres
+
+  RETURN VALUE
+    0   OK
+    !0  Error (my_error() called)
+*/
+
+int
+Event_db_repository::drop_event(THD *thd, LEX_STRING db, LEX_STRING name,
+                                bool drop_if_exists, uint *rows_affected)
+{
+  TABLE *table;
+  Open_tables_state backup;
+  int ret;
+
+  DBUG_ENTER("Event_db_repository::drop_event");
+  DBUG_PRINT("enter", ("db=%s name=%s", db.str, name.str));
+  ret= EVEX_OPEN_TABLE_FAILED;
+
+  thd->reset_n_backup_open_tables_state(&backup);
+  if (open_event_table(thd, TL_WRITE, &table))
+  {
+    my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
+    goto done;
+  }
+
+  if (!(ret= evex_db_find_event_by_name(thd, db, name, table)))
+  {
+    if ((ret= table->file->ha_delete_row(table->record[0])))
+      my_error(ER_EVENT_CANNOT_DELETE, MYF(0));
+  }
+  else if (ret == EVEX_KEY_NOT_FOUND)
+  { 
+    if (drop_if_exists)
+    {
+      push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
+                          ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST),
+                          "Event", name.str);
+      ret= 0;
+    } else
+      my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name.str);
+  }
+
+done:
+  /*
+    evex_drop_event() is used by Event_timed::drop therefore
+    we have to close our thread tables.
+  */
+  close_thread_tables(thd);
+  thd->restore_backup_open_tables_state(&backup);
+  DBUG_RETURN(ret);
+}
+
+
+int
+Event_db_repository::find_event_by_name(THD *thd, LEX_STRING db,
+                                        LEX_STRING name, TABLE *table)
+{
+  byte key[MAX_KEY_LENGTH];
+  DBUG_ENTER("Event_db_repository::find_event_by_name");
+  DBUG_PRINT("enter", ("name: %.*s", name.length, name.str));
+
+  /*
+    Create key to find row. We have to use field->store() to be able to
+    handle VARCHAR and CHAR fields.
+    Assumption here is that the two first fields in the table are
+    'db' and 'name' and the first key is the primary key over the
+    same fields.
+  */
+  if (db.length > table->field[ET_FIELD_DB]->field_length ||
+      name.length > table->field[ET_FIELD_NAME]->field_length)
+      
+    DBUG_RETURN(EVEX_KEY_NOT_FOUND);
+
+  table->field[ET_FIELD_DB]->store(db.str, db.length, &my_charset_bin);
+  table->field[ET_FIELD_NAME]->store(name.str, name.length, &my_charset_bin);
+
+  key_copy(key, table->record[0], table->key_info,
+           table->key_info->key_length);
+
+  if (table->file->index_read_idx(table->record[0], 0, key,
+                                  table->key_info->key_length,
+                                  HA_READ_KEY_EXACT))
+  {
+    DBUG_PRINT("info", ("Row not found"));
+    DBUG_RETURN(EVEX_KEY_NOT_FOUND);
+  }
+
+  DBUG_PRINT("info", ("Row found!"));
+  DBUG_RETURN(0);
+}
+
+
+int
+Event_db_repository::drop_schema_events(THD *thd, LEX_STRING schema)
+{
+  return drop_events_by_field(thd, ET_FIELD_DB, schema);
+}
+
+
+int
+Event_db_repository::drop_user_events(THD *thd, LEX_STRING definer)
+{
+  return drop_events_by_field(thd, ET_FIELD_DEFINER, definer);
+}
+
+
+/*
+  Drops all events in the selected database, from mysql.event.
+
+  SYNOPSIS
+    drop_events_from_table_by_field()
+      thd         Thread
+      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
+Event_db_repository::drop_events_by_field(THD *thd,  
+                                          enum enum_events_table_field field,
+                                          LEX_STRING field_value)
+{
+  int ret= 0;
+  TABLE *table;
+  Open_tables_state backup;
+  READ_RECORD read_record_info;
+  DBUG_ENTER("drop_events_from_table_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);
+  }
+
+  /* only enabled events are in memory, so we go now and delete the rest */
+  init_read_record(&read_record_info, thd, table, NULL, 1, 0);
+  while (!ret && !(read_record_info.read_record(&read_record_info)) )
+  {
+    char *et_field= get_field(thd->mem_root, table->field[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]));
+    }
+  }
+  end_read_record(&read_record_info);
+  thd->version--;   /* Force close to free memory */
+
+  DBUG_RETURN(ret);
+}
+
+
+/*
+  Looks for a named event in mysql.event and then loads it from
+  the table, compiles and inserts it into the cache.
+
+  SYNOPSIS
+    Event_scheduler::load_named_event()
+      thd      THD
+      etn      The name of the event to load and compile on scheduler's root
+      etn_new  The loaded event
+
+  RETURN VALUE
+    NULL       Error during compile or the event is non-enabled.
+    otherwise  Address
+*/
+
+int
+Event_db_repository::load_named_event(THD *thd, Event_timed *etn,
+                                      Event_timed **etn_new)
+{
+  int ret= 0;
+  MEM_ROOT *tmp_mem_root;
+  Event_timed *et_loaded= NULL;
+  Open_tables_state backup;
+
+  DBUG_ENTER("Event_scheduler::load_and_compile_event");
+  DBUG_PRINT("enter",("thd=%p name:%*s",thd, etn->name.length, etn->name.str));
+
+  thd->reset_n_backup_open_tables_state(&backup);
+  /* No need to use my_error() here because db_find_event() has done it */
+  {
+    sp_name spn(etn->dbname, etn->name);
+    ret= find_event(thd, &spn, &et_loaded, NULL, &repo_root);
+  }
+  thd->restore_backup_open_tables_state(&backup);
+  /* In this case no memory was allocated so we don't need to clean */
+  if (ret)
+    DBUG_RETURN(OP_LOAD_ERROR);
+
+  if (et_loaded->status != Event_timed::ENABLED)
+  {
+    /*
+      We don't load non-enabled events.
+      In db_find_event() `et_new` was allocated on the heap and not on
+      scheduler_root therefore we delete it here.
+    */
+    delete et_loaded;
+    DBUG_RETURN(OP_DISABLED_EVENT);
+  }
+
+  et_loaded->compute_next_execution_time();
+  *etn_new= et_loaded;
+
+  DBUG_RETURN(OP_OK);
+}

--- 1.1/sql/event_db_repository.h	2006-06-27 08:48:39 +02:00
+++ 1.2/sql/event_db_repository.h	2006-06-28 01:27:52 +02:00
@@ -16,5 +16,87 @@
    along with this program; if not, write to the Free Software
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
+enum enum_events_table_field
+{
+  ET_FIELD_DB = 0,
+  ET_FIELD_NAME,
+  ET_FIELD_BODY,
+  ET_FIELD_DEFINER,
+  ET_FIELD_EXECUTE_AT,
+  ET_FIELD_INTERVAL_EXPR,
+  ET_FIELD_TRANSIENT_INTERVAL,
+  ET_FIELD_CREATED,
+  ET_FIELD_MODIFIED,
+  ET_FIELD_LAST_EXECUTED,
+  ET_FIELD_STARTS,
+  ET_FIELD_ENDS,
+  ET_FIELD_STATUS,
+  ET_FIELD_ON_COMPLETION,
+  ET_FIELD_SQL_MODE,
+  ET_FIELD_COMMENT,
+  ET_FIELD_COUNT /* a cool trick to count the number of fields :) */
+};
+
+
+int
+evex_db_find_event_by_name(THD *thd, const LEX_STRING dbname,
+                           const LEX_STRING ev_name,
+                           TABLE *table);
+
+class Event_queue_element;
+
+class Event_db_repository
+{
+public:
+  Event_db_repository(){}
+  ~Event_db_repository(){}
+
+  int
+  init_repository();
+
+  void
+  deinit_repository();
+
+  int
+  open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
+
+  int
+  create_event(THD *thd, Event_timed *et, my_bool create_if_not,
+              uint *rows_affected);
+
+  int
+  update_event(THD *thd, Event_timed *et, sp_name *new_name);
+
+  int 
+  drop_event(THD *thd, LEX_STRING db, LEX_STRING name, bool drop_if_exists,
+             uint *rows_affected);
+
+  int
+  drop_schema_events(THD *thd, LEX_STRING schema);
+
+  int
+  drop_user_events(THD *thd, LEX_STRING definer);
+
+  int
+  find_event(THD *thd, sp_name *name, Event_timed **ett, TABLE *tbl,
+             MEM_ROOT *root);
+
+  int
+  load_named_event(THD *thd, Event_timed *etn, Event_timed **etn_new);
+
+  int
+  find_event_by_name(THD *thd, LEX_STRING db, LEX_STRING name, TABLE *table);
+private:
+
+  int
+  drop_events_by_field(THD *thd, enum enum_events_table_field field,
+                       LEX_STRING field_value);
+
+  MEM_ROOT repo_root;
+
+  /* Prevent use of these */
+  Event_db_repository(const Event_db_repository &);
+  void operator=(Event_db_repository &);
+};
  
 #endif /* _EVENT_DB_REPOSITORY_H_ */

--- 1.9/sql/event_scheduler.cc	2006-06-27 11:51:00 +02:00
+++ 1.10/sql/event_scheduler.cc	2006-06-28 01:27:52 +02:00
@@ -15,10 +15,10 @@
    Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
 #include "mysql_priv.h"
-#include "events_priv.h"
 #include "events.h"
 #include "event_data_objects.h"
 #include "event_scheduler.h"
+#include "event_db_repository.h"
 #include "sp_head.h"
 
 /*
@@ -574,8 +574,8 @@ event_worker_thread(void *arg)
     to change the context before sending the signal. We are under
     LOCK_scheduler_data being held by Event_scheduler::run() -> ::execute_top().
   */
-  change_security_context(thd, event->definer_user, event->definer_host,
-                          event->dbname, &security_ctx, &save_ctx);
+  thd->change_security_context(event->definer_user, event->definer_host,
+                               event->dbname, &security_ctx, &save_ctx);
   DBUG_PRINT("info", ("master_access=%d db_access=%d",
              thd->security_ctx->master_access, thd->security_ctx->db_access));
 
@@ -687,7 +687,7 @@ Event_scheduler::get_instance()
 */
 
 bool
-Event_scheduler::init()
+Event_scheduler::init(Event_db_repository *db_repo)
 {
   int i= 0;
   bool ret= FALSE;
@@ -695,6 +695,7 @@ Event_scheduler::init()
   DBUG_PRINT("enter", ("this=%p", this));
 
   LOCK_SCHEDULER_DATA();
+  db_repository= db_repo;
   for (;i < COND_LAST; i++)
     if (pthread_cond_init(&cond_vars[i], NULL))
     {
@@ -783,10 +784,10 @@ Event_scheduler::destroy()
     OP_LOAD_ERROR     Error during loading from disk
 */
 
-enum Event_scheduler::enum_error_code
+int
 Event_scheduler::create_event(THD *thd, Event_timed *et, bool check_existence)
 {
-  enum enum_error_code res;
+  int res;
   Event_timed *et_new;
   DBUG_ENTER("Event_scheduler::create_event");
   DBUG_PRINT("enter", ("thd=%p et=%p lock=%p",thd,et,&LOCK_scheduler_data));
@@ -805,7 +806,7 @@ Event_scheduler::create_event(THD *thd, 
   }
 
   /* We need to load the event on scheduler_root */
-  if (!(res= load_named_event(thd, et, &et_new)))
+  if (!(res= db_repository->load_named_event(thd, et, &et_new)))
   {
     queue_insert_safe(&queue, (byte *) et_new);
     DBUG_PRINT("info", ("Sending COND_new_work"));
@@ -904,12 +905,12 @@ Event_scheduler::drop_event(THD *thd, sp
     OP_ALREADY_EXISTS Event already in the queue    
 */
 
-enum Event_scheduler::enum_error_code
+int
 Event_scheduler::update_event(THD *thd, Event_timed *et,
                                LEX_STRING *new_schema,
                                LEX_STRING *new_name)
 {
-  enum enum_error_code res;
+  int res= OP_OK;
   Event_timed *et_old, *et_new= NULL;
   LEX_STRING old_schema, old_name;
 
@@ -947,7 +948,7 @@ Event_scheduler::update_event(THD *thd, 
     1. Error occured
     2. If the replace is DISABLED, we don't load it into the queue.
   */
-  if (!(res= load_named_event(thd, et, &et_new)))
+  if (!(res= db_repository->load_named_event(thd, et, &et_new)))
   {
     queue_insert_safe(&queue, (byte *) et_new);
     DBUG_PRINT("info", ("Sending COND_new_work"));
@@ -961,7 +962,7 @@ Event_scheduler::update_event(THD *thd, 
     et->dbname= old_schema;
     et->name= old_name;
   }
-
+  DBUG_PRINT("info", ("res=%d", res));
   UNLOCK_SCHEDULER_DATA();
   /*
     Andrey: Is this comment still truthful ???
@@ -1111,11 +1112,11 @@ Event_scheduler::find_event(sp_name *nam
 */
 
 void
-Event_scheduler::drop_matching_events(THD *thd, LEX_STRING *pattern,
+Event_scheduler::drop_matching_events(THD *thd, LEX_STRING pattern,
                            bool (*comparator)(Event_timed *,LEX_STRING *))
 {
   DBUG_ENTER("Event_scheduler::drop_matching_events");
-  DBUG_PRINT("enter", ("pattern=%*s state=%d", pattern->length, pattern->str,
+  DBUG_PRINT("enter", ("pattern=%*s state=%d", pattern.length, pattern.str,
              state));
   if (is_running_or_suspended())
   {
@@ -1124,7 +1125,7 @@ Event_scheduler::drop_matching_events(TH
     {
       Event_timed *et= (Event_timed *) queue_element(&queue, i);
       DBUG_PRINT("info", ("[%s.%s]?", et->dbname.str, et->name.str));
-      if (comparator(et, pattern))
+      if (comparator(et, &pattern))
       {
         /*
           The queue is ordered. If we remove an element, then all elements after
@@ -1179,7 +1180,7 @@ Event_scheduler::drop_matching_events(TH
 */
 
 int
-Event_scheduler::drop_schema_events(THD *thd, LEX_STRING *schema)
+Event_scheduler::drop_schema_events(THD *thd, LEX_STRING schema)
 {
   int ret;
   DBUG_ENTER("Event_scheduler::drop_schema_events");
@@ -1187,7 +1188,6 @@ Event_scheduler::drop_schema_events(THD 
   if (is_running_or_suspended())
     drop_matching_events(thd, schema, event_timed_db_equal);
 
-  ret= db_drop_events_from_table(thd, schema);
   UNLOCK_SCHEDULER_DATA();
 
   DBUG_RETURN(ret);
@@ -1713,7 +1713,7 @@ Event_scheduler::stop_all_running_events
     The caller must have acquited LOCK_scheduler_data.
 */
 
-enum Event_scheduler::enum_error_code
+int
 Event_scheduler::stop()
 {
   THD *thd= current_thd;
@@ -1778,7 +1778,7 @@ Event_scheduler::stop()
     OP_OK  OK
 */
 
-enum Event_scheduler::enum_error_code
+int
 Event_scheduler::suspend_or_resume(
               enum Event_scheduler::enum_suspend_or_resume action)
 {
@@ -2116,59 +2116,6 @@ Event_scheduler::events_count()
 }
 
 
-/*
-  Looks for a named event in mysql.event and then loads it from
-  the table, compiles and inserts it into the cache.
-
-  SYNOPSIS
-    Event_scheduler::load_named_event()
-      thd      THD
-      etn      The name of the event to load and compile on scheduler's root
-      etn_new  The loaded event
-
-  RETURN VALUE
-    NULL       Error during compile or the event is non-enabled.
-    otherwise  Address
-*/
-
-enum Event_scheduler::enum_error_code
-Event_scheduler::load_named_event(THD *thd, Event_timed *etn, Event_timed **etn_new)
-{
-  int ret= 0;
-  MEM_ROOT *tmp_mem_root;
-  Event_timed *et_loaded= NULL;
-  Open_tables_state backup;
-
-  DBUG_ENTER("Event_scheduler::load_and_compile_event");
-  DBUG_PRINT("enter",("thd=%p name:%*s",thd, etn->name.length, etn->name.str));
-
-  thd->reset_n_backup_open_tables_state(&backup);
-  /* No need to use my_error() here because db_find_event() has done it */
-  {
-    sp_name spn(etn->dbname, etn->name);
-    ret= db_find_event(thd, &spn, &et_loaded, NULL, &scheduler_root);
-  }
-  thd->restore_backup_open_tables_state(&backup);
-  /* In this case no memory was allocated so we don't need to clean */
-  if (ret)
-    DBUG_RETURN(OP_LOAD_ERROR);
-
-  if (et_loaded->status != Event_timed::ENABLED)
-  {
-    /*
-      We don't load non-enabled events.
-      In db_find_event() `et_new` was allocated on the heap and not on
-      scheduler_root therefore we delete it here.
-    */
-    delete et_loaded;
-    DBUG_RETURN(OP_DISABLED_EVENT);
-  }
-
-  et_loaded->compute_next_execution_time();
-  *etn_new= et_loaded;
-
-  DBUG_RETURN(OP_OK);
-}
 
 
 /*
@@ -2212,7 +2159,7 @@ Event_scheduler::load_events_from_db(THD
     DBUG_RETURN(EVEX_GENERAL_ERROR);
   }
 
-  if ((ret= Events::open_event_table(thd, TL_READ, &table)))
+  if ((ret= Events::get_instance()->open_event_table(thd, TL_READ, &table)))
   {
     sql_print_error("SCHEDULER: Table mysql.event is damaged. Can not open.");
     DBUG_RETURN(EVEX_OPEN_TABLE_FAILED);

--- 1.6/sql/event_scheduler.h	2006-06-27 11:51:00 +02:00
+++ 1.7/sql/event_scheduler.h	2006-06-28 01:27:52 +02:00
@@ -18,6 +18,7 @@
 
 class sp_name;
 class Event_timed;
+class Event_db_repository;
 
 class THD;
 typedef bool * (*event_timed_identifier_comparator)(Event_timed*, Event_timed*);
@@ -31,17 +32,6 @@ events_shutdown();
 class Event_scheduler
 {
 public:
-  /* Return codes */
-  enum enum_error_code
-  {
-    OP_OK= 0,
-    OP_NOT_RUNNING,
-    OP_CANT_KILL,
-    OP_CANT_INIT,
-    OP_DISABLED_EVENT,
-    OP_LOAD_ERROR,
-    OP_ALREADY_EXISTS
-  };
 
   enum enum_state
   {
@@ -66,10 +56,10 @@ public:
 
   /* Methods for queue management follow */
 
-  enum enum_error_code
+  int
   create_event(THD *thd, Event_timed *et, bool check_existence);
 
-  enum enum_error_code
+  int
   update_event(THD *thd, Event_timed *et, LEX_STRING *new_schema,
                 LEX_STRING *new_name);
 
@@ -78,10 +68,10 @@ public:
 
 
   int
-  drop_schema_events(THD *thd, LEX_STRING *schema);
+  drop_schema_events(THD *thd, LEX_STRING schema);
 
   int
-  drop_user_events(THD *thd, LEX_STRING *definer, uint *dropped_num)
+  drop_user_events(THD *thd, LEX_STRING *definer)
   { DBUG_ASSERT(0); return 0;}
 
   uint
@@ -92,20 +82,24 @@ public:
   bool
   start();
 
-  enum enum_error_code
+  int
   stop();
 
   bool
   start_suspended();
 
+  /*
+    Need to be public because has to be called from the function 
+    passed to pthread_create.
+  */
   bool
   run(THD *thd);
 
-  enum enum_error_code
+  int
   suspend_or_resume(enum enum_suspend_or_resume action);
   
   bool 
-  init();
+  init(Event_db_repository *db_repo);
 
   void
   destroy();
@@ -156,14 +150,11 @@ private:
   void
   stop_all_running_events(THD *thd);
 
-  enum enum_error_code
-  load_named_event(THD *thd, Event_timed *etn, Event_timed **etn_new);
-
   int
   load_events_from_db(THD *thd);
 
   void
-  drop_matching_events(THD *thd, LEX_STRING *pattern,
+  drop_matching_events(THD *thd, LEX_STRING pattern,
                        bool (*)(Event_timed *,LEX_STRING *));
 
   bool
@@ -229,6 +220,8 @@ private:
 
   /* The MEM_ROOT of the object */
   MEM_ROOT scheduler_root;
+
+  Event_db_repository *db_repository;
 
   /* The sorted queue with the Event_timed objects */
   QUEUE queue;

--- 1.60/sql/event_data_objects.cc	2006-06-27 11:51:00 +02:00
+++ 1.61/sql/event_data_objects.cc	2006-06-28 01:27:52 +02:00
@@ -16,12 +16,15 @@
 
 #define MYSQL_LEX 1
 #include "mysql_priv.h"
-#include "events_priv.h"
 #include "events.h"
 #include "event_data_objects.h"
+#include "event_db_repository.h"
 #include "sp_head.h"
 
 
+#define EVEX_MAX_INTERVAL_VALUE 2147483647L
+
+
 Event_parse_data *
 Event_parse_data::new_instance(THD *thd)
 {
@@ -733,29 +736,29 @@ Event_timed::load_from_row(MEM_ROOT *mem
 
   et= this;
 
-  if (table->s->fields != Events::FIELD_COUNT)
+  if (table->s->fields != ET_FIELD_COUNT)
     goto error;
 
   if ((et->dbname.str= get_field(mem_root,
-                                 table->field[Events::FIELD_DB])) == NULL)
+                                 table->field[ET_FIELD_DB])) == NULL)
     goto error;
 
   et->dbname.length= strlen(et->dbname.str);
 
   if ((et->name.str= get_field(mem_root,
-                               table->field[Events::FIELD_NAME])) == NULL)
+                               table->field[ET_FIELD_NAME])) == NULL)
     goto error;
 
   et->name.length= strlen(et->name.str);
 
   if ((et->body.str= get_field(mem_root,
-                               table->field[Events::FIELD_BODY])) == NULL)
+                               table->field[ET_FIELD_BODY])) == NULL)
     goto error;
 
   et->body.length= strlen(et->body.str);
 
   if ((et->definer.str= get_field(mem_root,
-                                  table->field[Events::FIELD_DEFINER])) == NullS)
+                                  table->field[ET_FIELD_DEFINER])) == NullS)
     goto error;
   et->definer.length= strlen(et->definer.str);
 
@@ -772,27 +775,27 @@ Event_timed::load_from_row(MEM_ROOT *mem
   et->definer_host.str= strmake_root(mem_root, ptr + 1, len);/* 1:because of @*/
   et->definer_host.length= len;
   
-  et->starts_null= table->field[Events::FIELD_STARTS]->is_null();
-  res1= table->field[Events::FIELD_STARTS]->
+  et->starts_null= table->field[ET_FIELD_STARTS]->is_null();
+  res1= table->field[ET_FIELD_STARTS]->
                                     get_date(&et->starts,TIME_NO_ZERO_DATE);
 
-  et->ends_null= table->field[Events::FIELD_ENDS]->is_null();
-  res2= table->field[Events::FIELD_ENDS]->get_date(&et->ends, TIME_NO_ZERO_DATE);
+  et->ends_null= table->field[ET_FIELD_ENDS]->is_null();
+  res2= table->field[ET_FIELD_ENDS]->get_date(&et->ends, TIME_NO_ZERO_DATE);
   
-  if (!table->field[Events::FIELD_INTERVAL_EXPR]->is_null())
-    et->expression= table->field[Events::FIELD_INTERVAL_EXPR]->val_int();
+  if (!table->field[ET_FIELD_INTERVAL_EXPR]->is_null())
+    et->expression= table->field[ET_FIELD_INTERVAL_EXPR]->val_int();
   else
     et->expression= 0;
   /*
     If res1 and res2 are true then both fields are empty.
-    Hence if Events::FIELD_EXECUTE_AT is empty there is an error.
+    Hence if ET_FIELD_EXECUTE_AT is empty there is an error.
   */
   et->execute_at_null=
-            table->field[Events::FIELD_EXECUTE_AT]->is_null();
+            table->field[ET_FIELD_EXECUTE_AT]->is_null();
   DBUG_ASSERT(!(et->starts_null && et->ends_null && !et->expression &&
               et->execute_at_null));
   if (!et->expression &&
-      table->field[Events::FIELD_EXECUTE_AT]-> get_date(&et->execute_at,
+      table->field[ET_FIELD_EXECUTE_AT]-> get_date(&et->execute_at,
                                                         TIME_NO_ZERO_DATE))
     goto error;
 
@@ -800,22 +803,22 @@ Event_timed::load_from_row(MEM_ROOT *mem
     In DB the values start from 1 but enum interval_type starts
     from 0
   */
-  if (!table->field[Events::FIELD_TRANSIENT_INTERVAL]->is_null())
+  if (!table->field[ET_FIELD_TRANSIENT_INTERVAL]->is_null())
     et->interval= (interval_type) ((ulonglong)
-          table->field[Events::FIELD_TRANSIENT_INTERVAL]->val_int() - 1);
+          table->field[ET_FIELD_TRANSIENT_INTERVAL]->val_int() - 1);
   else
     et->interval= (interval_type) 0;
 
-  et->created= table->field[Events::FIELD_CREATED]->val_int();
-  et->modified= table->field[Events::FIELD_MODIFIED]->val_int();
+  et->created= table->field[ET_FIELD_CREATED]->val_int();
+  et->modified= table->field[ET_FIELD_MODIFIED]->val_int();
 
-  table->field[Events::FIELD_LAST_EXECUTED]->
+  table->field[ET_FIELD_LAST_EXECUTED]->
                      get_date(&et->last_executed, TIME_NO_ZERO_DATE);
 
   last_executed_changed= false;
 
   /* ToDo : Andrey . Find a way not to allocate ptr on event_mem_root */
-  if ((ptr= get_field(mem_root, table->field[Events::FIELD_STATUS])) == NullS)
+  if ((ptr= get_field(mem_root, table->field[ET_FIELD_STATUS])) == NullS)
     goto error;
 
   DBUG_PRINT("load_from_row", ("Event [%s] is [%s]", et->name.str, ptr));
@@ -823,20 +826,20 @@ Event_timed::load_from_row(MEM_ROOT *mem
 
   /* ToDo : Andrey . Find a way not to allocate ptr on event_mem_root */
   if ((ptr= get_field(mem_root,
-                  table->field[Events::FIELD_ON_COMPLETION])) == NullS)
+                  table->field[ET_FIELD_ON_COMPLETION])) == NullS)
     goto error;
 
   et->on_completion= (ptr[0]=='D'? Event_timed::ON_COMPLETION_DROP:
                                    Event_timed::ON_COMPLETION_PRESERVE);
 
-  et->comment.str= get_field(mem_root, table->field[Events::FIELD_COMMENT]);
+  et->comment.str= get_field(mem_root, table->field[ET_FIELD_COMMENT]);
   if (et->comment.str != NullS)
     et->comment.length= strlen(et->comment.str);
   else
     et->comment.length= 0;
     
 
-  et->sql_mode= (ulong) table->field[Events::FIELD_SQL_MODE]->val_int();
+  et->sql_mode= (ulong) table->field[ET_FIELD_SQL_MODE]->val_int();
 
   DBUG_RETURN(0);
 error:
@@ -1277,6 +1280,7 @@ Event_timed::mark_last_executed(THD *thd
 }
 
 
+
 /*
   Drops the event
 
@@ -1299,7 +1303,8 @@ Event_timed::drop(THD *thd)
   uint tmp= 0;
   DBUG_ENTER("Event_timed::drop");
 
-  DBUG_RETURN(db_drop_event(thd, dbname, name, false, &tmp));
+  DBUG_RETURN(Events::get_instance()->
+                db_repository.drop_event(thd, dbname, name, false, &tmp));
 }
 
 
@@ -1336,7 +1341,7 @@ Event_timed::update_fields(THD *thd)
 
   thd->reset_n_backup_open_tables_state(&backup);
 
-  if (Events::open_event_table(thd, TL_WRITE, &table))
+  if (Events::get_instance()->open_event_table(thd, TL_WRITE, &table))
   {
     ret= EVEX_OPEN_TABLE_FAILED;
     goto done;
@@ -1352,15 +1357,15 @@ Event_timed::update_fields(THD *thd)
 
   if (last_executed_changed)
   {
-    table->field[Events::FIELD_LAST_EXECUTED]->set_notnull();
-    table->field[Events::FIELD_LAST_EXECUTED]->store_time(&last_executed,
+    table->field[ET_FIELD_LAST_EXECUTED]->set_notnull();
+    table->field[ET_FIELD_LAST_EXECUTED]->store_time(&last_executed,
                                                MYSQL_TIMESTAMP_DATETIME);
     last_executed_changed= false;
   }
   if (status_changed)
   {
-    table->field[Events::FIELD_STATUS]->set_notnull();
-    table->field[Events::FIELD_STATUS]->store((longlong)status, true);
+    table->field[ET_FIELD_STATUS]->set_notnull();
+    table->field[ET_FIELD_STATUS]->store((longlong)status, true);
     status_changed= false;
   }
 
@@ -1630,8 +1635,8 @@ Event_timed::compile(THD *thd, MEM_ROOT 
   thd->query_length= show_create.length();
   DBUG_PRINT("info", ("query:%s",thd->query));
 
-  change_security_context(thd, definer_user, definer_host, dbname,
-                          &security_ctx, &save_ctx);
+  thd->change_security_context(definer_user, definer_host, dbname,
+                               &security_ctx, &save_ctx);
   thd->lex= &lex;
   lex_start(thd, (uchar*)thd->query, thd->query_length);
   lex.et_compile_phase= TRUE;
@@ -1669,7 +1674,7 @@ done:
   lex.et->deinit_mutexes();
 
   lex_end(&lex);
-  restore_security_context(thd, save_ctx);
+  thd->restore_security_context(save_ctx);
   DBUG_PRINT("note", ("return old data on its place. set back NAMES"));
 
   thd->lex= old_lex;
@@ -1869,23 +1874,6 @@ event_timed_db_equal(Event_timed *et, LE
   return !sortcmp_lex_string(et->dbname, *db, system_charset_info);
 }
 
-
-/*
-  Checks whether two events have the same definer
-
-  SYNOPSIS
-    event_timed_definer_equal()
-
-  Returns
-    TRUE  definers are equal
-    FALSE definers are not equal
-*/
-
-bool
-event_timed_definer_equal(Event_timed *et, LEX_STRING *definer)
-{
-  return !sortcmp_lex_string(et->definer, *definer, system_charset_info);
-}
 
 
 /*

--- 1.4/sql/event_data_objects.h	2006-06-27 10:53:15 +02:00
+++ 1.5/sql/event_data_objects.h	2006-06-28 01:27:52 +02:00
@@ -40,9 +40,35 @@
 #define EVENT_FREE_WHEN_FINISHED (1L << 2)
 
 
+#define EVENT_EXEC_STARTED      0
+#define EVENT_EXEC_ALREADY_EXEC 1
+#define EVENT_EXEC_CANT_FORK    2
+
+
 class sp_head;
 class Sql_alloc;
 
+class Event_timed;
+
+/* Compares only the schema part of the identifier */
+bool
+event_timed_db_equal(Event_timed *et, LEX_STRING *db);
+
+
+/* Compares the whole identifier*/
+bool
+event_timed_identifier_equal(Event_timed *a, Event_timed *b);
+
+/* Compares only the schema part of the identifier */
+bool
+event_timed_db_equal(sp_name *name, LEX_STRING *db);
+
+
+/* Compares the whole identifier*/
+bool
+event_timed_identifier_equal(sp_name *a, Event_timed *b);
+
+
 class Event_timed
 {
   Event_timed(const Event_timed &);	/* Prevent use of these */
@@ -293,6 +319,12 @@ public:
 
   void
   init_comment(THD *thd, LEX_STRING *set_comment);
+
+};
+
+
+class Event_queue_element : public Event_timed
+{
 
 };
 

--- 1.177/sql/set_var.cc	2006-06-21 17:50:27 +02:00
+++ 1.178/sql/set_var.cc	2006-06-28 01:27:52 +02:00
@@ -3891,7 +3891,7 @@ byte *sys_var_thd_dbug::value_ptr(THD *t
 bool
 sys_var_event_scheduler::update(THD *thd, set_var *var)
 {
-  enum Event_scheduler::enum_error_code res;
+  int res;
   Event_scheduler *scheduler= Event_scheduler::get_instance();
   /* here start the thread if not running. */
   DBUG_ENTER("sys_var_event_scheduler::update");
Thread
bk commit into 5.1 tree (andrey:1.2215)ahristov28 Jun