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.2200 06/02/28 17:32:35 andrey@lmy004. +9 -0
manual merge
sql/event_timed.cc
1.43 06/02/28 17:32:28 andrey@lmy004. +19 -21
manual merge
sql/event_executor.cc
1.37 06/02/28 17:32:28 andrey@lmy004. +102 -120
manual merge
sql/event.cc
1.36 06/02/28 17:32:28 andrey@lmy004. +77 -110
manual merge
sql/sql_yacc.yy
1.469 06/02/28 16:16:02 andrey@lmy004. +0 -0
Auto merged
sql/sql_show.cc
1.315 06/02/28 16:16:02 andrey@lmy004. +0 -0
Auto merged
sql/sql_parse.cc
1.526 06/02/28 16:16:01 andrey@lmy004. +0 -0
Auto merged
sql/field.h
1.178 06/02/28 16:16:01 andrey@lmy004. +0 -0
Auto merged
sql/event.h
1.29 06/02/28 16:16:01 andrey@lmy004. +0 -0
Auto merged
mysql-test/t/disabled.def
1.87 06/02/28 16:16:01 andrey@lmy004. +0 -0
Auto merged
# 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-bug17619/RESYNC
--- 1.177/sql/field.h 2006-02-27 16:58:32 +01:00
+++ 1.178/sql/field.h 2006-02-28 16:16:01 +01:00
@@ -101,6 +101,10 @@ public:
virtual ~Field() {}
/* Store functions returns 1 on overflow and -1 on fatal error */
virtual int store(const char *to,uint length,CHARSET_INFO *cs)=0;
+ int store(LEX_STRING *str,CHARSET_INFO *cs)
+ {
+ return store(str->str, str->length, cs);
+ }
virtual int store(double nr)=0;
virtual int store(longlong nr, bool unsigned_val)=0;
virtual int store_decimal(const my_decimal *d)=0;
--- 1.525/sql/sql_parse.cc 2006-02-27 16:58:32 +01:00
+++ 1.526/sql/sql_parse.cc 2006-02-28 16:16:01 +01:00
@@ -3762,15 +3762,15 @@ end_with_restore_list:
uint rows_affected= 1;
DBUG_ASSERT(lex->et);
do {
- if (! lex->et->dbname.str)
+ if (! lex->et->ident.dbname.str)
{
my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
res= true;
break;
}
- if (check_access(thd, EVENT_ACL, lex->et->dbname.str, 0, 0, 0,
- is_schema_db(lex->et->dbname.str)))
+ if (check_access(thd, EVENT_ACL, lex->et->ident.dbname.str, 0, 0, 0,
+ is_schema_db(lex->et->ident.dbname.str)))
break;
if (end_active_trans(thd))
@@ -3817,12 +3817,12 @@ end_with_restore_list:
is_schema_db(lex->spname->m_db.str)))
break;
- if (lex->spname->m_name.length > NAME_LEN)
+ if (lex->et->ident.name.length > NAME_LEN)
{
- my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str);
+ my_error(ER_TOO_LONG_IDENT, MYF(0), lex->et->ident.name.str);
goto error;
}
- res= evex_show_create_event(thd, lex->spname, lex->et->definer);
+ res= evex_show_create_event(thd, lex->et->get_ident());
break;
}
case SQLCOM_CREATE_FUNCTION: // UDF function
--- 1.314/sql/sql_show.cc 2006-02-28 12:08:08 +01:00
+++ 1.315/sql/sql_show.cc 2006-02-28 16:16:02 +01:00
@@ -3936,7 +3936,7 @@ fill_events_copy_to_schema_table(THD *th
const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
CHARSET_INFO *scs= system_charset_info;
TIME time;
- event_timed et;
+ Event_timed et;
DBUG_ENTER("fill_events_copy_to_schema_tab");
restore_record(sch_table, s->default_values);
@@ -3947,14 +3947,14 @@ fill_events_copy_to_schema_table(THD *th
DBUG_RETURN(1);
}
- if (!(!wild || !wild[0] || !wild_compare(et.name.str, wild, 0)))
+ if (!(!wild || !wild[0] || !wild_compare(et.ident.name.str, wild, 0)))
DBUG_RETURN(0);
//->field[0] is EVENT_CATALOG and is by default NULL
- sch_table->field[1]->store(et.dbname.str, et.dbname.length, scs);
- sch_table->field[2]->store(et.name.str, et.name.length, scs);
- sch_table->field[3]->store(et.definer.str, et.definer.length, scs);
+ sch_table->field[1]->store(et.ident.dbname.str, et.ident.dbname.length, scs);
+ sch_table->field[2]->store(et.ident.name.str, et.ident.name.length, scs);
+ sch_table->field[3]->store(et.ident.definer.str, et.ident.definer.length, scs);
sch_table->field[4]->store(et.body.str, et.body.length, scs);
/* [9] is SQL_MODE */
--- 1.468/sql/sql_yacc.yy 2006-02-28 11:46:02 +01:00
+++ 1.469/sql/sql_yacc.yy 2006-02-28 16:16:02 +01:00
@@ -1343,7 +1343,7 @@ create:
lex->create_info.options= $3;
- if (!(lex->et= new event_timed())) // implicitly calls event_timed::init()
+ if (!(lex->et= new Event_timed())) // implicitly calls Event_timed::init()
YYABORT;
/*
@@ -1355,10 +1355,8 @@ create:
YYTHD->client_capabilities &= (~CLIENT_MULTI_QUERIES);
if (!lex->et_compile_phase)
- {
- lex->et->init_name(YYTHD, $4);
- lex->et->init_definer(YYTHD);
- }
+ lex->et->init_name_and_definer(YYTHD, $4);
+
}
ON SCHEDULE_SYM ev_schedule_time
opt_ev_on_completion
@@ -4822,7 +4820,7 @@ alter:
*/
{
LEX *lex=Lex;
- event_timed *et;
+ Event_timed *et;
if (lex->et)
{
@@ -4835,15 +4833,12 @@ alter:
}
lex->spname= 0;//defensive programming
- if (!(et= new event_timed()))// implicitly calls event_timed::init()
+ if (!(et= new Event_timed()))// implicitly calls Event_timed::init()
YYABORT;
lex->et = et;
if (!lex->et_compile_phase)
- {
- et->init_definer(YYTHD);
- et->init_name(YYTHD, $3);
- }
+ et->init_name_and_definer(YYTHD, $3);
/*
We have to turn of CLIENT_MULTI_QUERIES while parsing a
@@ -4911,7 +4906,7 @@ opt_ev_rename_to: /* empty */ { $$= 0;}
{
LEX *lex=Lex;
lex->spname= $3; //use lex's spname to hold the new name
- //the original name is in the event_timed object
+ //the original name is in the Event_timed object
$$= 1;
}
;
@@ -7734,14 +7729,11 @@ drop:
YYABORT;
}
- if (!(lex->et= new event_timed()))
+ if (!(lex->et= new Event_timed()))
YYABORT;
if (!lex->et_compile_phase)
- {
- lex->et->init_name(YYTHD, $4);
- lex->et->init_definer(YYTHD);
- }
+ lex->et->init_name_and_definer(YYTHD, $4);
lex->sql_command = SQLCOM_DROP_EVENT;
lex->drop_if_exists= $3;
@@ -8458,10 +8450,10 @@ show_param:
{
Lex->sql_command = SQLCOM_SHOW_CREATE_EVENT;
Lex->spname= $3;
- Lex->et= new event_timed();
+ Lex->et= new Event_timed();
if (!Lex->et)
YYABORT;
- Lex->et->init_definer(YYTHD);
+ Lex->et->init_name_and_definer(YYTHD, $3);
}
;
--- 1.35/sql/event.cc 2006-02-28 14:43:41 +01:00
+++ 1.36/sql/event.cc 2006-02-28 17:32:28 +01:00
@@ -49,11 +49,11 @@
- Consider using conditional variable when doing shutdown instead of
waiting till all worker threads end.
- - Make event_timed::get_show_create_event() work
+ - Make Event_timed::get_show_create_event() work
- Add logging to file
- - Move comparison code to class event_timed
+ - Move comparison code to class Event_timed
Warning:
- For now parallel execution is not possible because the same sp_head cannot be
@@ -276,14 +276,14 @@ my_time_compare(TIME *a, TIME *b)
/*
- Compares the execute_at members of 2 event_timed instances
-
+ Compares the execute_at members of 2 Event_timed instances
+
Synopsis
event_timed_compare()
-
- a - first event_timed object
- b - second event_timed object
-
+
+ a - first Event_timed object
+ b - second Event_timed object
+
RETURNS:
-1 - a->execute_at < b->execute_at
0 - a->execute_at == b->execute_at
@@ -294,14 +294,14 @@ my_time_compare(TIME *a, TIME *b)
*/
int
-event_timed_compare(event_timed *a, event_timed *b)
+event_timed_compare(Event_timed *a, Event_timed *b)
{
return my_time_compare(&a->execute_at, &b->execute_at);
}
/*
- Compares the execute_at members of 2 event_timed instances.
+ Compares the execute_at members of 2 Event_timed instances.
Used as callback for the prioritized queue when shifting
elements inside.
@@ -309,9 +309,9 @@ event_timed_compare(event_timed *a, even
event_timed_compare()
vptr - not used (set it to NULL)
- a - first event_timed object
- b - second event_timed object
-
+ a - first Event_timed object
+ b - second Event_timed object
+
RETURNS:
-1 - a->execute_at < b->execute_at
0 - a->execute_at == b->execute_at
@@ -324,7 +324,7 @@ event_timed_compare(event_timed *a, even
int
event_timed_compare_q(void *vptr, byte* a, byte *b)
{
- return event_timed_compare((event_timed *)a, (event_timed *)b);
+ return event_timed_compare((Event_timed *)a, (Event_timed *)b);
}
@@ -340,10 +340,10 @@ event_timed_compare_q(void *vptr, byte*
buf - preallocated String buffer to add the value to
interval - the interval type (for instance YEAR_MONTH)
expression - the value in the lowest entity
-
+
RETURNS
- 0 - OK
- 1 - Error
+ 0 OK
+ 1 Error
*/
int
@@ -482,7 +482,7 @@ evex_open_event_table(THD *thd, enum thr
{
TABLE_LIST tables;
bool not_used;
- DBUG_ENTER("open_proc_table");
+ DBUG_ENTER("evex_open_event_table");
bzero((char*) &tables, sizeof(tables));
tables.db= (char*) "mysql";
@@ -520,10 +520,10 @@ evex_open_event_table(THD *thd, enum thr
*/
inline int
-evex_db_find_event_aux(THD *thd, event_timed *et, TABLE *table)
+evex_db_find_event_aux(THD *thd, Event_timed_name *etn, TABLE *table)
{
- return evex_db_find_event_by_name(thd, et->dbname, et->name,
- et->definer, table);
+ return evex_db_find_event_by_name(thd, etn->dbname, etn->name,
+ etn->definer, table);
}
@@ -551,6 +551,7 @@ evex_db_find_event_by_name(THD *thd, con
byte key[MAX_KEY_LENGTH];
DBUG_ENTER("evex_db_find_event_by_name");
DBUG_PRINT("enter", ("name: %.*s", ev_name.length, ev_name.str));
+ CHARSET_INFO *mcb= &my_charset_bin;
/*
Create key to find row. We have to use field->store() to be able to
@@ -562,19 +563,16 @@ evex_db_find_event_by_name(THD *thd, con
if (dbname.length > table->field[EVEX_FIELD_DB]->field_length ||
ev_name.length > table->field[EVEX_FIELD_NAME]->field_length ||
user_name.length > table->field[EVEX_FIELD_DEFINER]->field_length)
-
DBUG_RETURN(EVEX_KEY_NOT_FOUND);
- table->field[EVEX_FIELD_DB]->store(dbname.str, dbname.length, &my_charset_bin);
- table->field[EVEX_FIELD_NAME]->store(ev_name.str, ev_name.length,
- &my_charset_bin);
- table->field[EVEX_FIELD_DEFINER]->store(user_name.str, user_name.length,
- &my_charset_bin);
+ table->field[EVEX_FIELD_DB]->store(dbname.str, dbname.length, mcb);
+ table->field[EVEX_FIELD_NAME]->store(ev_name.str, ev_name.length, mcb);
+ table->field[EVEX_FIELD_DEFINER]->store(user_name.str, user_name.length, mcb);
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))
+ table->key_info->key_length,HA_READ_KEY_EXACT))
DBUG_RETURN(EVEX_KEY_NOT_FOUND);
DBUG_RETURN(0);
@@ -589,6 +587,7 @@ evex_db_find_event_by_name(THD *thd, con
thd THD
table the row to fill out
et Event's data
+ is_update Create or update
Returns
0 - ok
@@ -600,23 +599,27 @@ evex_db_find_event_by_name(THD *thd, con
*/
static int
-evex_fill_row(THD *thd, TABLE *table, event_timed *et, my_bool is_update)
+evex_fill_row(THD *thd, TABLE *table, Event_timed *et, my_bool is_update)
{
enum evex_table_field field_num;
+ CHARSET_INFO *scs= system_charset_info;
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= EVEX_FIELD_DB]->
- store(et->dbname.str, et->dbname.length, system_charset_info))
- goto trunc_err;
-
- if (table->field[field_num= EVEX_FIELD_NAME]->
- store(et->name.str, et->name.length, system_charset_info))
- goto trunc_err;
+ DBUG_PRINT("info", ("dbname=[%s]", et->ident.dbname.str));
+ DBUG_PRINT("info", ("name =[%s]", et->ident.name.str));
+ DBUG_PRINT("info", ("user =[%s]", et->ident.definer.str));
+ DBUG_PRINT("info", ("body =[%*.s]", et->body.length, et->body.str));
+
+ /* when update we set schema and name in the calling function */
+ if (!is_update)
+ {
+ if (table->field[field_num= EVEX_FIELD_DB]->store(&et->ident.dbname, scs))
+ goto trunc_err;
+
+ if (table->field[field_num= EVEX_FIELD_NAME]->store(&et->ident.name, scs))
+ goto trunc_err;
+ }
/* both ON_COMPLETION and STATUS are NOT NULL thus not calling set_notnull() */
table->field[EVEX_FIELD_ON_COMPLETION]->store((longlong)et->on_completion);
@@ -631,8 +634,7 @@ evex_fill_row(THD *thd, TABLE *table, ev
{
table->field[EVEX_FIELD_SQL_MODE]->store((longlong)thd->variables.sql_mode);
- if (table->field[field_num= EVEX_FIELD_BODY]->
- store(et->body.str, et->body.length, system_charset_info))
+ if (table->field[field_num= EVEX_FIELD_BODY]->store(&et->body, scs))
goto trunc_err;
}
@@ -666,6 +668,7 @@ evex_fill_row(THD *thd, TABLE *table, ev
}
else if (et->execute_at.year)
{
+ /* fix_fields already called in init_execute_at */
table->field[EVEX_FIELD_INTERVAL_EXPR]->set_null();
table->field[EVEX_FIELD_TRANSIENT_INTERVAL]->set_null();
table->field[EVEX_FIELD_STARTS]->set_null();
@@ -693,6 +696,7 @@ evex_fill_row(THD *thd, TABLE *table, ev
system_charset_info))
goto trunc_err;
}
+ DBUG_PRINT("info", ("finished"));
DBUG_RETURN(0);
trunc_err:
@@ -720,7 +724,7 @@ trunc_err:
*/
static int
-db_create_event(THD *thd, event_timed *et, my_bool create_if_not,
+db_create_event(THD *thd, Event_timed *et, my_bool create_if_not,
uint *rows_affected)
{
int ret= 0;
@@ -728,8 +732,9 @@ db_create_event(THD *thd, event_timed *e
char definer[HOSTNAME_LENGTH+USERNAME_LENGTH+2];
char olddb[128];
bool dbchanged= false;
+ CHARSET_INFO *scs= system_charset_info;
DBUG_ENTER("db_create_event");
- DBUG_PRINT("enter", ("name: %.*s", et->name.length, et->name.str));
+ DBUG_PRINT("enter", ("name: %s", et->ident.name.str));
*rows_affected= 0;
DBUG_PRINT("info", ("open mysql.event for update"));
@@ -740,46 +745,46 @@ db_create_event(THD *thd, event_timed *e
}
DBUG_PRINT("info", ("check existance of an event with the same name"));
- if (!evex_db_find_event_aux(thd, et, table))
+ if (!evex_db_find_event_aux(thd, et->get_ident(), 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;
+ et->ident.name.str);
+ goto ok;
}
- my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), et->name.str);
+ my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), et->ident.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)))
+ if ((ret= sp_use_new_db(thd, et->ident.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)
+ if (EVEX_DB_FIELD_LEN < scs->cset->numchars(scs, et->ident.dbname.str,
+ et->ident.dbname.str +
+ et->ident.dbname.length))
{
- my_error(ER_TOO_LONG_IDENT, MYF(0), et->dbname.str);
+ my_error(ER_TOO_LONG_IDENT, MYF(0), et->ident.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)
+ if (EVEX_DB_FIELD_LEN < scs->cset->numchars(scs, et->ident.name.str,
+ et->ident.name.str +
+ et->ident.name.length))
{
- my_error(ER_TOO_LONG_IDENT, MYF(0), et->name.str);
+ my_error(ER_TOO_LONG_IDENT, MYF(0), et->ident.name.str);
goto err;
}
if (et->body.length > table->field[EVEX_FIELD_BODY]->field_length)
{
- my_error(ER_TOO_LONG_BODY, MYF(0), et->name.str);
+ my_error(ER_TOO_LONG_BODY, MYF(0), et->ident.name.str);
goto err;
}
@@ -790,11 +795,9 @@ db_create_event(THD *thd, event_timed *e
goto err;
}
- if ((ret=table->field[EVEX_FIELD_DEFINER]->store(et->definer.str,
- et->definer.length,
- system_charset_info)))
+ if ((ret=table->field[EVEX_FIELD_DEFINER]->store(&et->ident.definer, scs)))
{
- my_error(ER_EVENT_STORE_FAILED, MYF(0), et->name.str, ret);
+ my_error(ER_EVENT_STORE_FAILED, MYF(0), et->ident.name.str, ret);
goto err;
}
@@ -809,7 +812,7 @@ db_create_event(THD *thd, event_timed *e
if (table->file->ha_write_row(table->record[0]))
{
- my_error(ER_EVENT_STORE_FAILED, MYF(0), et->name.str, ret);
+ my_error(ER_EVENT_STORE_FAILED, MYF(0), et->ident.name.str, ret);
goto err;
}
@@ -855,17 +858,21 @@ err:
*/
static int
-db_update_event(THD *thd, event_timed *et, sp_name *new_name)
+db_update_event(THD *thd, Event_timed *et, sp_name *new_name)
{
TABLE *table;
int ret= EVEX_OPEN_TABLE_FAILED;
+ CHARSET_INFO *scs= system_charset_info;
+
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->name.length, et->name.str));
+ DBUG_PRINT("info", ("dbname: %s", et->ident.dbname.str));
+ DBUG_PRINT("info", ("name : %s", et->ident.name.str));
+ DBUG_PRINT("info", ("user : %s", et->ident.definer.str));
if (new_name)
- DBUG_PRINT("enter", ("rename to: %.*s", new_name->m_name.length,
- new_name->m_name.str));
+ {
+ DBUG_PRINT("enter", ("rename dbname: %s", new_name->m_db.str));
+ DBUG_PRINT("enter", ("rename name : %s", new_name->m_name.str));
+ }
if (evex_open_event_table(thd, TL_WRITE, &table))
{
@@ -876,15 +883,15 @@ db_update_event(THD *thd, event_timed *e
/* first look whether we overwrite */
if (new_name)
{
- if (!sortcmp_lex_string(et->name, new_name->m_name, system_charset_info) &&
- !sortcmp_lex_string(et->dbname, new_name->m_db, system_charset_info))
+ if (!sortcmp_lex_string(et->ident.name, new_name->m_name, scs) &&
+ !sortcmp_lex_string(et->ident.dbname, new_name->m_db, scs))
{
- my_error(ER_EVENT_SAME_NAME, MYF(0), et->name.str);
+ my_error(ER_EVENT_SAME_NAME, MYF(0), et->ident.name.str);
goto err;
}
if (!evex_db_find_event_by_name(thd, new_name->m_db, new_name->m_name,
- et->definer, table))
+ et->ident.definer, table))
{
my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), new_name->m_name.str);
goto err;
@@ -896,32 +903,33 @@ db_update_event(THD *thd, event_timed *e
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))
+ if (EVEX_KEY_NOT_FOUND == evex_db_find_event_aux(thd, et->get_ident(), table))
{
- my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), et->name.str);
- goto err;
+ my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), et->ident.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 */
+ /*
+ 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[EVEX_FIELD_DB]->
- store(new_name->m_db.str, new_name->m_db.length, system_charset_info);
- table->field[EVEX_FIELD_NAME]->
- store(new_name->m_name.str, new_name->m_name.length, system_charset_info);
+ table->field[EVEX_FIELD_DB]->store(&new_name->m_db, scs);
+ table->field[EVEX_FIELD_NAME]->store(&new_name->m_name, 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);
+ my_error(ER_EVENT_STORE_FAILED, MYF(0), et->ident.name.str, ret);
goto err;
}
@@ -943,46 +951,42 @@ err:
SYNOPSIS
db_find_event()
thd THD
- name the name of the event to find
- definer who owns the event
+ etn Event_timed_name
ett event's data if event is found
tbl TABLE object to use when not NULL
-
+ root On which root to load the event's data
NOTES
1) Use sp_name for look up, return in **ett if found
2) tbl is not closed at exit
*/
-static int
-db_find_event(THD *thd, sp_name *name, LEX_STRING *definer, event_timed **ett,
- TABLE *tbl, MEM_ROOT *root)
+int
+db_find_event(THD *thd, Event_timed_name *etn, Event_timed **ett, MEM_ROOT *root)
{
TABLE *table;
int ret;
char *ptr;
- event_timed *et=NULL;
+ 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;
+ DBUG_PRINT("enter", ("db : %*s", etn->dbname.length, etn->dbname.str));
+ DBUG_PRINT("enter", ("name: %*s", etn->name.length, etn->name.str));
+ DBUG_PRINT("enter", ("defi: %*s", etn->definer.length, etn->definer.str));
+ DBUG_ASSERT(root);
- if (tbl)
- table= tbl;
- else if (evex_open_event_table(thd, TL_READ, &table))
+ if (evex_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, *definer,
- table)))
+ if ((ret= evex_db_find_event_aux(thd, etn, table)))
{
- my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name->m_name.str);
+ my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), etn->name.str);
goto done;
}
- et= new event_timed;
+
+ et= new Event_timed;
/*
1)The table should not be closed beforehand. ::load_from_row() only loads
@@ -1002,8 +1006,7 @@ done:
delete et;
et= 0;
}
- /* don't close the table if we haven't opened it ourselves */
- if (!tbl && table)
+ if (table)
close_thread_tables(thd);
*ett= et;
DBUG_RETURN(ret);
@@ -1027,33 +1030,38 @@ done:
*/
static int
-evex_load_and_compile_event(THD * thd, sp_name *spn, LEX_STRING definer,
- bool use_lock)
+evex_load_and_compile_event(THD * thd, Event_timed_name *etn, bool use_lock)
{
int ret= 0;
MEM_ROOT *tmp_mem_root;
- event_timed *ett;
+ Event_timed *ett;
Open_tables_state backup;
DBUG_ENTER("db_load_and_compile_event");
- DBUG_PRINT("enter", ("name: %*s", spn->m_name.length, spn->m_name.str));
-
- tmp_mem_root= thd->mem_root;
- thd->mem_root= &evex_mem_root;
+ DBUG_PRINT("enter", ("name: %*s", 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 */
- ret= db_find_event(thd, spn, &definer, &ett, NULL, NULL);
+ /*
+ no need to use my_error() here because db_find_event() has done it
+ */
+ ret= db_find_event(thd, etn, &ett, &evex_mem_root);
thd->restore_backup_open_tables_state(&backup);
if (ret)
goto done;
+#if NO_NEED_TO_COMPILE_IT_HERE_COMPILE_IT_DURING_EXEC
+ tmp_mem_root= thd->mem_root;
+ thd->mem_root= &evex_mem_root;
/*
allocate on evex_mem_root. if you call without evex_mem_root
then sphead will not be cleared!
*/
if ((ret= ett->compile(thd, &evex_mem_root)))
goto done;
+
+ if (thd->mem_root != tmp_mem_root)
+ thd->mem_root= tmp_mem_root;
+#endif
ett->compute_next_execution_time();
if (use_lock)
@@ -1070,8 +1078,6 @@ evex_load_and_compile_event(THD * thd, s
VOID(pthread_mutex_unlock(&LOCK_event_arrays));
done:
- if (thd->mem_root != tmp_mem_root)
- thd->mem_root= tmp_mem_root;
DBUG_RETURN(ret);
}
@@ -1083,62 +1089,52 @@ done:
SYNOPSIS
evex_remove_from_cache()
-
- db - db name
- name - event name
- use_lock - whether to lock the mutex LOCK_event_arrays or not in case it
- has been already locked outside
- is_drop - if an event is currently being executed then we can also delete
- the event_timed instance, so we alarm the event that it should
- drop itself if this parameter is set to TRUE. It's false on
- ALTER EVENT.
+ etn The name of the event to remove from the queue
+ use_lock Whether to lock the mutex LOCK_event_arrays or not in case it
+ has been already locked outside
+ is_drop If an event is currently being executed then we can also delete
+ the Event_timed instance, so we alarm the event that it should
+ drop itself if this parameter is set to TRUE. It's false on
+ ALTER EVENT.
RETURNS
0 OK (always)
*/
static int
-evex_remove_from_cache(LEX_STRING *db, LEX_STRING *name, bool use_lock,
- bool is_drop)
+evex_remove_from_cache(Event_timed_name *etn, bool use_lock, bool is_drop)
{
- //ToDo : Add definer to the tuple (db, name) to become triple
uint i;
- int ret= 0;
DBUG_ENTER("evex_remove_from_cache");
- /*
- It is possible that 2 (or 1) pass(es) won't find the event in memory.
- The reason is that DISABLED events are not cached.
- */
if (use_lock)
VOID(pthread_mutex_lock(&LOCK_event_arrays));
- for (i= 0; i < evex_queue_num_elements(EVEX_EQ_NAME); ++i)
+ for (i= 0; i < EVEX_EQ_NAME.elements; ++i)
{
- event_timed *et= evex_queue_element(&EVEX_EQ_NAME, i, event_timed*);
- DBUG_PRINT("info", ("[%s.%s]==[%s.%s]?",db->str,name->str, et->dbname.str,
- et->name.str));
- if (!sortcmp_lex_string(*name, et->name, system_charset_info) &&
- !sortcmp_lex_string(*db, et->dbname, system_charset_info))
+ Event_timed *et= evex_queue_element(&EVEX_EQ_NAME, i, Event_timed*);
+ DBUG_PRINT("info", ("[%s.%s]==[%s.%s]?",
+ etn->dbname.str, etn->name.str,
+ et->ident.dbname.str, et->ident.name.str));
+ if (etn->same_name(et->get_ident()))
{
if (et->can_spawn_now())
{
- DBUG_PRINT("evex_remove_from_cache", ("not running - free and delete"));
+ DBUG_PRINT("info", ("not running - free and delete"));
et->free_sp();
delete et;
}
else
{
- DBUG_PRINT("evex_remove_from_cache",
- ("running.defer mem free. is_drop=%d", is_drop));
+ DBUG_PRINT("info", ("running.defer mem free. is_drop=%d", is_drop));
et->flags|= EVENT_EXEC_NO_MORE;
- et->dropped= is_drop;
+ if (is_drop)
+ et->dropped= true;
}
- DBUG_PRINT("evex_remove_from_cache", ("delete from queue"));
+ DBUG_PRINT("info", ("delete from queue"));
evex_queue_delete_element(&EVEX_EQ_NAME, i);
/* ok, we have cleaned */
- ret= 0;
goto done;
}
}
@@ -1147,7 +1143,7 @@ done:
if (use_lock)
VOID(pthread_mutex_unlock(&LOCK_event_arrays));
- DBUG_RETURN(ret);
+ DBUG_RETURN(0);
}
@@ -1168,14 +1164,13 @@ done:
*/
int
-evex_create_event(THD *thd, event_timed *et, uint create_options,
+evex_create_event(THD *thd, Event_timed *et, uint create_options,
uint *rows_affected)
{
int ret = 0;
DBUG_ENTER("evex_create_event");
- DBUG_PRINT("enter", ("name: %*s options:%d", et->name.length,
- et->name.str, create_options));
+ DBUG_PRINT("enter",("name: %s options:%d",et->ident.name.str, create_options));
if ((ret = db_create_event(thd, et,
create_options & HA_LEX_CREATE_IF_NOT_EXISTS,
@@ -1184,10 +1179,7 @@ evex_create_event(THD *thd, event_timed
VOID(pthread_mutex_lock(&LOCK_evex_running));
if (evex_is_running && et->status == MYSQL_EVENT_ENABLED)
- {
- sp_name spn(et->dbname, et->name);
- ret= evex_load_and_compile_event(thd, &spn, et->definer, true);
- }
+ ret= evex_load_and_compile_event(thd, et->get_ident(), true);
VOID(pthread_mutex_unlock(&LOCK_evex_running));
done:
@@ -1206,6 +1198,10 @@ done:
et event's data
new_name set in case of RENAME TO.
+ RETURNS
+ 0 OK
+ EVEX_COMPILE_ERROR Error during compilation of the event
+
NOTES
et contains data about dbname and event name.
new_name is the new name of the event, if not null (this means
@@ -1213,14 +1209,14 @@ done:
*/
int
-evex_update_event(THD *thd, event_timed *et, sp_name *new_name,
+evex_update_event(THD *thd, Event_timed *et, sp_name *new_name,
uint *rows_affected)
{
int ret, i;
bool need_second_pass= true;
DBUG_ENTER("evex_update_event");
- DBUG_PRINT("enter", ("name: %*s", et->name.length, et->name.str));
+ DBUG_PRINT("enter", ("name: %s", et->ident.name.str));
/*
db_update_event() opens & closes the table to prevent
@@ -1235,16 +1231,20 @@ evex_update_event(THD *thd, event_timed
UNLOCK_MUTEX_AND_BAIL_OUT(LOCK_evex_running, done);
VOID(pthread_mutex_lock(&LOCK_event_arrays));
- evex_remove_from_cache(&et->dbname, &et->name, false, false);
+ evex_remove_from_cache(et->get_ident(), false, false);
if (et->status == MYSQL_EVENT_ENABLED)
{
if (new_name)
- ret= evex_load_and_compile_event(thd, new_name, et->definer, false);
- else
{
- sp_name spn(et->dbname, et->name);
- ret= evex_load_and_compile_event(thd, &spn, et->definer, false);
+ Event_timed_name etn;
+ etn.name= new_name->m_name;
+ etn.dbname= new_name->m_db;
+ etn.definer= et->ident.definer;
+ ret= evex_load_and_compile_event(thd, &etn, false);
}
+ else
+ ret= evex_load_and_compile_event(thd, et->get_ident(), false);
+
if (ret == EVEX_COMPILE_ERROR)
my_error(ER_EVENT_COMPILE_ERROR, MYF(0));
}
@@ -1262,15 +1262,16 @@ done:
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
+ etn 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
+
*/
-int db_drop_event(THD *thd, event_timed *et, bool drop_if_exists,
+int db_drop_event(THD *thd, Event_timed_name *etn, bool drop_if_exists,
uint *rows_affected)
{
- TABLE *table;
+ TABLE *table= NULL;
Open_tables_state backup;
int ret;
@@ -1284,13 +1285,10 @@ int db_drop_event(THD *thd, event_timed
goto done;
}
- if (!(ret= evex_db_find_event_aux(thd, et, table)))
+ if (!(ret= evex_db_find_event_aux(thd, etn, table)))
{
if ((ret= table->file->ha_delete_row(table->record[0])))
- {
my_error(ER_EVENT_CANNOT_DELETE, MYF(0));
- goto done;
- }
}
else if (ret == EVEX_KEY_NOT_FOUND)
{
@@ -1298,20 +1296,18 @@ int db_drop_event(THD *thd, event_timed
{
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST),
- "Event", et->name.str);
+ "Event", etn->name.str);
ret= 0;
} else
- my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), et->name.str);
- goto done;
+ my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), etn->name.str);
}
-
-
-done:
/*
- evex_drop_event() is used by event_timed::drop therefore
+ evex_drop_event() is used by Event_timed::drop() therefore
we have to close our thread tables.
*/
close_thread_tables(thd);
+
+done:
thd->restore_backup_open_tables_state(&backup);
DBUG_RETURN(ret);
}
@@ -1325,33 +1321,24 @@ done:
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
-
+ rows_affected affected number of rows is returned here
+
+ RETURNS
+ see db_drop_event()
*/
int
-evex_drop_event(THD *thd, event_timed *et, bool drop_if_exists,
+evex_drop_event(THD *thd, Event_timed *et, bool drop_if_exists,
uint *rows_affected)
{
- TABLE *table;
- int ret= 0;
-
DBUG_ENTER("evex_drop_event");
-
VOID(pthread_mutex_lock(&LOCK_evex_running));
if (evex_is_running)
- ret= evex_remove_from_cache(&et->dbname, &et->name, true, true);
+ evex_remove_from_cache(et->get_ident(), true, true);
VOID(pthread_mutex_unlock(&LOCK_evex_running));
-
- if (ret == 1)
- ret= 0;
- else if (ret == 0)
- ret= db_drop_event(thd, et, drop_if_exists, rows_affected);
- else
- my_error(ER_UNKNOWN_ERROR, MYF(0));
-
- DBUG_RETURN(ret);
+
+ DBUG_RETURN(db_drop_event(thd, et->get_ident(),drop_if_exists,rows_affected));
}
@@ -1361,7 +1348,7 @@ evex_drop_event(THD *thd, event_timed *e
SYNOPSIS
evex_show_create_event()
thd THD
- spn the name of the event (db, name)
+ epn the name of the event
definer the definer of the event
RETURNS
@@ -1370,30 +1357,33 @@ evex_drop_event(THD *thd, event_timed *e
*/
int
-evex_show_create_event(THD *thd, sp_name *spn, LEX_STRING definer)
+evex_show_create_event(THD *thd, Event_timed_name *etn)
{
int ret;
- event_timed *et= NULL;
+ Event_timed *et= NULL;
Open_tables_state backup;
- DBUG_ENTER("evex_update_event");
- DBUG_PRINT("enter", ("name: %*s", spn->m_name.length, spn->m_name.str));
+ DBUG_ENTER("evex_show_create_event");
+ DBUG_PRINT("enter", ("db : %*s", etn->dbname.length, etn->dbname.str));
+ DBUG_PRINT("enter", ("name: %*s", etn->name.length, etn->name.str));
+ DBUG_PRINT("enter", ("defi: %*s", etn->definer.length, etn->definer.str));
thd->reset_n_backup_open_tables_state(&backup);
- ret= db_find_event(thd, spn, &definer, &et, NULL, thd->mem_root);
+ ret= db_find_event(thd, etn, &et, thd->mem_root);
thd->restore_backup_open_tables_state(&backup);
if (!ret && et)
{
+ CHARSET_INFO *scs= system_charset_info;
Protocol *protocol= thd->protocol;
char show_str_buf[768];
- String show_str(show_str_buf, sizeof(show_str_buf), system_charset_info);
+ String show_str(show_str_buf, sizeof(show_str_buf), scs);
List<Item> field_list;
byte *sql_mode_str;
ulong sql_mode_len=0;
show_str.length(0);
- show_str.set_charset(system_charset_info);
+ show_str.set_charset(scs);
if (et->get_create_event(thd, &show_str))
DBUG_RETURN(1);
@@ -1413,11 +1403,11 @@ evex_show_create_event(THD *thd, sp_name
DBUG_RETURN(1);
protocol->prepare_for_resend();
- protocol->store(et->name.str, et->name.length, system_charset_info);
-
- protocol->store((char*) sql_mode_str, sql_mode_len, system_charset_info);
+ protocol->store(et->ident.name.str, et->ident.name.length, scs);
- protocol->store(show_str.c_ptr(), show_str.length(), system_charset_info);
+ protocol->store((char*) sql_mode_str, sql_mode_len, scs);
+
+ protocol->store(show_str.c_ptr(), show_str.length(), scs);
ret= protocol->write();
send_eof(thd);
}
@@ -1427,30 +1417,32 @@ evex_show_create_event(THD *thd, sp_name
/*
- evex_drop_db_events - Drops all events in the selected database
-
- thd - Thread
- db - ASCIIZ the name of the database
+ Drops all events in the selected database
- Returns:
- 0 - OK
- 1 - Failed to delete a specific row
- 2 - Got NULL while reading db name from a row
+ SYNOPSIS
+ evex_drop_db_events()
+ thd Thread context
+ db ASCIIZ the name of the database
- Note:
- The algo is the following
+ RETURNS
+ 0 OK
+ 1 Failed to delete a specific row
+ 2 Got NULL while reading db name from a row
+
+ NOTES:
+ The algorithm is the following
1. Go through the in-memory cache, if the scheduler is working
and for every event whose dbname matches the database we drop
check whether is currently in execution:
- - event_timed::can_spawn() returns true -> the event is not
+ - Event_timed::can_spawn() returns true -> the event is not
being executed in a child thread. The reason not to use
- event_timed::is_running() is that the latter shows only if
+ Event_timed::is_running() is that the latter shows only if
it is being executed, which is 99% of the time in the thread
but there are some initiliazations before and after the
anonymous SP is being called. So if we delete in this moment
-=> *boom*, so we have to check whether the thread has been
spawned and can_spawn() is the right method.
- - event_timed::can_spawn() returns false -> being runned ATM
+ - Event_timed::can_spawn() returns false -> being runned ATM
just set the flags so it should drop itself.
*/
@@ -1467,65 +1459,63 @@ evex_drop_db_events(THD *thd, char *db)
DBUG_ENTER("evex_drop_db_events");
DBUG_PRINT("info",("dropping events from %s", db));
+ VOID(pthread_mutex_lock(&LOCK_evex_running));
VOID(pthread_mutex_lock(&LOCK_event_arrays));
if ((ret= evex_open_event_table(thd, TL_WRITE, &table)))
{
sql_print_error("Table mysql.event is damaged.");
VOID(pthread_mutex_unlock(&LOCK_event_arrays));
- DBUG_RETURN(SP_OPEN_TABLE_FAILED);
+ DBUG_RETURN(EVEX_OPEN_TABLE_FAILED);
}
- DBUG_PRINT("info",("%d elements in the queue",
- evex_queue_num_elements(EVEX_EQ_NAME)));
- VOID(pthread_mutex_lock(&LOCK_evex_running));
+ DBUG_PRINT("info",("%d elements in the queue", EVEX_EQ_NAME.elements));
if (!evex_is_running)
goto skip_memory;
- for (i= 0; i < evex_queue_num_elements(EVEX_EQ_NAME); ++i)
+ for (i= 0; i < EVEX_EQ_NAME.elements; ++i)
{
- event_timed *et= evex_queue_element(&EVEX_EQ_NAME, i, event_timed*);
- if (sortcmp_lex_string(et->dbname, db_lex, system_charset_info))
+ Event_timed *et= evex_queue_element(&EVEX_EQ_NAME, i, Event_timed*);
+ if (sortcmp_lex_string(et->ident.dbname, db_lex, system_charset_info))
continue;
if (et->can_spawn_now_n_lock(thd))
{
- DBUG_PRINT("info",("event %s not running - direct delete", et->name.str));
- if (!(ret= evex_db_find_event_aux(thd, et, table)))
+ DBUG_PRINT("info",("event %s not running - direct delete",
+ et->ident.name.str));
+ if (!(ret= evex_db_find_event_aux(thd, et->get_ident(), table)))
{
- DBUG_PRINT("info",("event %s found on disk", et->name.str));
+ DBUG_PRINT("info",("event %s found on disk", et->ident.name.str));
if ((ret= table->file->ha_delete_row(table->record[0])))
{
sql_print_error("Error while deleting a row - dropping "
"a database. Skipping the rest.");
- my_error(ER_EVENT_DROP_FAILED, MYF(0), et->name.str);
+ my_error(ER_EVENT_DROP_FAILED, MYF(0), et->ident.name.str);
goto end;
}
DBUG_PRINT("info",("deleted event [%s] num [%d]. Time to free mem",
- et->name.str, i));
+ et->ident.name.str, i));
}
else if (ret == EVEX_KEY_NOT_FOUND)
{
sql_print_error("Expected to find event %s.%s of %s on disk-not there.",
- et->dbname.str, et->name.str, et->definer.str);
+ et->ident.dbname.str, et->ident.name.str,
+ et->ident.definer.str);
}
+ et->spawn_unlock(thd);
et->free_sp();
delete et;
- et= 0;
- /* no need to call et->spawn_unlock because we already cleaned et */
}
else
{
DBUG_PRINT("info",("event %s is running. setting exec_no_more and dropped",
- et->name.str));
+ et->ident.name.str));
et->flags|= EVENT_EXEC_NO_MORE;
et->dropped= TRUE;
}
- DBUG_PRINT("info",("%d elements in the queue",
- evex_queue_num_elements(EVEX_EQ_NAME)));
- evex_queue_delete_element(&EVEX_EQ_NAME, i);// 0 is top
- DBUG_PRINT("info",("%d elements in the queue",
- evex_queue_num_elements(EVEX_EQ_NAME)));
+ DBUG_PRINT("info",("%d elements in the queue", EVEX_EQ_NAME.elements));
+ evex_queue_delete_element(&EVEX_EQ_NAME, i);// 1 is top
+ DBUG_PRINT("info",("%d elements in the queue", EVEX_EQ_NAME.elements));
/*
decrease so we start at the same position, there will be
less elements in the queue, it will still be ordered so on
@@ -1561,7 +1551,7 @@ skip_memory:
LEX_STRING et_db_lex= {et_db, strlen(et_db)};
if (!sortcmp_lex_string(et_db_lex, db_lex, system_charset_info))
{
- event_timed ett;
+ Event_timed ett;
char *ptr;
if ((ptr= get_field(thd->mem_root, table->field[EVEX_FIELD_STATUS]))
@@ -1584,10 +1574,10 @@ skip_memory:
*/
if ((evex_is_running && ptr[0] == 'D') || !evex_is_running)
{
- DBUG_PRINT("info", ("Dropping %s.%s", et_db, ett.name.str));
+ DBUG_PRINT("info", ("Dropping %s.%s", et_db, ett.ident.name.str));
if ((ret= table->file->ha_delete_row(table->record[0])))
{
- my_error(ER_EVENT_DROP_FAILED, MYF(0), ett.name.str);
+ my_error(ER_EVENT_DROP_FAILED, MYF(0), ett.ident.name.str);
goto end;
}
}
@@ -1596,8 +1586,8 @@ skip_memory:
DBUG_PRINT("info",("Disk checked for disabled events. Finishing."));
end:
- VOID(pthread_mutex_unlock(&LOCK_evex_running));
VOID(pthread_mutex_unlock(&LOCK_event_arrays));
+ VOID(pthread_mutex_unlock(&LOCK_evex_running));
end_read_record(&read_record_info);
thd->version--; /* Force close to free memory */
--- 1.28/sql/event.h 2006-02-28 16:13:54 +01:00
+++ 1.29/sql/event.h 2006-02-28 16:16:01 +01:00
@@ -186,6 +186,9 @@ public:
TIME starts;
TIME ends;
TIME execute_at;
+ my_bool starts_null;
+ my_bool ends_null;
+ my_bool execute_at_null;
longlong expression;
interval_type interval;
--- 1.36/sql/event_executor.cc 2006-02-28 14:43:41 +01:00
+++ 1.37/sql/event_executor.cc 2006-02-28 17:32:28 +01:00
@@ -17,6 +17,7 @@
#include "event_priv.h"
#include "event.h"
#include "sp.h"
+#include "event_manager.h"
#define WAIT_STATUS_READY 0
#define WAIT_STATUS_EMPTY_QUEUE 1
@@ -55,7 +56,7 @@ static int
evex_load_events_from_db(THD *thd);
bool
-evex_print_warnings(THD *thd, event_timed *et);
+evex_print_warnings(THD *thd, Event_timed *et);
/*
TODO Andrey: Check for command line option whether to start
@@ -108,6 +109,7 @@ evex_init_mutexes()
return;
evex_mutexes_initted= TRUE;
+ pthread_mutex_init(&Event_scheduler_manager::LOCK_manager, MY_MUTEX_INIT_FAST);
pthread_mutex_init(&LOCK_event_arrays, MY_MUTEX_INIT_FAST);
pthread_mutex_init(&LOCK_workers_count, MY_MUTEX_INIT_FAST);
pthread_mutex_init(&LOCK_evex_running, MY_MUTEX_INIT_FAST);
@@ -203,16 +205,21 @@ init_events()
evex_is_running= false;
VOID(pthread_mutex_unlock(&LOCK_evex_running));
- if (event_executor_running_global_var)
+ VOID(pthread_mutex_lock(&LOCK_evex_running));
+ if (event_executor_running_global_var && !evex_is_running)
{
#ifndef DBUG_FAULTY_THR
/* TODO Andrey: Change the error code returned! */
if (pthread_create(&th, &connection_attrib, event_executor_main,(void*)NULL))
- DBUG_RETURN(ER_SLAVE_THREAD);
+ {
+ VOID(pthread_mutex_unlock(&LOCK_evex_running));
+ DBUG_RETURN(1);
+ }
#else
event_executor_main(NULL);
#endif
}
+ VOID(pthread_mutex_unlock(&LOCK_evex_running));
DBUG_RETURN(0);
}
@@ -304,6 +311,9 @@ init_event_thread(THD* thd)
/*
This function waits till the time next event in the queue should be
executed.
+ SYNOPSIS
+ executor_wait_till_next_event_exec()
+ thd THD of the main event thread
Returns
WAIT_STATUS_READY There is an event to be executed right now
@@ -316,9 +326,10 @@ init_event_thread(THD* thd)
static int
executor_wait_till_next_event_exec(THD *thd)
{
- event_timed *et;
+ Event_timed *et;
TIME time_now;
int t2sleep;
+ bool new_top;
DBUG_ENTER("executor_wait_till_next_event_exec");
/*
@@ -326,12 +337,12 @@ executor_wait_till_next_event_exec(THD *
element in the queue.
*/
VOID(pthread_mutex_lock(&LOCK_event_arrays));
- if (!evex_queue_num_elements(EVEX_EQ_NAME))
+ if (!EVEX_EQ_NAME.elements)
{
VOID(pthread_mutex_unlock(&LOCK_event_arrays));
DBUG_RETURN(1);
}
- et= evex_queue_first_element(&EVEX_EQ_NAME, event_timed*);
+ et= evex_queue_first_element(&EVEX_EQ_NAME, Event_timed*);
DBUG_ASSERT(et);
if (et->status == MYSQL_EVENT_DISABLED)
{
@@ -342,7 +353,7 @@ executor_wait_till_next_event_exec(THD *
evex_queue_delete_element(&EVEX_EQ_NAME, 0);// 0 is top, internally 1
VOID(pthread_mutex_unlock(&LOCK_event_arrays));
sql_print_information("Event found disabled, dropping.");
- DBUG_RETURN(1);
+ DBUG_RETURN(WAIT_STATUS_EMPTY_QUEUE);
}
DBUG_PRINT("evex main thread",("computing time to sleep till next exec"));
@@ -353,6 +364,7 @@ executor_wait_till_next_event_exec(THD *
VOID(pthread_mutex_unlock(&LOCK_event_arrays));
DBUG_PRINT("evex main thread",("unlocked LOCK_event_arrays"));
+ t2sleep*=10;
if (t2sleep > 0)
{
/*
@@ -360,11 +372,11 @@ executor_wait_till_next_event_exec(THD *
has been killed, or there is a new candidate
*/
while (t2sleep-- && !thd->killed && event_executor_running_global_var &&
- evex_queue_num_elements(EVEX_EQ_NAME) &&
- (evex_queue_first_element(&EVEX_EQ_NAME, event_timed*) == et))
+ EVEX_EQ_NAME.elements && !et->killed &&
+ (new_top= (et==evex_queue_first_element(&EVEX_EQ_NAME,Event_timed*))))
{
- DBUG_PRINT("evex main thread",("will sleep a bit more"));
- my_sleep(1000000);
+ DBUG_PRINT("evex main thread", ("will sleep a bit more"));
+ my_sleep(100000);
}
}
@@ -400,18 +412,16 @@ event_executor_main(void *arg)
{
THD *thd; /* needs to be first for thread_stack */
uint i=0, j=0;
- my_ulonglong cnt= 0;
+ static my_ulonglong cnt= 0;
TIME time_now;
DBUG_ENTER("event_executor_main");
DBUG_PRINT("event_executor_main", ("EVEX thread started"));
-
- /* init memory root */
- init_alloc_root(&evex_mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
-
- /* needs to call my_thread_init(), otherwise we get a coredump in DBUG_ stuff*/
- my_thread_init();
+ VOID(pthread_mutex_lock(&LOCK_evex_running));
+ if (evex_is_running)
+ UNLOCK_MUTEX_AND_BAIL_OUT(LOCK_evex_running, err_no_thd);
+ VOID(pthread_mutex_unlock(&LOCK_evex_running));
if (sizeof(my_time_t) != sizeof(time_t))
{
@@ -427,8 +437,16 @@ event_executor_main(void *arg)
sql_print_error("SCHEDULER: Cannot create THD for the main thread.");
goto err_no_thd;
}
- thd->thread_stack = (char*)&thd; // remember where our stack is
+ /* init memory root */
+ init_alloc_root(&evex_mem_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
+
+ /* needs to call my_thread_init(), otherwise we get a coreDUMB in DBUG_ stuff*/
+ my_thread_init();
+
+ /* remember where our stack is */
+ thd->thread_stack = (char*)&thd;
+
pthread_detach_this_thread();
if (init_event_thread(thd))
@@ -456,11 +474,16 @@ event_executor_main(void *arg)
VOID(pthread_mutex_lock(&LOCK_event_arrays));
evex_queue_init(&EVEX_EQ_NAME);
VOID(pthread_mutex_unlock(&LOCK_event_arrays));
+ if (evex_is_running)
+ UNLOCK_MUTEX_AND_BAIL_OUT(LOCK_evex_running, finish);
evex_is_running= true;
VOID(pthread_mutex_unlock(&LOCK_evex_running));
thd->security_ctx->user= my_strdup("event_scheduler", MYF(0));
+ if (!event_executor_running_global_var)
+ goto finish;
+
if (evex_load_events_from_db(thd))
goto finish;
@@ -470,8 +493,8 @@ event_executor_main(void *arg)
while (!thd->killed)
{
TIME time_now;
- event_timed *et;
-
+ Event_timed *et;
+
cnt++;
DBUG_PRINT("info", ("EVEX External Loop %d thd->k", cnt));
@@ -482,9 +505,9 @@ event_executor_main(void *arg)
break;
}
- if (!evex_queue_num_elements(EVEX_EQ_NAME))
+ if (!EVEX_EQ_NAME.elements)
{
- my_sleep(1000000);// sleep 1s
+ my_sleep(100000);// sleep 0.1s
continue;
}
@@ -513,13 +536,13 @@ restart_ticking:
thd->end_time();
my_tz_UTC->gmt_sec_to_TIME(&time_now, thd->query_start());
- if (!evex_queue_num_elements(EVEX_EQ_NAME))
+ if (!EVEX_EQ_NAME.elements)
{
VOID(pthread_mutex_unlock(&LOCK_event_arrays));
DBUG_PRINT("evex main thread",("empty queue"));
continue;
}
- et= evex_queue_first_element(&EVEX_EQ_NAME, event_timed*);
+ et= evex_queue_first_element(&EVEX_EQ_NAME, Event_timed*);
DBUG_PRINT("evex main thread",("got event from the queue"));
if (!et->execute_at_null && my_time_compare(&time_now,&et->execute_at) == -1)
@@ -534,17 +557,17 @@ restart_ticking:
{
int fork_ret_code;
- DBUG_PRINT("evex main thread", ("[%10s] this exec at [%llu]", et->name.str,
+ DBUG_PRINT("evex main thread", ("[%10s] this exec at [%llu]", et->ident.name.str,
TIME_to_ulonglong_datetime(&et->execute_at)));
et->mark_last_executed(thd);
if (et->compute_next_execution_time())
{
sql_print_error("SCHEDULER: Error while computing time of %s.%s . "
"Disabling after execution.",
- et->dbname.str, et->name.str);
+ et->ident.dbname.str, et->ident.name.str);
et->status= MYSQL_EVENT_DISABLED;
}
- DBUG_PRINT("evex main thread", ("[%10s] next exec at [%llu]", et->name.str,
+ DBUG_PRINT("evex main thread", ("[%10s] next exec at [%llu]", et->ident.name.str,
TIME_to_ulonglong_datetime(&et->execute_at)));
et->update_fields(thd);
@@ -555,11 +578,6 @@ restart_ticking:
thread_safe_decrement(workers_count, &LOCK_workers_count);
sql_print_error("SCHEDULER: Problem while trying to create a thread");
UNLOCK_MUTEX_AND_BAIL_OUT(LOCK_event_arrays, finish);
- case EVENT_EXEC_ALREADY_EXEC:
- thread_safe_decrement(workers_count, &LOCK_workers_count);
- sql_print_information("SCHEDULER: %s.%s in execution. Skip this time.",
- et->dbname.str, et->name.str);
- break;
default:
DBUG_ASSERT(!fork_ret_code);
if (fork_ret_code)
@@ -588,10 +606,6 @@ finish:
/* First manifest that this thread does not work and then destroy */
VOID(pthread_mutex_lock(&LOCK_evex_running));
- evex_is_running= false;
- evex_main_thread_id= 0;
- VOID(pthread_mutex_unlock(&LOCK_evex_running));
-
/*
TODO: A better will be with a conditional variable
@@ -604,6 +618,7 @@ finish:
while (1)
{
VOID(pthread_mutex_lock(&LOCK_workers_count));
+ DBUG_PRINT("info", ("workers count %d", workers_count));
if (!workers_count)
{
VOID(pthread_mutex_unlock(&LOCK_workers_count));
@@ -619,9 +634,9 @@ finish:
*/
sql_print_information("SCHEDULER: Emptying the queue.");
VOID(pthread_mutex_lock(&LOCK_event_arrays));
- for (i= 0; i < evex_queue_num_elements(EVEX_EQ_NAME); ++i)
+ for (i= 0; i < EVEX_EQ_NAME.elements; ++i)
{
- event_timed *et= evex_queue_element(&EVEX_EQ_NAME, i, event_timed*);
+ Event_timed *et= evex_queue_element(&EVEX_EQ_NAME, i, Event_timed*);
et->free_sp();
delete et;
}
@@ -644,12 +659,13 @@ finish:
pthread_mutex_unlock(&LOCK_thread_count);
-err_no_thd:
- VOID(pthread_mutex_lock(&LOCK_evex_running));
- evex_is_running= false;
+ free_root(&evex_mem_root, MYF(0));
+ evex_is_running= false;
+ evex_main_thread_id= 0;
VOID(pthread_mutex_unlock(&LOCK_evex_running));
+err_no_thd:
- free_root(&evex_mem_root, MYF(0));
+ event_executor_running_global_var= false;
sql_print_information("SCHEDULER: Stopped.");
#ifndef DBUG_FAULTY_THR
@@ -673,7 +689,7 @@ pthread_handler_t
event_executor_worker(void *event_void)
{
THD *thd; /* needs to be first for thread_stack */
- event_timed *event = (event_timed *) event_void;
+ Event_timed *event = (Event_timed *) event_void;
MEM_ROOT worker_mem_root;
DBUG_ENTER("event_executor_worker");
@@ -712,24 +728,33 @@ event_executor_worker(void *event_void)
{
int ret;
+ if (!event->can_spawn_now_n_lock(thd))
+ {
+ sql_print_information("SCHEDULER: %s.%s in execution. Skip this time.",
+ event->ident.dbname.str, event->ident.name.str);
+ goto err;
+ }
+
sql_print_information("SCHEDULER: Executing event %s.%s of %s [EXPR:%d]",
- event->dbname.str, event->name.str,
- event->definer.str, (int) event->expression);
+ event->ident.dbname.str, event->ident.name.str,
+ event->ident.definer.str, (int) event->expression);
ret= event->execute(thd, &worker_mem_root);
evex_print_warnings(thd, event);
sql_print_information("SCHEDULER: Executed event %s.%s of %s [EXPR:%d]. "
- "RetCode=%d", event->dbname.str, event->name.str,
- event->definer.str, (int) event->expression, ret);
+ "RetCode=%d", event->ident.dbname.str,
+ event->ident.name.str, event->ident.definer.str,
+ (int) event->expression, ret);
if (ret == EVEX_COMPILE_ERROR)
sql_print_information("SCHEDULER: COMPILE ERROR for event %s.%s of",
- event->dbname.str, event->name.str,
- event->definer.str);
+ event->ident.dbname.str, event->ident.name.str,
+ event->ident.definer.str);
else if (ret == EVEX_MICROSECOND_UNSUP)
sql_print_information("SCHEDULER: MICROSECOND is not supported");
+
+ event->spawn_thread_finish(thd);
}
- event->spawn_thread_finish(thd);
err:
@@ -808,8 +833,8 @@ evex_load_events_from_db(THD *thd)
init_read_record(&read_record_info, thd, table ,NULL,1,0);
while (!(read_record_info.read_record(&read_record_info)))
{
- event_timed *et;
- if (!(et= new event_timed))
+ Event_timed *et;
+ if (!(et= new Event_timed))
{
DBUG_PRINT("evex_load_events_from_db", ("Out of memory"));
ret= -1;
@@ -825,13 +850,15 @@ evex_load_events_from_db(THD *thd)
}
if (et->status != MYSQL_EVENT_ENABLED)
{
- DBUG_PRINT("evex_load_events_from_db",("%s is disabled",et->name.str));
+ DBUG_PRINT("evex_load_events_from_db", ("%s.%s of %s is disabled",
+ et->ident.dbname.str, et->ident.name.str,
+ et->ident.definer.str));
delete et;
continue;
}
-
- DBUG_PRINT("evex_load_events_from_db",
- ("Event %s loaded from row. Time to compile", et->name.str));
+
+ DBUG_PRINT("evex_load_events_from_db", ("Event %s.%s loaded from row. "
+ "Time to compile", et->ident.dbname.str, et->ident.name.str));
switch (ret= et->compile(thd, &evex_mem_root)) {
case EVEX_MICROSECOND_UNSUP:
@@ -840,7 +867,7 @@ evex_load_events_from_db(THD *thd)
goto end;
case EVEX_COMPILE_ERROR:
sql_print_error("SCHEDULER: Error while compiling %s.%s. Aborting load.",
- et->dbname.str, et->name.str);
+ et->ident.dbname.str, et->ident.name.str);
goto end;
default:
break;
@@ -850,7 +877,7 @@ evex_load_events_from_db(THD *thd)
if (et->compute_next_execution_time())
{
sql_print_error("SCHEDULER: Error while computing execution time of %s.%s."
- " Skipping", et->dbname.str, et->name.str);
+ " Skipping", et->ident.dbname.str, et->ident.name.str);
continue;
}
@@ -858,7 +885,7 @@ evex_load_events_from_db(THD *thd)
evex_queue_insert(&EVEX_EQ_NAME, (EVEX_PTOQEL) et);
DBUG_PRINT("evex_load_events_from_db", ("%p %*s",
- et, et->name.length,et->name.str));
+ et, et->ident.name.length, et->ident.name.str));
count++;
}
@@ -897,9 +924,12 @@ end:
bool
sys_var_event_executor::update(THD *thd, set_var *var)
{
+ bool wait= false;
/* here start the thread if not running. */
DBUG_ENTER("sys_var_event_executor::update");
VOID(pthread_mutex_lock(&LOCK_evex_running));
+ wait= (*value && !var->save_result.ulong_value);
+
*value= var->save_result.ulong_value;
DBUG_PRINT("new_value", ("%d", *value));
@@ -909,7 +939,8 @@ sys_var_event_executor::update(THD *thd,
init_events();
} else
VOID(pthread_mutex_unlock(&LOCK_evex_running));
-
+ if (wait)
+ my_sleep(200000);
DBUG_RETURN(0);
}
@@ -941,8 +972,8 @@ static sql_print_xxx_func sql_print_xxx_
*/
bool
-evex_print_warnings(THD *thd, event_timed *et)
-{
+evex_print_warnings(THD *thd, Event_timed *et)
+{
MYSQL_ERROR *err;
DBUG_ENTER("evex_show_warnings");
char msg_buf[1024];
@@ -964,9 +995,10 @@ evex_print_warnings(THD *thd, event_time
prefix.append('@');
append_identifier(thd,&prefix,et->definer_host.str,et->definer_host.length);
prefix.append("][", 2);
- append_identifier(thd,&prefix, et->dbname.str, et->dbname.length);
+ append_identifier(thd,&prefix, et->ident.dbname.str,
+ et->ident.dbname.length);
prefix.append('.');
- append_identifier(thd,&prefix, et->name.str, et->name.length);
+ append_identifier(thd, &prefix, et->ident.name.str, et->ident.name.length);
prefix.append("] ", 2);
}
--- 1.42/sql/event_timed.cc 2006-02-28 16:13:55 +01:00
+++ 1.43/sql/event_timed.cc 2006-02-28 17:32:28 +01:00
@@ -87,6 +87,7 @@ Event_timed::init()
set_zero_time(&ends, MYSQL_TIMESTAMP_DATETIME);
set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME);
set_zero_time(&last_executed, MYSQL_TIMESTAMP_DATETIME);
+ starts_null= ends_null= execute_at_null= TRUE;
comment.str= body.str= definer_user.str= definer_host.str= NULL;
comment.length= body.length= definer_user.length= definer_host.length= 0;
@@ -171,7 +172,7 @@ Event_timed::init_body(THD *thd)
body_begin, thd->lex->ptr));
body.length= thd->lex->ptr - body_begin;
- // Trim nuls at the end
+ /* Trim nuls at the end */
while (body.length && body_begin[body.length-1] == '\0')
body.length--;
@@ -213,12 +214,16 @@ Event_timed::init_execute_at(THD *thd, I
if (expr->fix_fields(thd, &expr))
DBUG_RETURN(EVEX_PARSE_ERROR);
-
- /* Let's check whether time is in the past */
- thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp,
+
+ /* no starts and/or ends in case of execute_at */
+ DBUG_PRINT("info", ("starts_null && ends_null should be 1 is %d",
+ (starts_null && ends_null)));
+ DBUG_ASSERT(starts_null && ends_null);
+
+ /* let's check whether time is in the past */
+ thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp,
(my_time_t) thd->query_start());
-
if ((not_used= expr->get_date(<ime, TIME_NO_ZERO_DATE)))
DBUG_RETURN(ER_WRONG_VALUE);
@@ -233,7 +238,7 @@ Event_timed::init_execute_at(THD *thd, I
*/
my_tz_UTC->gmt_sec_to_TIME(<ime, TIME_to_timestamp(thd,<ime, ¬_used));
-
+ execute_at_null= FALSE;
execute_at= ltime;
DBUG_RETURN(0);
}
@@ -302,14 +307,14 @@ Event_timed::init_interval(THD *thd, Ite
case INTERVAL_DAY_MINUTE:
expression= (interval.day* 24 + interval.hour) * 60 + interval.minute;
break;
- case INTERVAL_HOUR_SECOND: // day is anyway 0
+ case INTERVAL_HOUR_SECOND: /* day is anyway 0 */
case INTERVAL_DAY_SECOND:
/* DAY_SECOND having problems because of leap seconds? */
expression= ((interval.day* 24 + interval.hour) * 60 + interval.minute)*60
+ interval.second;
break;
- case INTERVAL_MINUTE_MICROSECOND: // day and hour are 0
- case INTERVAL_HOUR_MICROSECOND:// day is anyway 0
+ case INTERVAL_MINUTE_MICROSECOND: /* day and hour are 0 */
+ case INTERVAL_HOUR_MICROSECOND: /* day is anyway 0 */
case INTERVAL_DAY_MICROSECOND:
DBUG_RETURN(EVEX_MICROSECOND_UNSUP);
expression= ((((interval.day*24) + interval.hour)*60+interval.minute)*60 +
@@ -388,6 +393,7 @@ Event_timed::init_starts(THD *thd, Item
my_tz_UTC->gmt_sec_to_TIME(<ime, TIME_to_timestamp(thd, <ime, ¬_used));
starts= ltime;
+ starts_null= FALSE;
DBUG_RETURN(0);
}
@@ -417,8 +423,7 @@ Event_timed::init_starts(THD *thd, Item
int
Event_timed::init_ends(THD *thd, Item *new_ends)
{
- TIME ltime;
- my_time_t my_time_tmp;
+ TIME ltime, ltime_now;
my_bool not_used;
DBUG_ENTER("Event_timed::init_ends");
@@ -426,20 +431,34 @@ Event_timed::init_ends(THD *thd, Item *n
if (new_ends->fix_fields(thd, &new_ends))
DBUG_RETURN(EVEX_PARSE_ERROR);
- /* The field was already fixed in init_ends */
+ DBUG_PRINT("info", ("convert to TIME"));
if ((not_used= new_ends->get_date(<ime, TIME_NO_ZERO_DATE)))
DBUG_RETURN(EVEX_BAD_PARAMS);
/*
- This may result in a 1970-01-01 date if ltime is > 2037-xx-xx.
- CONVERT_TZ has similar problem.
+ This may result in a 1970-01-01 date if ltime is > 2037-xx-xx ?
+ CONVERT_TZ has similar problem ?
*/
+ DBUG_PRINT("info", ("get the UTC time"));
my_tz_UTC->gmt_sec_to_TIME(<ime, TIME_to_timestamp(thd, <ime, ¬_used));
- if (starts.year && my_time_compare(&starts, <ime) != -1)
+ /* Check whether ends is after starts */
+ DBUG_PRINT("info", ("ENDS after STARTS?"));
+ if (!starts_null && my_time_compare(&starts, <ime) != -1)
+ DBUG_RETURN(EVEX_BAD_PARAMS);
+
+ /*
+ The parser forces starts to be provided but one day STARTS could be
+ set before NOW() and in this case the following check should be done.
+ Check whether ENDS is not in the past.
+ */
+ DBUG_PRINT("info", ("ENDS after NOW?"));
+ my_tz_UTC->gmt_sec_to_TIME(<ime_now, thd->query_start());
+ if (my_time_compare(<ime_now, <ime) == 1)
DBUG_RETURN(EVEX_BAD_PARAMS);
ends= ltime;
+ ends_null= FALSE;
DBUG_RETURN(0);
}
@@ -459,7 +478,7 @@ Event_timed::init_comment(THD *thd, LEX_
DBUG_ENTER("Event_timed::init_comment");
comment.str= strmake_root(thd->mem_root, set_comment->str,
- comment.length= set_comment->length);
+ comment.length= set_comment->length);
DBUG_VOID_RETURN;
}
@@ -533,29 +552,38 @@ Event_timed::load_from_row(MEM_ROOT *mem
len= et->ident.definer.length - len - 1; //1 is because of @
et->definer_host.str= strmake_root(mem_root, ptr + 1, len);//1: because of @
et->definer_host.length= len;
+
+ et->starts_null= table->field[EVEX_FIELD_STARTS]->is_null();
+ res1= table->field[EVEX_FIELD_STARTS]->get_date(&et->starts,TIME_NO_ZERO_DATE);
- res1= table->field[EVEX_FIELD_STARTS]->
- get_date(&et->starts, TIME_NO_ZERO_DATE);
-
- res2= table->field[EVEX_FIELD_ENDS]->
- get_date(&et->ends, TIME_NO_ZERO_DATE);
-
- et->expression= table->field[EVEX_FIELD_INTERVAL_EXPR]->val_int();
-
+ et->ends_null= table->field[EVEX_FIELD_ENDS]->is_null();
+ res2= table->field[EVEX_FIELD_ENDS]->get_date(&et->ends, TIME_NO_ZERO_DATE);
+
+ if (!table->field[EVEX_FIELD_INTERVAL_EXPR]->is_null())
+ et->expression= table->field[EVEX_FIELD_INTERVAL_EXPR]->val_int();
+ else
+ et->expression= 0;
/*
If res1 and res2 are true then both fields are empty.
Hence if EVEX_FIELD_EXECUTE_AT is empty there is an error.
*/
- if (res1 && res2 && !et->expression && table->field[EVEX_FIELD_EXECUTE_AT]->
- get_date(&et->execute_at, TIME_NO_ZERO_DATE))
+ et->execute_at_null= table->field[EVEX_FIELD_EXECUTE_AT]->is_null();
+ DBUG_ASSERT(!(et->starts_null && et->ends_null && !et->expression &&
+ et->execute_at_null));
+ if (!et->expression &&
+ table->field[EVEX_FIELD_EXECUTE_AT]->get_date(&et->execute_at,
+ TIME_NO_ZERO_DATE))
goto error;
/*
In DB the values start from 1 but enum interval_type starts
from 0
*/
- et->interval= (interval_type)
+ if (!table->field[EVEX_FIELD_TRANSIENT_INTERVAL]->is_null())
+ et->interval= (interval_type)
((ulonglong) table->field[EVEX_FIELD_TRANSIENT_INTERVAL]->val_int() - 1);
+ else
+ et->interval= (interval_type) 0;
et->modified= table->field[EVEX_FIELD_CREATED]->val_int();
et->created= table->field[EVEX_FIELD_MODIFIED]->val_int();
@@ -584,20 +612,20 @@ Event_timed::load_from_row(MEM_ROOT *mem
#endif
last_executed_changed= false;
- // ToDo : Andrey . Find a way not to allocate ptr on event_mem_root
+ /* ToDo : Andrey . Find a way not to allocate ptr on event_mem_root */
if ((ptr= get_field(mem_root, table->field[EVEX_FIELD_STATUS])) == NullS)
goto error;
DBUG_PRINT("load_from_row", ("Event [%s] is [%s]", et->ident.name.str, ptr));
et->status= (ptr[0]=='E'? MYSQL_EVENT_ENABLED:MYSQL_EVENT_DISABLED);
- // ToDo : Andrey . Find a way not to allocate ptr on event_mem_root
+ /* ToDo : Andrey . Find a way not to allocate ptr on event_mem_root */
if ((ptr= get_field(mem_root,
table->field[EVEX_FIELD_ON_COMPLETION])) == NullS)
goto error;
et->on_completion= (ptr[0]=='D'? MYSQL_EVENT_ON_COMPLETION_DROP:
- MYSQL_EVENT_ON_COMPLETION_PRESERVE);
+ MYSQL_EVENT_ON_COMPLETION_PRESERVE);
et->comment.str= get_field(mem_root, table->field[EVEX_FIELD_COMMENT]);
if (et->comment.str != NullS)
@@ -744,11 +772,12 @@ Event_timed::compute_next_execution_time
last_executed.second);
#endif
- /* If time_now is after ends don't execute anymore */
- if (ends.year && (tmp= my_time_compare(&ends, &time_now)) == -1)
+ /* if time_now is after ends don't execute anymore */
+ if (!ends_null && (tmp= my_time_compare(&ends, &time_now)) == -1)
{
/* time_now is after ends. don't execute anymore */
set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME);
+ execute_at_null= TRUE;
if (on_completion == MYSQL_EVENT_ON_COMPLETION_DROP)
dropped= true;
status= MYSQL_EVENT_DISABLED;
@@ -762,7 +791,7 @@ Event_timed::compute_next_execution_time
Let's check whether time_now is before starts.
If so schedule for starts.
*/
- if (starts.year && (tmp= my_time_compare(&time_now, &starts)) < 1)
+ if (!starts_null && (tmp= my_time_compare(&time_now, &starts)) < 1)
{
if (tmp == 0 && my_time_compare(&starts, &last_executed) == 0)
{
@@ -778,11 +807,12 @@ Event_timed::compute_next_execution_time
time_now before starts. Scheduling for starts
*/
execute_at= starts;
+ execute_at_null= FALSE;
goto ret;
}
}
- if (starts.year && ends.year)
+ if (!starts_null && !ends_null)
{
/*
Both starts and m_ends are set and time_now is between them (incl.)
@@ -791,7 +821,10 @@ Event_timed::compute_next_execution_time
If not set then schedule for now.
*/
if (!last_executed.year)
+ {
execute_at= time_now;
+ execute_at_null= FALSE;
+ }
else
{
TIME next_exec;
@@ -804,15 +837,19 @@ Event_timed::compute_next_execution_time
{
/* Next execution after ends. No more executions */
set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME);
+ execute_at_null= TRUE;
if (on_completion == MYSQL_EVENT_ON_COMPLETION_DROP)
dropped= true;
}
else
+ {
execute_at= next_exec;
+ execute_at_null= FALSE;
+ }
}
goto ret;
}
- else if (!starts.year && !ends.year)
+ else if (starts_null && ends_null)
{
/*
Both starts and m_ends are not set, so we schedule for the next
@@ -828,11 +865,12 @@ Event_timed::compute_next_execution_time
/* last_executed not set. Schedule the event for now */
execute_at= time_now;
}
+ execute_at_null= FALSE;
}
else
{
- /* Either starts or m_ends is set */
- if (starts.year)
+ /* either starts or m_ends is set */
+ if (!starts_null)
{
/*
- starts is set.
@@ -847,6 +885,7 @@ Event_timed::compute_next_execution_time
}
else
execute_at= starts;
+ execute_at_null= FALSE;
}
else
{
@@ -869,11 +908,15 @@ Event_timed::compute_next_execution_time
if (my_time_compare(&ends, &next_exec) == -1)
{
set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME);
+ execute_at_null= TRUE;
if (on_completion == MYSQL_EVENT_ON_COMPLETION_DROP)
dropped= true;
}
else
+ {
execute_at= next_exec;
+ execute_at_null= FALSE;
+ }
}
}
goto ret;
@@ -903,7 +946,7 @@ Event_timed::mark_last_executed(THD *thd
thd->end_time();
my_tz_UTC->gmt_sec_to_TIME(&time_now, (my_time_t) thd->query_start());
- last_executed= time_now; // was execute_at
+ last_executed= time_now; /* was execute_at */
#ifdef ANDREY_0
last_executed= execute_at;
#endif
@@ -1059,7 +1102,7 @@ Event_timed::get_create_event(THD *thd,
}
else
{
- char dtime_buff[20*2+32];// +32 to make my_snprintf_{8bit|ucs2} happy
+ char dtime_buff[20*2+32];/* +32 to make my_snprintf_{8bit|ucs2} happy */
buf->append(STRING_WITH_LEN("AT '"));
/*
Pass the buffer and the second param tells fills the buffer and
@@ -1129,7 +1172,6 @@ Event_timed::execute(THD *thd, MEM_ROOT
if (!sphead && (ret= compile(thd, mem_root)))
goto done;
-
/* Now we are sure we have valid this->sphead so we can copy the context */
sphead->m_security_ctx= security_ctx;
thd->db= my_strdup(ident.dbname.str, MYF(0));
@@ -1171,17 +1213,15 @@ done:
/*
Switches the security context
-
Synopsis
Event_timed::change_security_context()
thd Thread
backup -Where to store the old context
RETURN
- 0 OK
- 1 Error (generates error too)
+ 0 - OK
+ 1 - Error (generates error too)
*/
-
bool
Event_timed::change_security_context(THD *thd, Security_context *s_ctx,
Security_context **backup)
@@ -1192,7 +1232,7 @@ Event_timed::change_security_context(THD
s_ctx->init();
*backup= 0;
if (acl_getroot_no_password(s_ctx, definer_user.str, definer_host.str,
- definer_host.str, ident.dbname.str))
+ definer_host.str, ident.dbname.str))
{
my_error(ER_NO_SUCH_USER, MYF(0), definer_user.str, definer_host.str);
DBUG_RETURN(TRUE);
@@ -1206,7 +1246,6 @@ Event_timed::change_security_context(THD
/*
Restores the security context
-
Synopsis
Event_timed::restore_security_context()
thd - thread
@@ -1334,7 +1373,6 @@ Event_timed::compile(THD *thd, MEM_ROOT
sphead->m_db= ident.dbname;
/*
Ccopy also chistics since they will vanish otherwise we get 0x0 pointer
- TODO: Handle sql_mode!!
*/
sphead->set_definer(ident.definer.str, ident.definer.length);
sphead->set_info(0, 0, &lex.sp_chistics, sql_mode);
@@ -1371,14 +1409,13 @@ done:
use ::can_spawn_now() only for basic checking because a race
condition may occur between the check and eventual modification (deletion)
of the object.
-
SYNOPSIS
Event_timed::can_spawn_now_n_lock()
thd Thread
- RETURNS
- true Locked
- false Cannot lock
+ Returns
+ true - locked
+ false - cannot lock
*/
bool
--- 1.86/mysql-test/t/disabled.def 2006-02-27 15:07:05 +01:00
+++ 1.87/mysql-test/t/disabled.def 2006-02-28 16:16:01 +01:00
@@ -10,9 +10,9 @@
#
##############################################################################
#ndb_alter_table_row : sometimes wrong error 1015!=1046
-events_bugs : test case unstable (race conditions). andrey will fix
-events_stress : test case unstable. andrey will fix
-events : test case unstable. andrey will fix
+#events_bugs : test case unstable (race conditions). andrey will fix
+#events_stress : test case unstable. andrey will fix
+#events : test case unstable. andrey will fix
ndb_autodiscover : Needs to be fixed w.r.t binlog
ndb_autodiscover2 : Needs to be fixed w.r.t binlog
ndb_binlog_basic : Results are not deterministic, Tomas will fix
| Thread |
|---|
| • bk commit into 5.1 tree (andrey:1.2200) | ahristov | 28 Feb |