diff options
author | unknown <andrey@lmy004.> | 2006-02-14 16:20:48 +0100 |
---|---|---|
committer | unknown <andrey@lmy004.> | 2006-02-14 16:20:48 +0100 |
commit | 8d4f74be2d9b00e435fb22475414a0a68729092f (patch) | |
tree | 04e5e29db6b8ea8d6c0e1d15cd7a8aa20ec2bcb2 /sql/event_timed.cc | |
parent | 80c60741c0ba9c78bb9370ef72d2b9b7cb01d9e2 (diff) | |
download | mariadb-git-8d4f74be2d9b00e435fb22475414a0a68729092f.tar.gz |
- final fixes for bug#16431 (Events: An event which alters itself disappears)
- fix for bug#16423 (Events: SHOW CREATE EVENT doesn't work)
- this Changeset commits makes CREATE/UPDATE/DELETE EVENT real DDL statements
by committing the currently open transaction before they are executed.
- this Changeset also fixes a trailing space problem since the very early days
of the internal cron
- adds sophisticated checking of whether mysql.event was tampered accidentally
or with purpose by an user.
- adds a lot of inline function documentation - documents everything left
uncodumented
- INTERVAL_XXXX to XXX in I_S.EVENTS.INTERVAL_FIELD
WL#1034 (Internal CRON)
mysql-test/r/events.result:
update result
mysql-test/t/events.test:
add test cases for SHOW CREATE EVENT
add test cases where the structure of mysql.event is changed and error reporting in this case
sql/event.cc:
- do a lot more checking on mysql.event whether it's valid
introduced generic function table_check_intact() which can be used also
for checking whether a system table (mysql.*) has been tampered by user
and report an error in this case. The checking is quite strict, thus
maybe some mechanism can be added later that loosens this like some
session variable, for instance, i_am_aware_that_i_can_damage_my_data
so the table will be opened nevertheless we think that it's not valid.
- add evex_show_create_event(THD *thd, sp_name *spn, LEX_STRING definer)
- document a loooot. not a single function left undocumented.
sql/event.h:
- add evex_show_create_event(THD *thd, sp_name *spn, LEX_STRING definer)
- change get_show_create_event() to get_create_event()
- add TABLE_FIELD_W_TYPE used by table_check_intact()
- add event_timed::sql_mode so it can be used by show create event. currently
always 0, will be fixed by a patch for another bug. At least makes the code
of show create event complete.
sql/event_executor.cc:
- add evex_check_system_tables() that checks on boot and event
main thread startup that mysql.db and mysql.user tables are correct.
- document everything!
sql/event_priv.h:
remove a line
sql/event_timed.cc:
- implement SHOW CREATE EVENT
- document undocumented functions!
sql/share/errmsg.txt:
- fix an error message and add two new
sql/sql_acl.cc:
- add mysql.db table definition to use by table_check_intact()
- exchange some of the positions by numbers from mysql.db to enum names (see sql_acl.h)
sql/sql_acl.h:
- define the structure of mysql.db table
sql/sql_parse.cc:
- handle SQLCOM_SHOW_CREATE_EVENT
- end the current transaction becase CREATE/UPDATE/DELETE EVENT is a DDL
statement
sql/sql_show.cc:
- remove interval_type_to_name
- use common function event_reconstruct_interval_expression()
that reconstructs the expression given at create/alter, to some
extent - interval of 2:62 MINUTE_SECOND will be reconstructed as
interval of 3:02 MINUTE_SECOND!
sql/sql_yacc.yy:
init the definer of event_timed also when doing SHOW CREATE EVENT
because it's needed for checking into mysql.event
sql/table.cc:
- remove stale code. only mysql.event should be a 'system_table'
- add table_check_intact() to check the consistency of a table.
mostly usable with mysql.xxx tables.
sql/table.h:
- export TABLE_FIELD_W_TYPE and table_check_intact() which are used for
checking the structure of a table. mostly usable for mysql.xxx tables.
Diffstat (limited to 'sql/event_timed.cc')
-rw-r--r-- | sql/event_timed.cc | 159 |
1 files changed, 122 insertions, 37 deletions
diff --git a/sql/event_timed.cc b/sql/event_timed.cc index 28d21089b74..3b98d66497b 100644 --- a/sql/event_timed.cc +++ b/sql/event_timed.cc @@ -116,7 +116,10 @@ event_timed::init_body(THD *thd) while (body.length && body_begin[body.length-1] == '\0') body.length--; - body.str= strmake_root(root, (char *)body_begin, body.length); + //the first is always space which I cannot skip in the parser + DBUG_ASSERT(*body_begin == ' '); + body.length--; + body.str= strmake_root(root, (char *)body_begin + 1, body.length); DBUG_VOID_RETURN; } @@ -847,6 +850,15 @@ err: } +/* + Set the internal last_executed TIME struct to now. NOW is the + time according to thd->query_start(), so the THD's clock. + + Synopsis + event_timed::drop() + thd - thread context +*/ + void event_timed::mark_last_executed(THD *thd) { @@ -864,7 +876,13 @@ event_timed::mark_last_executed(THD *thd) /* - Returns : + Drops the event + + Synopsis + event_timed::drop() + thd - thread context + + RETURNS : 0 - OK -1 - Cannot open mysql.event -2 - Cannot find the event in mysql.event (already deleted?) @@ -894,6 +912,22 @@ event_timed::drop(THD *thd) } +/* + Saves status and last_executed_at to the disk if changed. + + Synopsis + event_timed::drop() + thd - thread context + + Returns : + 0 - OK + SP_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. +*/ + bool event_timed::update_fields(THD *thd) { @@ -951,40 +985,75 @@ done: } -char * -event_timed::get_show_create_event(THD *thd, uint32 *length) +/* + Get SHOW CREATE EVENT as string + + thd - Thread + buf - String*, should be already allocated. CREATE EVENT goes inside. + + Returns: + 0 - OK + 1 - Error (for now if mysql.event has been tampered and MICROSECONDS + interval or derivative has been put there. +*/ + +int +event_timed::get_create_event(THD *thd, String *buf) { - char *dst, *ret; - uint len, tmp_len; - DBUG_ENTER("get_show_create_event"); + int multipl= 0; + char tmp_buff[128]; + String expr_buf(tmp_buff, sizeof(tmp_buff), system_charset_info); + expr_buf.length(0); + + DBUG_ENTER("get_create_event"); DBUG_PRINT("ret_info",("body_len=[%d]body=[%s]", body.length, body.str)); - len = strlen("CREATE EVENT `") + dbname.length + strlen("`.`") + name.length + - strlen("` ON SCHEDULE EVERY 5 MINUTE DO ") + body.length;// + strlen(";"); - - ret= dst= (char*) alloc_root(thd->mem_root, len + 1); - memcpy(dst, "CREATE EVENT `", tmp_len= strlen("CREATE EVENT `")); - dst+= tmp_len; - memcpy(dst, dbname.str, tmp_len=dbname.length); - dst+= tmp_len; - memcpy(dst, "`.`", tmp_len= strlen("`.`")); - dst+= tmp_len; - memcpy(dst, name.str, tmp_len= name.length); - dst+= tmp_len; - memcpy(dst, "` ON SCHEDULE EVERY 5 MINUTE DO ", - tmp_len= strlen("` ON SCHEDULE EVERY 5 MINUTE DO ")); - dst+= tmp_len; - - memcpy(dst, body.str, tmp_len= body.length); - dst+= tmp_len; -// memcpy(dst, ";", 1); -// ++dst; - *dst= '\0'; - - *length= len; - - DBUG_PRINT("ret_info",("len=%d",*length)); - DBUG_RETURN(ret); + if (expression && + event_reconstruct_interval_expression(&expr_buf, interval, expression)) + DBUG_RETURN(1); + + buf->append(STRING_WITH_LEN("CREATE EVENT ")); + append_identifier(thd, buf, dbname.str, dbname.length); + buf->append(STRING_WITH_LEN(".")); + 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(expr_buf); + } + else + { + 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 returns + the number of chars to copy + */ + buf->append(dtime_buff, my_datetime_to_str(&execute_at, dtime_buff)); + buf->append(STRING_WITH_LEN("'")); + } + + if (on_completion == MYSQL_EVENT_ON_COMPLETION_DROP) + buf->append(STRING_WITH_LEN(" ON COMPLETION NOT PRESERVE ")); + else + buf->append(STRING_WITH_LEN(" ON COMPLETION PRESERVE ")); + + if (status == MYSQL_EVENT_ENABLED) + buf->append(STRING_WITH_LEN("ENABLE")); + else + buf->append(STRING_WITH_LEN("DISABLE")); + + if (comment.length) + { + buf->append(STRING_WITH_LEN(" COMMENT ")); + append_unescaped(buf, comment.str, comment.length); + } + buf->append(STRING_WITH_LEN(" DO ")); + buf->append(body.str, body.length); + + DBUG_RETURN(0); } @@ -1045,13 +1114,21 @@ done: /* + Compiles an event before it's execution. Compiles the anonymous + sp_head object held by the event + + Synopsis + event_timed::compile() + thd - thread context, used for memory allocation mostly + mem_root - if != NULL then this memory root is used for allocs + instead of thd->mem_root + Returns 0 - Success EVEX_COMPILE_ERROR - Error during compilation */ - int event_timed::compile(THD *thd, MEM_ROOT *mem_root) { @@ -1064,9 +1141,13 @@ event_timed::compile(THD *thd, MEM_ROOT *mem_root) char *old_query; uint old_query_len; st_sp_chistics *p; - CHARSET_INFO *old_character_set_client, *old_collation_connection, + char create_buf[2048]; + String show_create(create_buf, sizeof(create_buf), system_charset_info); + CHARSET_INFO *old_character_set_client, + *old_collation_connection, *old_character_set_results; - + + show_create.length(0); old_character_set_client= thd->variables.character_set_client; old_character_set_results= thd->variables.character_set_results; old_collation_connection= thd->variables.collation_connection; @@ -1089,7 +1170,11 @@ event_timed::compile(THD *thd, MEM_ROOT *mem_root) old_query= thd->query; old_db= thd->db; thd->db= dbname.str; - thd->query= get_show_create_event(thd, &thd->query_length); + + get_create_event(thd, &show_create); + + thd->query= show_create.c_ptr(); + thd->query_length= show_create.length(); DBUG_PRINT("event_timed::compile", ("query:%s",thd->query)); thd->lex= &lex; |