1
0
mirror of https://github.com/MariaDB/server.git synced 2025-07-30 16:24:05 +03:00

WL#3337 (Event scheduler new architecture)

More small fixes to the API : use LEX_STRING instead of LEX_STRING* and if error
then return bool(true) instead of error code.
Merged functions. Reduced usage of sp_name.
Fixed a lot of function documentation errors.
Added function documentation wherever needed.
Removed some unused defines and error codes.

Next to come is batch rename of Event_scheduler_ng to Event_scheduler.
This commit is contained in:
andrey@lmy004.
2006-07-11 18:28:15 +02:00
parent 2f7555b308
commit 0d517461f0
15 changed files with 531 additions and 568 deletions

View File

@ -182,12 +182,10 @@ Event_parse_data::init_body(THD *thd)
SYNOPSIS
Event_parse_data::init_definer()
RETURN VALUE
0 OK
thd Thread
*/
int
void
Event_parse_data::init_definer(THD *thd)
{
int definer_user_len;
@ -216,22 +214,20 @@ Event_parse_data::init_definer(THD *thd)
definer.str[definer.length]= '\0';
DBUG_PRINT("info",("definer [%s] initted", definer.str));
DBUG_RETURN(0);
DBUG_VOID_RETURN;
}
/*
Set time for execution for one time events.
Sets time for execution for one-time event.
SYNOPSIS
Event_parse_data::init_execute_at()
expr when (datetime)
thd Thread
RETURN VALUE
0 OK
EVEX_PARSE_ERROR fix_fields failed
EVEX_BAD_PARAMS datetime is in the past
ER_WRONG_VALUE wrong value for execute at
0 OK
ER_WRONG_VALUE Wrong value for execute at (reported)
*/
int
@ -293,18 +289,16 @@ wrong_value:
/*
Set time for execution for transient events.
Sets time for execution of multi-time event.s
SYNOPSIS
Event_parse_data::init_interval()
expr how much?
new_interval what is the interval
thd Thread
RETURN VALUE
0 OK
EVEX_PARSE_ERROR fix_fields failed (reported)
EVEX_BAD_PARAMS Interval is not positive (reported)
EVEX_MICROSECOND_UNSUP Microseconds are not supported (reported)
0 OK
EVEX_BAD_PARAMS Interval is not positive or MICROSECOND (reported)
ER_WRONG_VALUE Wrong value for interval (reported)
*/
int
@ -402,12 +396,11 @@ wrong_value:
/*
Sets activation time.
Sets STARTS.
SYNOPSIS
Event_parse_data::init_starts()
expr how much?
interval what is the interval
NOTES
Note that activation time is not execution time.
@ -418,9 +411,8 @@ wrong_value:
same time.
RETURN VALUE
0 OK
EVEX_PARSE_ERROR fix_fields failed
EVEX_BAD_PARAMS starts before now
0 OK
ER_WRONG_VALUE Starts before now
*/
int
@ -471,12 +463,11 @@ wrong_value:
/*
Sets deactivation time.
Sets ENDS (deactivation time).
SYNOPSIS
Event_parse_data::init_ends()
thd THD
new_ends When?
NOTES
Note that activation time is not execution time.
@ -566,7 +557,7 @@ Event_parse_data::report_bad_value(const char *item_name, Item *bad_item)
/*
Performs checking of the data gathered during the parsing phase.
Checks for validity the data gathered during the parsing phase.
SYNOPSIS
Event_parse_data::check_parse_data()
@ -594,6 +585,7 @@ Event_parse_data::check_parse_data(THD *thd)
DBUG_RETURN(ret);
}
/*
Constructor
@ -769,11 +761,8 @@ Event_timed::init()
{
DBUG_ENTER("Event_timed::init");
body.str= comment.str= NULL;
body.length= comment.length= 0;
definer_user.str= definer_host.str= 0;
definer_user.length= definer_host.length= 0;
definer_user.str= definer_host.str= body.str= comment.str= NULL;
definer_user.length= definer_host.length= body.length= comment.length= 0;
sql_mode= 0;
@ -880,7 +869,7 @@ Event_queue_element::load_from_row(TABLE *table)
expression= 0;
/*
If res1 and res2 are TRUE then both fields are empty.
Hence if ET_FIELD_EXECUTE_AT is empty there is an error.
Hence, if ET_FIELD_EXECUTE_AT is empty there is an error.
*/
execute_at_null= table->field[ET_FIELD_EXECUTE_AT]->is_null();
DBUG_ASSERT(!(starts_null && ends_null && !expression && execute_at_null));
@ -1440,8 +1429,8 @@ Event_queue_element::drop(THD *thd)
uint tmp= 0;
DBUG_ENTER("Event_queue_element::drop");
DBUG_RETURN(Events::get_instance()->drop_event(thd, dbname, name, FALSE,
&tmp, TRUE));
DBUG_RETURN(Events::get_instance()->
drop_event(thd, dbname, name, FALSE, &tmp, TRUE));
}
@ -1453,20 +1442,17 @@ Event_queue_element::drop(THD *thd)
thd - thread context
RETURN VALUE
0 OK
EVEX_OPEN_TABLE_FAILED Error while opening mysql.event for writing
EVEX_WRITE_ROW_FAILED On error to write to disk
others return code from SE in case deletion of the event
row failed.
FALSE OK
TRUE Error while opening mysql.event for writing or during write on disk
*/
bool
Event_queue_element::update_timing_fields(THD *thd)
{
TABLE *table;
Field **fields;
Open_tables_state backup;
int ret;
int ret= FALSE;
DBUG_ENTER("Event_queue_element::update_timing_fields");
@ -1480,12 +1466,12 @@ Event_queue_element::update_timing_fields(THD *thd)
if (Events::get_instance()->open_event_table(thd, TL_WRITE, &table))
{
ret= EVEX_OPEN_TABLE_FAILED;
ret= TRUE;
goto done;
}
fields= table->field;
if ((ret= Events::get_instance()->db_repository->
find_event_by_name(thd, dbname, name, table)))
find_named_event(thd, dbname, name, table)))
goto done;
store_record(table,record[1]);
@ -1494,20 +1480,20 @@ Event_queue_element::update_timing_fields(THD *thd)
if (last_executed_changed)
{
table->field[ET_FIELD_LAST_EXECUTED]->set_notnull();
table->field[ET_FIELD_LAST_EXECUTED]->store_time(&last_executed,
fields[ET_FIELD_LAST_EXECUTED]->set_notnull();
fields[ET_FIELD_LAST_EXECUTED]->store_time(&last_executed,
MYSQL_TIMESTAMP_DATETIME);
last_executed_changed= FALSE;
}
if (status_changed)
{
table->field[ET_FIELD_STATUS]->set_notnull();
table->field[ET_FIELD_STATUS]->store((longlong)status, TRUE);
fields[ET_FIELD_STATUS]->set_notnull();
fields[ET_FIELD_STATUS]->store((longlong)status, TRUE);
status_changed= FALSE;
}
if ((table->file->ha_update_row(table->record[1],table->record[0])))
ret= EVEX_WRITE_ROW_FAILED;
if ((table->file->ha_update_row(table->record[1], table->record[0])))
ret= TRUE;
done:
close_thread_tables(thd);
@ -1550,10 +1536,9 @@ Event_timed::get_create_event(THD *thd, String *buf)
buf->append(STRING_WITH_LEN("CREATE EVENT "));
append_identifier(thd, buf, name.str, name.length);
buf->append(STRING_WITH_LEN(" ON SCHEDULE "));
if (expression)
{
buf->append(STRING_WITH_LEN("EVERY "));
buf->append(STRING_WITH_LEN(" ON SCHEDULE EVERY "));
buf->append(expr_buf);
buf->append(' ');
LEX_STRING *ival= &interval_type_to_name[interval];
@ -1562,7 +1547,7 @@ Event_timed::get_create_event(THD *thd, String *buf)
else
{
char dtime_buff[20*2+32];/* +32 to make my_snprintf_{8bit|ucs2} happy */
buf->append(STRING_WITH_LEN("AT '"));
buf->append(STRING_WITH_LEN(" ON SCHEDULE AT '"));
/*
Pass the buffer and the second param tells fills the buffer and
returns the number of chars to copy.
@ -1612,7 +1597,7 @@ int
Event_job_data::get_fake_create_event(THD *thd, String *buf)
{
DBUG_ENTER("Event_job_data::get_create_event");
buf->append(STRING_WITH_LEN("CREATE EVENT test.anonymous ON SCHEDULE "
buf->append(STRING_WITH_LEN("CREATE EVENT anonymous ON SCHEDULE "
"EVERY 3337 HOUR DO "));
buf->append(body.str, body.length);
@ -1620,81 +1605,6 @@ Event_job_data::get_fake_create_event(THD *thd, String *buf)
}
/*
Executes the event (the underlying sp_head object);
SYNOPSIS
Event_job_data::execute()
thd THD
mem_root If != NULL use it to compile the event on it
RETURN VALUE
0 success
-99 No rights on this.dbname.str
-100 event in execution (parallel execution is impossible)
others retcodes of sp_head::execute_procedure()
*/
int
Event_job_data::execute(THD *thd, MEM_ROOT *mem_root)
{
Security_context *save_ctx;
/* this one is local and not needed after exec */
Security_context security_ctx;
int ret= 0;
DBUG_ENTER("Event_job_data::execute");
DBUG_PRINT("info", ("EXECUTING %s.%s", dbname.str, name.str));
thd->change_security_context(definer_user, definer_host, dbname,
&security_ctx, &save_ctx);
if (!sphead && (ret= compile(thd, mem_root)))
goto done;
/*
THD::~THD will clean this or if there is DROP DATABASE in the SP then
it will be free there. It should not point to our buffer which is allocated
on a mem_root.
*/
thd->db= my_strdup(dbname.str, MYF(0));
thd->db_length= dbname.length;
if (!check_access(thd, EVENT_ACL,dbname.str, 0, 0, 0,is_schema_db(dbname.str)))
{
List<Item> empty_item_list;
empty_item_list.empty();
if (thd->enable_slow_log)
sphead->m_flags|= sp_head::LOG_SLOW_STATEMENTS;
sphead->m_flags|= sp_head::LOG_GENERAL_LOG;
ret= sphead->execute_procedure(thd, &empty_item_list);
}
else
{
DBUG_PRINT("error", ("%s@%s has no rights on %s", definer_user.str,
definer_host.str, dbname.str));
ret= -99;
}
/* Will compile every time a new sp_head on different root */
free_sp();
done:
thd->restore_security_context(save_ctx);
/*
1. Don't cache sphead if allocated on another mem_root
2. Don't call security_ctx.destroy() because this will free our dbname.str
name.str and definer.str
*/
if (mem_root && sphead)
{
delete sphead;
sphead= 0;
}
DBUG_PRINT("info", ("EXECUTED %s.%s ret=%d", dbname.str, name.str, ret));
DBUG_RETURN(ret);
}
/*
Frees the memory of the sp_head object we hold
SYNOPSIS
@ -1816,7 +1726,6 @@ Event_job_data::compile(THD *thd, MEM_ROOT *mem_root)
DBUG_PRINT("note", ("success compiling %s.%s", dbname.str, name.str));
sphead= lex.sphead;
sphead->m_db= dbname;
sphead->set_definer(definer.str, definer.length);
sphead->set_info(0, 0, &lex.sp_chistics, sql_mode);
@ -1847,11 +1756,77 @@ done:
}
/*
Executes the event (the underlying sp_head object);
SYNOPSIS
Event_job_data::execute()
thd THD
RETURN VALUE
0 success
-99 No rights on this.dbname.str
others retcodes of sp_head::execute_procedure()
*/
int
Event_job_data::execute(THD *thd)
{
Security_context *save_ctx;
/* this one is local and not needed after exec */
Security_context security_ctx;
int ret= 0;
DBUG_ENTER("Event_job_data::execute");
DBUG_PRINT("info", ("EXECUTING %s.%s", dbname.str, name.str));
if ((ret= compile(thd, NULL)))
goto done;
thd->change_security_context(definer_user, definer_host, dbname,
&security_ctx, &save_ctx);
/*
THD::~THD will clean this or if there is DROP DATABASE in the SP then
it will be free there. It should not point to our buffer which is allocated
on a mem_root.
*/
thd->db= my_strdup(dbname.str, MYF(0));
thd->db_length= dbname.length;
if (!check_access(thd, EVENT_ACL,dbname.str, 0, 0, 0,is_schema_db(dbname.str)))
{
List<Item> empty_item_list;
empty_item_list.empty();
if (thd->enable_slow_log)
sphead->m_flags|= sp_head::LOG_SLOW_STATEMENTS;
sphead->m_flags|= sp_head::LOG_GENERAL_LOG;
ret= sphead->execute_procedure(thd, &empty_item_list);
}
else
{
DBUG_PRINT("error", ("%s@%s has no rights on %s", definer_user.str,
definer_host.str, dbname.str));
ret= -99;
}
thd->restore_security_context(save_ctx);
done:
free_sp();
DBUG_PRINT("info", ("EXECUTED %s.%s ret=%d", dbname.str, name.str, ret));
DBUG_RETURN(ret);
}
/*
Checks whether two events are in the same schema
SYNOPSIS
event_basic_db_equal()
db Schema
et Compare et->dbname to `db`
RETURN VALUE
TRUE Equal
@ -1859,9 +1834,9 @@ done:
*/
bool
event_basic_db_equal(LEX_STRING *db, Event_basic *et)
event_basic_db_equal(LEX_STRING db, Event_basic *et)
{
return !sortcmp_lex_string(et->dbname, *db, system_charset_info);
return !sortcmp_lex_string(et->dbname, db, system_charset_info);
}