summaryrefslogtreecommitdiff
path: root/sql/event_timed.cc
diff options
context:
space:
mode:
authorunknown <andrey@lmy004.>2006-02-14 16:20:48 +0100
committerunknown <andrey@lmy004.>2006-02-14 16:20:48 +0100
commit8d4f74be2d9b00e435fb22475414a0a68729092f (patch)
tree04e5e29db6b8ea8d6c0e1d15cd7a8aa20ec2bcb2 /sql/event_timed.cc
parent80c60741c0ba9c78bb9370ef72d2b9b7cb01d9e2 (diff)
downloadmariadb-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.cc159
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;