From 1d1e9d10b6fa27c433e71c5270818ea81e8f72ea Mon Sep 17 00:00:00 2001 From: "andrey@lmy004." <> Date: Thu, 8 Jun 2006 23:07:11 +0200 Subject: [PATCH 01/16] Reorganize, physically the events code Unify method naming -> create/update/drop_event Move class Event_timed to event_timed.h class Events is in events.h (renamed from event.h) The implementation is in events.cc (renamed from event.h) --- .bzrignore | 1 + include/my_time.h | 2 +- libmysqld/CMakeLists.txt | 2 +- libmysqld/Makefile.am | 2 +- sql/CMakeLists.txt | 2 +- sql/Makefile.am | 4 +- sql/event.h | 296 ---------------------------- sql/event_executor.cc | 15 -- sql/event_scheduler.cc | 53 +++-- sql/event_scheduler.h | 11 +- sql/event_timed.cc | 11 +- sql/{event.cc => events.cc} | 99 +--------- sql/events.h | 97 +++++++++ sql/{event_priv.h => events_priv.h} | 9 +- sql/mysql_priv.h | 4 + sql/mysqld.cc | 2 +- sql/sql_db.cc | 2 +- sql/sql_parse.cc | 3 +- sql/sql_show.cc | 3 +- sql/sql_yacc.yy | 2 +- sql/time.cc | 56 ++++++ 21 files changed, 236 insertions(+), 440 deletions(-) delete mode 100644 sql/event.h delete mode 100644 sql/event_executor.cc rename sql/{event.cc => events.cc} (93%) create mode 100644 sql/events.h rename sql/{event_priv.h => events_priv.h} (95%) diff --git a/.bzrignore b/.bzrignore index 57fcbdd8f73..fd3f52b9a57 100644 --- a/.bzrignore +++ b/.bzrignore @@ -1771,3 +1771,4 @@ vio/viotest.cpp zlib/*.ds? zlib/*.vcproj libmysqld/event_scheduler.cc +libmysqld/events.cc diff --git a/include/my_time.h b/include/my_time.h index df500dc501b..3025b98a9c4 100644 --- a/include/my_time.h +++ b/include/my_time.h @@ -104,7 +104,7 @@ enum interval_type INTERVAL_YEAR_MONTH, INTERVAL_DAY_HOUR, INTERVAL_DAY_MINUTE, INTERVAL_DAY_SECOND, INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND, INTERVAL_MINUTE_SECOND, INTERVAL_DAY_MICROSECOND, INTERVAL_HOUR_MICROSECOND, - INTERVAL_MINUTE_MICROSECOND, INTERVAL_SECOND_MICROSECOND + INTERVAL_MINUTE_MICROSECOND, INTERVAL_SECOND_MICROSECOND, INTERVAL_LAST }; C_MODE_END diff --git a/libmysqld/CMakeLists.txt b/libmysqld/CMakeLists.txt index ff8ceda5c5b..69d8b6e0f67 100644 --- a/libmysqld/CMakeLists.txt +++ b/libmysqld/CMakeLists.txt @@ -29,7 +29,7 @@ ADD_LIBRARY(mysqldemb emb_qcache.cc libmysqld.c lib_sql.cc ../libmysql/libmysql.c ../sql/password.c ../sql-common/client.c ../sql-common/my_time.c ../sql-common/my_user.c ../sql-common/pack.c ../sql/derror.cc ../sql/event_executor.cc - ../sql/event_timed.cc ../sql/event.cc ../sql/discover.cc + ../sql/event_timed.cc ../sql/events.cc ../sql/discover.cc ../sql/field_conv.cc ../sql/field.cc ../sql/filesort.cc ../sql/gstream.cc ../sql/ha_heap.cc ../sql/ha_myisam.cc ../sql/ha_myisammrg.cc ${mysql_se_ha_src} diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am index a3af2d43bd5..1e8b84a17d0 100644 --- a/libmysqld/Makefile.am +++ b/libmysqld/Makefile.am @@ -68,7 +68,7 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \ spatial.cc gstream.cc sql_help.cc tztime.cc sql_cursor.cc \ sp_head.cc sp_pcontext.cc sp.cc sp_cache.cc sp_rcontext.cc \ parse_file.cc sql_view.cc sql_trigger.cc my_decimal.cc \ - event_scheduler.cc event.cc event_timed.cc \ + event_scheduler.cc events.cc event_timed.cc \ rpl_filter.cc sql_partition.cc sql_builtin.cc sql_plugin.cc \ sql_tablespace.cc \ rpl_injector.cc my_user.c partition_info.cc diff --git a/sql/CMakeLists.txt b/sql/CMakeLists.txt index 2b44fbdcc79..d80a51bb829 100644 --- a/sql/CMakeLists.txt +++ b/sql/CMakeLists.txt @@ -52,7 +52,7 @@ ADD_EXECUTABLE(mysqld ../sql-common/client.c derror.cc des_key_file.cc sql_update.cc sql_view.cc strfunc.cc table.cc thr_malloc.cc time.cc tztime.cc uniques.cc unireg.cc item_xmlfunc.cc rpl_tblmap.cc sql_binlog.cc event_scheduler.cc event_timed.cc - sql_tablespace.cc event.cc ../sql-common/my_user.c + sql_tablespace.cc events.cc ../sql-common/my_user.c partition_info.cc ${PROJECT_SOURCE_DIR}/sql/sql_yacc.cc ${PROJECT_SOURCE_DIR}/sql/sql_yacc.h diff --git a/sql/Makefile.am b/sql/Makefile.am index 7f711a1e212..689c916fbba 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -64,7 +64,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ tztime.h my_decimal.h\ sp_head.h sp_pcontext.h sp_rcontext.h sp.h sp_cache.h \ parse_file.h sql_view.h sql_trigger.h \ - sql_array.h sql_cursor.h event.h event_priv.h \ + sql_array.h sql_cursor.h events.h events_priv.h \ sql_plugin.h authors.h sql_partition.h \ partition_info.h partition_element.h event_scheduler.h \ contributors.h @@ -104,7 +104,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \ tztime.cc my_time.c my_user.c my_decimal.cc\ sp_head.cc sp_pcontext.cc sp_rcontext.cc sp.cc \ sp_cache.cc parse_file.cc sql_trigger.cc \ - event_scheduler.cc event.cc event_timed.cc \ + event_scheduler.cc events.cc event_timed.cc \ sql_plugin.cc sql_binlog.cc \ sql_builtin.cc sql_tablespace.cc partition_info.cc diff --git a/sql/event.h b/sql/event.h deleted file mode 100644 index 02c5fa78150..00000000000 --- a/sql/event.h +++ /dev/null @@ -1,296 +0,0 @@ -#ifndef _EVENT_H_ -#define _EVENT_H_ -/* Copyright (C) 2004-2006 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - - - -#define EVEX_OK 0 -#define EVEX_KEY_NOT_FOUND -1 -#define EVEX_OPEN_TABLE_FAILED -2 -#define EVEX_WRITE_ROW_FAILED -3 -#define EVEX_DELETE_ROW_FAILED -4 -#define EVEX_GET_FIELD_FAILED -5 -#define EVEX_PARSE_ERROR -6 -#define EVEX_INTERNAL_ERROR -7 -#define EVEX_NO_DB_ERROR -8 -#define EVEX_COMPILE_ERROR -19 -#define EVEX_GENERAL_ERROR -20 -#define EVEX_BAD_IDENTIFIER -21 -#define EVEX_BODY_TOO_LONG -22 -#define EVEX_BAD_PARAMS -23 -#define EVEX_NOT_RUNNING -24 -#define EVEX_MICROSECOND_UNSUP -25 -#define EVEX_CANT_KILL -26 - -#define EVENT_EXEC_NO_MORE (1L << 0) -#define EVENT_NOT_USED (1L << 1) -#define EVENT_FREE_WHEN_FINISHED (1L << 2) - -class Event_timed; - -class Events -{ -public: - static ulong opt_event_scheduler; - static TYPELIB opt_typelib; - - enum enum_table_field - { - FIELD_DB = 0, - FIELD_NAME, - FIELD_BODY, - FIELD_DEFINER, - FIELD_EXECUTE_AT, - FIELD_INTERVAL_EXPR, - FIELD_TRANSIENT_INTERVAL, - FIELD_CREATED, - FIELD_MODIFIED, - FIELD_LAST_EXECUTED, - FIELD_STARTS, - FIELD_ENDS, - FIELD_STATUS, - FIELD_ON_COMPLETION, - FIELD_SQL_MODE, - FIELD_COMMENT, - FIELD_COUNT /* a cool trick to count the number of fields :) */ - }; - - static int - create_event(THD *thd, Event_timed *et, uint create_options, - uint *rows_affected); - - static int - update_event(THD *thd, Event_timed *et, sp_name *new_name, - uint *rows_affected); - - static int - drop_event(THD *thd, Event_timed *et, bool drop_if_exists, - uint *rows_affected); - - static int - open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table); - - static int - show_create_event(THD *thd, sp_name *spn); - - static int - reconstruct_interval_expression(String *buf, interval_type interval, - longlong expression); - - static int - drop_schema_events(THD *thd, char *db); - - static int - dump_internal_status(THD *thd); - - static int - init(); - - static void - shutdown(); - - static void - init_mutexes(); - - static void - destroy_mutexes(); - - -private: - /* Prevent use of these */ - Events(const Events &); - void operator=(Events &); -}; - - - -class sp_head; - -class Event_timed -{ - Event_timed(const Event_timed &); /* Prevent use of these */ - void operator=(Event_timed &); - my_bool in_spawned_thread; - ulong locked_by_thread_id; - my_bool running; - ulong thread_id; - pthread_mutex_t LOCK_running; - pthread_cond_t COND_finished; - - bool status_changed; - bool last_executed_changed; - -public: - enum enum_status - { - ENABLED = 1, - DISABLED - }; - - enum enum_on_completion - { - ON_COMPLETION_DROP = 1, - ON_COMPLETION_PRESERVE - }; - - TIME last_executed; - - LEX_STRING dbname; - LEX_STRING name; - LEX_STRING body; - - LEX_STRING definer_user; - LEX_STRING definer_host; - LEX_STRING definer;// combination of user and host - - LEX_STRING comment; - 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; - - ulonglong created; - ulonglong modified; - enum enum_on_completion on_completion; - enum enum_status status; - sp_head *sphead; - ulong sql_mode; - const uchar *body_begin; - - bool dropped; - bool free_sphead_on_delete; - uint flags;//all kind of purposes - - static void *operator new(size_t size) - { - void *p; - DBUG_ENTER("Event_timed::new(size)"); - p= my_malloc(size, MYF(0)); - DBUG_PRINT("info", ("alloc_ptr=0x%lx", p)); - DBUG_RETURN(p); - } - - static void *operator new(size_t size, MEM_ROOT *mem_root) - { return (void*) alloc_root(mem_root, (uint) size); } - - static void operator delete(void *ptr, size_t size) - { - DBUG_ENTER("Event_timed::delete(ptr,size)"); - DBUG_PRINT("enter", ("free_ptr=0x%lx", ptr)); - TRASH(ptr, size); - my_free((gptr) ptr, MYF(0)); - DBUG_VOID_RETURN; - } - - static void operator delete(void *ptr, MEM_ROOT *mem_root) - { - /* - Don't free the memory it will be done by the mem_root but - we need to call the destructor because we free other resources - which are not allocated on the root but on the heap, or we - deinit mutexes. - */ - DBUG_ASSERT(0); - } - - Event_timed(); - - ~Event_timed(); - - void - init(); - - void - deinit_mutexes(); - - int - init_definer(THD *thd); - - int - init_execute_at(THD *thd, Item *expr); - - int - init_interval(THD *thd, Item *expr, interval_type new_interval); - - void - init_name(THD *thd, sp_name *spn); - - int - init_starts(THD *thd, Item *starts); - - int - init_ends(THD *thd, Item *ends); - - void - init_body(THD *thd); - - void - init_comment(THD *thd, LEX_STRING *set_comment); - - int - load_from_row(MEM_ROOT *mem_root, TABLE *table); - - bool - compute_next_execution_time(); - - int - drop(THD *thd); - - void - mark_last_executed(THD *thd); - - bool - update_fields(THD *thd); - - int - get_create_event(THD *thd, String *buf); - - int - execute(THD *thd, MEM_ROOT *mem_root); - - int - compile(THD *thd, MEM_ROOT *mem_root); - - bool - is_running(); - - int - spawn_now(void * (*thread_func)(void*), void *arg); - - bool - spawn_thread_finish(THD *thd); - - void - free_sp(); - - bool - has_equal_db(Event_timed *etn); - - int - kill_thread(THD *thd); - - void - set_thread_id(ulong tid) { thread_id= tid; } -}; - - -#endif /* _EVENT_H_ */ diff --git a/sql/event_executor.cc b/sql/event_executor.cc deleted file mode 100644 index f236fb47771..00000000000 --- a/sql/event_executor.cc +++ /dev/null @@ -1,15 +0,0 @@ -/* Copyright (C) 2004-2005 MySQL AB - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software - Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc index e360254fdd2..10e641dceed 100644 --- a/sql/event_scheduler.cc +++ b/sql/event_scheduler.cc @@ -14,8 +14,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "event_priv.h" -#include "event.h" +#include "mysql_priv.h" +#include "events_priv.h" +#include "events.h" +#include "event_timed.h" #include "event_scheduler.h" #include "sp_head.h" @@ -46,8 +48,8 @@ The scheduler only manages execution of the events. Their creation, alteration and deletion is delegated to other routines found in event.cc . These routines interact with the scheduler : - - CREATE EVENT -> Event_scheduler::add_event() - - ALTER EVENT -> Event_scheduler::replace_event() + - CREATE EVENT -> Event_scheduler::create_event() + - ALTER EVENT -> Event_scheduler::update_event() - DROP EVENT -> Event_scheduler::drop_event() There is one mutex in the single Event_scheduler object which controls @@ -298,6 +300,35 @@ public: }; +/* + Compares the execute_at members of 2 Event_timed instances. + Used as callback for the prioritized queue when shifting + elements inside. + + SYNOPSIS + event_timed_compare_q() + + vptr - not used (set it to NULL) + a - first Event_timed object + b - second Event_timed object + + RETURN VALUE + -1 - a->execute_at < b->execute_at + 0 - a->execute_at == b->execute_at + 1 - a->execute_at > b->execute_at + + NOTES + execute_at.second_part is not considered during comparison +*/ + +static int +event_timed_compare_q(void *vptr, byte* a, byte *b) +{ + return my_time_compare(&((Event_timed *)a)->execute_at, + &((Event_timed *)b)->execute_at); +} + + /* Prints the stack of infos, warnings, errors from thd to the console so it can be fetched by the logs-into-tables and @@ -740,10 +771,10 @@ Event_scheduler::destroy() /* - Adds an event to the scheduler queue + Creates an event in the scheduler queue SYNOPSIS - Event_scheduler::add_event() + Event_scheduler::create_event() et The event to add check_existence Whether to check if already loaded. @@ -753,11 +784,11 @@ Event_scheduler::destroy() */ enum Event_scheduler::enum_error_code -Event_scheduler::add_event(THD *thd, Event_timed *et, bool check_existence) +Event_scheduler::create_event(THD *thd, Event_timed *et, bool check_existence) { enum enum_error_code res; Event_timed *et_new; - DBUG_ENTER("Event_scheduler::add_event"); + DBUG_ENTER("Event_scheduler::create_event"); DBUG_PRINT("enter", ("thd=%p et=%p lock=%p",thd,et,&LOCK_scheduler_data)); LOCK_SCHEDULER_DATA(); @@ -859,7 +890,7 @@ Event_scheduler::drop_event(THD *thd, Event_timed *et) /* - Replaces an event in the scheduler queue + Updates an event from the scheduler queue SYNOPSIS Event_scheduler::replace_event() @@ -873,14 +904,14 @@ Event_scheduler::drop_event(THD *thd, Event_timed *et) */ enum Event_scheduler::enum_error_code -Event_scheduler::replace_event(THD *thd, Event_timed *et, LEX_STRING *new_schema, +Event_scheduler::update_event(THD *thd, Event_timed *et, LEX_STRING *new_schema, LEX_STRING *new_name) { enum enum_error_code res; Event_timed *et_old, *et_new= NULL; LEX_STRING old_schema, old_name; - DBUG_ENTER("Event_scheduler::replace_event"); + DBUG_ENTER("Event_scheduler::update_event"); DBUG_PRINT("enter", ("thd=%p et=%p et=[%s.%s] lock=%p", thd, et, et->dbname.str, et->name.str, &LOCK_scheduler_data)); diff --git a/sql/event_scheduler.h b/sql/event_scheduler.h index dffd47539fa..5ae310bab2a 100644 --- a/sql/event_scheduler.h +++ b/sql/event_scheduler.h @@ -16,6 +16,7 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +class Event_timed; class THD; typedef bool * (*event_timed_identifier_comparator)(Event_timed*, Event_timed*); @@ -26,7 +27,6 @@ events_init(); void events_shutdown(); - class Event_scheduler { public: @@ -66,14 +66,15 @@ public: /* Methods for queue management follow */ enum enum_error_code - add_event(THD *thd, Event_timed *et, bool check_existence); + create_event(THD *thd, Event_timed *et, bool check_existence); + + enum enum_error_code + update_event(THD *thd, Event_timed *et, LEX_STRING *new_schema, + LEX_STRING *new_name); bool drop_event(THD *thd, Event_timed *et); - enum enum_error_code - replace_event(THD *thd, Event_timed *et, LEX_STRING *new_schema, - LEX_STRING *new_name); int drop_schema_events(THD *thd, LEX_STRING *schema); diff --git a/sql/event_timed.cc b/sql/event_timed.cc index d6d6dddf971..4ec875f32a3 100644 --- a/sql/event_timed.cc +++ b/sql/event_timed.cc @@ -15,8 +15,10 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #define MYSQL_LEX 1 -#include "event_priv.h" -#include "event.h" +#include "mysql_priv.h" +#include "events_priv.h" +#include "events.h" +#include "event_timed.h" #include "sp_head.h" @@ -395,6 +397,8 @@ Event_timed::init_interval(THD *thd, Item *expr, interval_type new_interval) break; case INTERVAL_MICROSECOND: DBUG_RETURN(EVEX_MICROSECOND_UNSUP); + case INTERVAL_LAST: + DBUG_ASSERT(0); } if (interval_tmp.neg || expression > EVEX_MAX_INTERVAL_VALUE) DBUG_RETURN(EVEX_BAD_PARAMS); @@ -834,6 +838,8 @@ bool get_next_time(TIME *next, TIME *start, TIME *time_now, TIME *last_exec, */ DBUG_RETURN(1); break; + case INTERVAL_LAST: + DBUG_ASSERT(0); } DBUG_PRINT("info", ("seconds=%ld months=%ld", seconds, months)); if (seconds) @@ -1279,7 +1285,6 @@ done: DBUG_RETURN(ret); } -extern LEX_STRING interval_type_to_name[]; /* Get SHOW CREATE EVENT as string diff --git a/sql/event.cc b/sql/events.cc similarity index 93% rename from sql/event.cc rename to sql/events.cc index 5273394640c..8398bb422f4 100644 --- a/sql/event.cc +++ b/sql/events.cc @@ -14,8 +14,10 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "event_priv.h" -#include "event.h" +#include "mysql_priv.h" +#include "events_priv.h" +#include "events.h" +#include "event_timed.h" #include "event_scheduler.h" #include "sp.h" #include "sp_head.h" @@ -160,35 +162,11 @@ TABLE_FIELD_W_TYPE event_table_fields[Events::FIELD_COUNT] = { }; -LEX_STRING interval_type_to_name[] = { - {(char *) STRING_WITH_LEN("YEAR")}, - {(char *) STRING_WITH_LEN("QUARTER")}, - {(char *) STRING_WITH_LEN("MONTH")}, - {(char *) STRING_WITH_LEN("DAY")}, - {(char *) STRING_WITH_LEN("HOUR")}, - {(char *) STRING_WITH_LEN("MINUTE")}, - {(char *) STRING_WITH_LEN("WEEK")}, - {(char *) STRING_WITH_LEN("SECOND")}, - {(char *) STRING_WITH_LEN("MICROSECOND")}, - {(char *) STRING_WITH_LEN("YEAR_MONTH")}, - {(char *) STRING_WITH_LEN("DAY_HOUR")}, - {(char *) STRING_WITH_LEN("DAY_MINUTE")}, - {(char *) STRING_WITH_LEN("DAY_SECOND")}, - {(char *) STRING_WITH_LEN("HOUR_MINUTE")}, - {(char *) STRING_WITH_LEN("HOUR_SECOND")}, - {(char *) STRING_WITH_LEN("MINUTE_SECOND")}, - {(char *) STRING_WITH_LEN("DAY_MICROSECOND")}, - {(char *) STRING_WITH_LEN("HOUR_MICROSECOND")}, - {(char *) STRING_WITH_LEN("MINUTE_MICROSECOND")}, - {(char *) STRING_WITH_LEN("SECOND_MICROSECOND")} -}; - - /* Compares 2 LEX strings regarding case. SYNOPSIS - my_time_compare() + sortcmp_lex_string() s - first LEX_STRING t - second LEX_STRING @@ -210,68 +188,6 @@ int sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs) } -/* - Compares 2 TIME structures - - SYNOPSIS - my_time_compare() - - a - first TIME - b - second time - - RETURN VALUE - -1 - a < b - 0 - a == b - 1 - a > b - - NOTES - TIME.second_part is not considered during comparison -*/ - -int -my_time_compare(TIME *a, TIME *b) -{ - my_ulonglong a_t= TIME_to_ulonglong_datetime(a); - my_ulonglong b_t= TIME_to_ulonglong_datetime(b); - - if (a_t > b_t) - return 1; - else if (a_t < b_t) - return -1; - - return 0; -} - - -/* - Compares the execute_at members of 2 Event_timed instances. - Used as callback for the prioritized queue when shifting - elements inside. - - SYNOPSIS - event_timed_compare() - - vptr - not used (set it to NULL) - 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 - 1 - a->execute_at > b->execute_at - - Notes - execute_at.second_part is not considered during comparison -*/ - -int -event_timed_compare_q(void *vptr, byte* a, byte *b) -{ - return my_time_compare(&((Event_timed *)a)->execute_at, - &((Event_timed *)b)->execute_at); -} - - /* Reconstructs interval expression from interval type and expression value that is in form of a value of the smalles entity: @@ -999,7 +915,8 @@ Events::create_event(THD *thd, Event_timed *et, uint create_options, rows_affected))) { Event_scheduler *scheduler= Event_scheduler::get_instance(); - if (scheduler->initialized() && (ret= scheduler->add_event(thd, et, true))) + if (scheduler->initialized() && + (ret= scheduler->create_event(thd, et, true))) my_error(ER_EVENT_MODIFY_QUEUE_ERROR, MYF(0), ret); } /* No need to close the table, it will be closed in sql_parse::do_command */ @@ -1044,7 +961,7 @@ Events::update_event(THD *thd, Event_timed *et, sp_name *new_name, { Event_scheduler *scheduler= Event_scheduler::get_instance(); if (scheduler->initialized() && - (ret= scheduler->replace_event(thd, et, + (ret= scheduler->update_event(thd, et, new_name? &new_name->m_db: NULL, new_name? &new_name->m_name: NULL))) my_error(ER_EVENT_MODIFY_QUEUE_ERROR, MYF(0), ret); diff --git a/sql/events.h b/sql/events.h new file mode 100644 index 00000000000..66cce6e7777 --- /dev/null +++ b/sql/events.h @@ -0,0 +1,97 @@ +#ifndef _EVENT_H_ +#define _EVENT_H_ +/* Copyright (C) 2004-2006 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +class Event_timed; + +class Events +{ +public: + static ulong opt_event_scheduler; + static TYPELIB opt_typelib; + + enum enum_table_field + { + FIELD_DB = 0, + FIELD_NAME, + FIELD_BODY, + FIELD_DEFINER, + FIELD_EXECUTE_AT, + FIELD_INTERVAL_EXPR, + FIELD_TRANSIENT_INTERVAL, + FIELD_CREATED, + FIELD_MODIFIED, + FIELD_LAST_EXECUTED, + FIELD_STARTS, + FIELD_ENDS, + FIELD_STATUS, + FIELD_ON_COMPLETION, + FIELD_SQL_MODE, + FIELD_COMMENT, + FIELD_COUNT /* a cool trick to count the number of fields :) */ + }; + + static int + create_event(THD *thd, Event_timed *et, uint create_options, + uint *rows_affected); + + static int + update_event(THD *thd, Event_timed *et, sp_name *new_name, + uint *rows_affected); + + static int + drop_event(THD *thd, Event_timed *et, bool drop_if_exists, + uint *rows_affected); + + static int + open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table); + + static int + show_create_event(THD *thd, sp_name *spn); + + static int + reconstruct_interval_expression(String *buf, interval_type interval, + longlong expression); + + static int + drop_schema_events(THD *thd, char *db); + + static int + dump_internal_status(THD *thd); + + static int + init(); + + static void + shutdown(); + + static void + init_mutexes(); + + static void + destroy_mutexes(); + + +private: + /* Prevent use of these */ + Events(const Events &); + void operator=(Events &); +}; + + +#endif /* _EVENT_H_ */ diff --git a/sql/event_priv.h b/sql/events_priv.h similarity index 95% rename from sql/event_priv.h rename to sql/events_priv.h index 43ef30a659f..ed02cb7055b 100644 --- a/sql/event_priv.h +++ b/sql/events_priv.h @@ -16,9 +16,6 @@ along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "mysql_priv.h" - - #define EVENT_EXEC_STARTED 0 #define EVENT_EXEC_ALREADY_EXEC 1 #define EVENT_EXEC_CANT_FORK 2 @@ -27,17 +24,13 @@ #define EVEX_NAME_FIELD_LEN 64 #define EVEX_MAX_INTERVAL_VALUE 2147483647L -int -my_time_compare(TIME *a, TIME *b); +class Event_timed; int evex_db_find_event_by_name(THD *thd, const LEX_STRING dbname, const LEX_STRING ev_name, TABLE *table); -int -event_timed_compare_q(void *vptr, byte* a, byte *b); - int db_drop_event(THD *thd, Event_timed *et, bool drop_if_exists, uint *rows_affected); diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h index 0fd0c5597d1..7ed361d52b7 100644 --- a/sql/mysql_priv.h +++ b/sql/mysql_priv.h @@ -1739,6 +1739,8 @@ bool date_add_interval(TIME *ltime, interval_type int_type, INTERVAL interval); bool calc_time_diff(TIME *l_time1, TIME *l_time2, int l_sign, longlong *seconds_out, long *microseconds_out); +extern LEX_STRING interval_type_to_name[]; + extern DATE_TIME_FORMAT *date_time_format_make(timestamp_type format_type, const char *format_str, uint format_length); @@ -1754,6 +1756,7 @@ void make_date(const DATE_TIME_FORMAT *format, const TIME *l_time, String *str); void make_time(const DATE_TIME_FORMAT *format, const TIME *l_time, String *str); +int my_time_compare(TIME *a, TIME *b); int test_if_number(char *str,int *res,bool allow_wildcards); void change_byte(byte *,uint,char,char); @@ -1770,6 +1773,7 @@ void filesort_free_buffers(TABLE *table); void change_double_for_sort(double nr,byte *to); double my_double_round(double value, int dec, bool truncate); int get_quick_record(SQL_SELECT *select); + int calc_weekday(long daynr,bool sunday_first_day_of_week); uint calc_week(TIME *l_time, uint week_behaviour, uint *year); void find_date(char *pos,uint *vek,uint flag); diff --git a/sql/mysqld.cc b/sql/mysqld.cc index 42787d67351..52aa8560e99 100644 --- a/sql/mysqld.cc +++ b/sql/mysqld.cc @@ -24,7 +24,7 @@ #include "stacktrace.h" #include "mysqld_suffix.h" #include "mysys_err.h" -#include "event.h" +#include "events.h" #include "ha_myisam.h" diff --git a/sql/sql_db.cc b/sql/sql_db.cc index 6d5362c2554..273ed3a5115 100644 --- a/sql/sql_db.cc +++ b/sql/sql_db.cc @@ -20,7 +20,7 @@ #include "mysql_priv.h" #include #include "sp.h" -#include "event.h" +#include "events.h" #include #include #ifdef __WIN__ diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 3206cfa2d52..491ccece03d 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -26,7 +26,8 @@ #include "sp_head.h" #include "sp.h" #include "sp_cache.h" -#include "event.h" +#include "events.h" +#include "event_timed.h" #ifdef HAVE_OPENSSL /* diff --git a/sql/sql_show.cc b/sql/sql_show.cc index bdf0724ee96..a22c36fffa3 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -26,7 +26,8 @@ #include "sql_trigger.h" #include "authors.h" #include "contributors.h" -#include "event.h" +#include "events.h" +#include "event_timed.h" #include #ifdef WITH_PARTITION_STORAGE_ENGINE diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 82dcc758ff0..b4fe53749cc 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -38,7 +38,7 @@ #include "sp_pcontext.h" #include "sp_rcontext.h" #include "sp.h" -#include "event.h" +#include "event_timed.h" #include #include diff --git a/sql/time.cc b/sql/time.cc index 3c654de23bb..5b12aacf84a 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -24,6 +24,30 @@ /* Some functions to calculate dates */ #ifndef TESTTIME + +LEX_STRING interval_type_to_name[INTERVAL_LAST] = { + {(char *) STRING_WITH_LEN("YEAR")}, + {(char *) STRING_WITH_LEN("QUARTER")}, + {(char *) STRING_WITH_LEN("MONTH")}, + {(char *) STRING_WITH_LEN("DAY")}, + {(char *) STRING_WITH_LEN("HOUR")}, + {(char *) STRING_WITH_LEN("MINUTE")}, + {(char *) STRING_WITH_LEN("WEEK")}, + {(char *) STRING_WITH_LEN("SECOND")}, + {(char *) STRING_WITH_LEN("MICROSECOND")}, + {(char *) STRING_WITH_LEN("YEAR_MONTH")}, + {(char *) STRING_WITH_LEN("DAY_HOUR")}, + {(char *) STRING_WITH_LEN("DAY_MINUTE")}, + {(char *) STRING_WITH_LEN("DAY_SECOND")}, + {(char *) STRING_WITH_LEN("HOUR_MINUTE")}, + {(char *) STRING_WITH_LEN("HOUR_SECOND")}, + {(char *) STRING_WITH_LEN("MINUTE_SECOND")}, + {(char *) STRING_WITH_LEN("DAY_MICROSECOND")}, + {(char *) STRING_WITH_LEN("HOUR_MICROSECOND")}, + {(char *) STRING_WITH_LEN("MINUTE_MICROSECOND")}, + {(char *) STRING_WITH_LEN("SECOND_MICROSECOND")} +}; + /* Calc weekday from daynr */ /* Returns 0 for monday, 1 for tuesday .... */ @@ -909,4 +933,36 @@ calc_time_diff(TIME *l_time1, TIME *l_time2, int l_sign, longlong *seconds_out, } +/* + Compares 2 TIME structures + + SYNOPSIS + my_time_compare() + + a - first TIME + b - second time + + RETURN VALUE + -1 - a < b + 0 - a == b + 1 - a > b + + NOTES + TIME.second_part is not considered during comparison +*/ + +int +my_time_compare(TIME *a, TIME *b) +{ + my_ulonglong a_t= TIME_to_ulonglong_datetime(a); + my_ulonglong b_t= TIME_to_ulonglong_datetime(b); + + if (a_t > b_t) + return 1; + else if (a_t < b_t) + return -1; + + return 0; +} + #endif From 40fe2b9a45b396c7b908ce512b3fc6c373510993 Mon Sep 17 00:00:00 2001 From: "andrey@lmy004." <> Date: Tue, 20 Jun 2006 17:05:41 +0200 Subject: [PATCH 02/16] forgot to event_timed.h STRING_WITH_LEN -> C_STRING_WITH_LEN --- sql/event_timed.h | 217 ++++++++++++++++++++++++++++++++++++++++++++++ sql/time.cc | 42 ++++----- 2 files changed, 238 insertions(+), 21 deletions(-) create mode 100644 sql/event_timed.h diff --git a/sql/event_timed.h b/sql/event_timed.h new file mode 100644 index 00000000000..0652cece361 --- /dev/null +++ b/sql/event_timed.h @@ -0,0 +1,217 @@ +#ifndef _EVENT_TIMED_H_ +#define _EVENT_TIMED_H_ +/* Copyright (C) 2004-2006 MySQL AB + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + + +#define EVEX_OK 0 +#define EVEX_KEY_NOT_FOUND -1 +#define EVEX_OPEN_TABLE_FAILED -2 +#define EVEX_WRITE_ROW_FAILED -3 +#define EVEX_DELETE_ROW_FAILED -4 +#define EVEX_GET_FIELD_FAILED -5 +#define EVEX_PARSE_ERROR -6 +#define EVEX_INTERNAL_ERROR -7 +#define EVEX_NO_DB_ERROR -8 +#define EVEX_COMPILE_ERROR -19 +#define EVEX_GENERAL_ERROR -20 +#define EVEX_BAD_IDENTIFIER -21 +#define EVEX_BODY_TOO_LONG -22 +#define EVEX_BAD_PARAMS -23 +#define EVEX_NOT_RUNNING -24 +#define EVEX_MICROSECOND_UNSUP -25 +#define EVEX_CANT_KILL -26 + +#define EVENT_EXEC_NO_MORE (1L << 0) +#define EVENT_NOT_USED (1L << 1) +#define EVENT_FREE_WHEN_FINISHED (1L << 2) + + +class sp_head; + +class Event_timed +{ + Event_timed(const Event_timed &); /* Prevent use of these */ + void operator=(Event_timed &); + my_bool in_spawned_thread; + ulong locked_by_thread_id; + my_bool running; + ulong thread_id; + pthread_mutex_t LOCK_running; + pthread_cond_t COND_finished; + + bool status_changed; + bool last_executed_changed; + +public: + enum enum_status + { + ENABLED = 1, + DISABLED + }; + + enum enum_on_completion + { + ON_COMPLETION_DROP = 1, + ON_COMPLETION_PRESERVE + }; + + TIME last_executed; + + LEX_STRING dbname; + LEX_STRING name; + LEX_STRING body; + + LEX_STRING definer_user; + LEX_STRING definer_host; + LEX_STRING definer;// combination of user and host + + LEX_STRING comment; + 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; + + ulonglong created; + ulonglong modified; + enum enum_on_completion on_completion; + enum enum_status status; + sp_head *sphead; + ulong sql_mode; + const uchar *body_begin; + + bool dropped; + bool free_sphead_on_delete; + uint flags;//all kind of purposes + + static void *operator new(size_t size) + { + void *p; + DBUG_ENTER("Event_timed::new(size)"); + p= my_malloc(size, MYF(0)); + DBUG_PRINT("info", ("alloc_ptr=0x%lx", p)); + DBUG_RETURN(p); + } + + static void *operator new(size_t size, MEM_ROOT *mem_root) + { return (void*) alloc_root(mem_root, (uint) size); } + + static void operator delete(void *ptr, size_t size) + { + DBUG_ENTER("Event_timed::delete(ptr,size)"); + DBUG_PRINT("enter", ("free_ptr=0x%lx", ptr)); + TRASH(ptr, size); + my_free((gptr) ptr, MYF(0)); + DBUG_VOID_RETURN; + } + + static void operator delete(void *ptr, MEM_ROOT *mem_root) + { + /* + Don't free the memory it will be done by the mem_root but + we need to call the destructor because we free other resources + which are not allocated on the root but on the heap, or we + deinit mutexes. + */ + DBUG_ASSERT(0); + } + + Event_timed(); + + ~Event_timed(); + + void + init(); + + void + deinit_mutexes(); + + int + init_definer(THD *thd); + + int + init_execute_at(THD *thd, Item *expr); + + int + init_interval(THD *thd, Item *expr, interval_type new_interval); + + void + init_name(THD *thd, sp_name *spn); + + int + init_starts(THD *thd, Item *starts); + + int + init_ends(THD *thd, Item *ends); + + void + init_body(THD *thd); + + void + init_comment(THD *thd, LEX_STRING *set_comment); + + int + load_from_row(MEM_ROOT *mem_root, TABLE *table); + + bool + compute_next_execution_time(); + + int + drop(THD *thd); + + void + mark_last_executed(THD *thd); + + bool + update_fields(THD *thd); + + int + get_create_event(THD *thd, String *buf); + + int + execute(THD *thd, MEM_ROOT *mem_root); + + int + compile(THD *thd, MEM_ROOT *mem_root); + + bool + is_running(); + + int + spawn_now(void * (*thread_func)(void*), void *arg); + + bool + spawn_thread_finish(THD *thd); + + void + free_sp(); + + bool + has_equal_db(Event_timed *etn); + + int + kill_thread(THD *thd); + + void + set_thread_id(ulong tid) { thread_id= tid; } +}; + +#endif /* _EVENT_H_ */ diff --git a/sql/time.cc b/sql/time.cc index 5b12aacf84a..b3164818f75 100644 --- a/sql/time.cc +++ b/sql/time.cc @@ -26,26 +26,26 @@ #ifndef TESTTIME LEX_STRING interval_type_to_name[INTERVAL_LAST] = { - {(char *) STRING_WITH_LEN("YEAR")}, - {(char *) STRING_WITH_LEN("QUARTER")}, - {(char *) STRING_WITH_LEN("MONTH")}, - {(char *) STRING_WITH_LEN("DAY")}, - {(char *) STRING_WITH_LEN("HOUR")}, - {(char *) STRING_WITH_LEN("MINUTE")}, - {(char *) STRING_WITH_LEN("WEEK")}, - {(char *) STRING_WITH_LEN("SECOND")}, - {(char *) STRING_WITH_LEN("MICROSECOND")}, - {(char *) STRING_WITH_LEN("YEAR_MONTH")}, - {(char *) STRING_WITH_LEN("DAY_HOUR")}, - {(char *) STRING_WITH_LEN("DAY_MINUTE")}, - {(char *) STRING_WITH_LEN("DAY_SECOND")}, - {(char *) STRING_WITH_LEN("HOUR_MINUTE")}, - {(char *) STRING_WITH_LEN("HOUR_SECOND")}, - {(char *) STRING_WITH_LEN("MINUTE_SECOND")}, - {(char *) STRING_WITH_LEN("DAY_MICROSECOND")}, - {(char *) STRING_WITH_LEN("HOUR_MICROSECOND")}, - {(char *) STRING_WITH_LEN("MINUTE_MICROSECOND")}, - {(char *) STRING_WITH_LEN("SECOND_MICROSECOND")} + { C_STRING_WITH_LEN("YEAR")}, + { C_STRING_WITH_LEN("QUARTER")}, + { C_STRING_WITH_LEN("MONTH")}, + { C_STRING_WITH_LEN("DAY")}, + { C_STRING_WITH_LEN("HOUR")}, + { C_STRING_WITH_LEN("MINUTE")}, + { C_STRING_WITH_LEN("WEEK")}, + { C_STRING_WITH_LEN("SECOND")}, + { C_STRING_WITH_LEN("MICROSECOND")}, + { C_STRING_WITH_LEN("YEAR_MONTH")}, + { C_STRING_WITH_LEN("DAY_HOUR")}, + { C_STRING_WITH_LEN("DAY_MINUTE")}, + { C_STRING_WITH_LEN("DAY_SECOND")}, + { C_STRING_WITH_LEN("HOUR_MINUTE")}, + { C_STRING_WITH_LEN("HOUR_SECOND")}, + { C_STRING_WITH_LEN("MINUTE_SECOND")}, + { C_STRING_WITH_LEN("DAY_MICROSECOND")}, + { C_STRING_WITH_LEN("HOUR_MICROSECOND")}, + { C_STRING_WITH_LEN("MINUTE_MICROSECOND")}, + { C_STRING_WITH_LEN("SECOND_MICROSECOND")} }; /* Calc weekday from daynr */ @@ -939,7 +939,7 @@ calc_time_diff(TIME *l_time1, TIME *l_time2, int l_sign, longlong *seconds_out, SYNOPSIS my_time_compare() - a - first TIME + a - first time b - second time RETURN VALUE From b75254e101459fd472f015e871b228c8c2d350a6 Mon Sep 17 00:00:00 2001 From: "dlenev@mysql.com" <> Date: Wed, 21 Jun 2006 01:50:20 +0400 Subject: [PATCH 03/16] Fix for bug#19634 "Re-execution of multi-delete which involve trigger/stored function crashes server". Attempts to execute prepared multi-delete statement which involved trigger or stored function caused server crashes (the same happened for such statements included in stored procedures in cases when one tried to execute them more than once). The problem was caused by yet another incorrect usage of check_table_access() routine (the latter assumes that table list which it gets as argument corresponds to value LEX::query_tables_own_last). We solve this problem by juggling with LEX::query_tables_own_last value when we call check_table_access() for LEX::auxilliary_table_list (better solution is too intrusive and should be done in 5.1). --- mysql-test/r/sp-prelocking.result | 18 ++++++++++++++ mysql-test/t/sp-prelocking.test | 31 ++++++++++++++++++++++++ sql/sql_parse.cc | 40 +++++++++++++++++++++++++++---- 3 files changed, 85 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/sp-prelocking.result b/mysql-test/r/sp-prelocking.result index 2335513b28a..7d8dd862748 100644 --- a/mysql-test/r/sp-prelocking.result +++ b/mysql-test/r/sp-prelocking.result @@ -237,3 +237,21 @@ deallocate prepare stmt; drop table t1; drop view v1, v2, v3; drop function bug15683; +drop table if exists t1, t2, t3; +drop function if exists bug19634; +create table t1 (id int, data int); +create table t2 (id int); +create table t3 (data int); +create function bug19634() returns int return (select count(*) from t3); +prepare stmt from "delete t1 from t1, t2 where t1.id = t2.id and bug19634()"; +execute stmt; +execute stmt; +deallocate prepare stmt; +create trigger t1_bi before delete on t1 for each row insert into t3 values (old.data); +prepare stmt from "delete t1 from t1, t2 where t1.id = t2.id"; +execute stmt; +execute stmt; +deallocate prepare stmt; +drop function bug19634; +drop table t1, t2, t3; +End of 5.0 tests diff --git a/mysql-test/t/sp-prelocking.test b/mysql-test/t/sp-prelocking.test index a7215462afb..b94de6236d3 100644 --- a/mysql-test/t/sp-prelocking.test +++ b/mysql-test/t/sp-prelocking.test @@ -272,3 +272,34 @@ drop table t1; drop view v1, v2, v3; drop function bug15683; + +# +# Bug#19634 "Re-execution of multi-delete which involve trigger/stored +# function crashes server" +# +--disable_warnings +drop table if exists t1, t2, t3; +drop function if exists bug19634; +--enable_warnings +create table t1 (id int, data int); +create table t2 (id int); +create table t3 (data int); +create function bug19634() returns int return (select count(*) from t3); +prepare stmt from "delete t1 from t1, t2 where t1.id = t2.id and bug19634()"; +# This should not crash server +execute stmt; +execute stmt; +deallocate prepare stmt; + +create trigger t1_bi before delete on t1 for each row insert into t3 values (old.data); +prepare stmt from "delete t1 from t1, t2 where t1.id = t2.id"; + +execute stmt; +execute stmt; +deallocate prepare stmt; + +drop function bug19634; +drop table t1, t2, t3; + + +--echo End of 5.0 tests diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index ba5c2ebf484..7ed96250240 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -5202,8 +5202,26 @@ bool check_global_access(THD *thd, ulong want_access) /* - Check the privilege for all used tables. Table privileges are cached - in the table list for GRANT checking + Check the privilege for all used tables. + + SYNOPSYS + check_table_access() + thd Thread context + want_access Privileges requested + tables List of tables to be checked + no_errors FALSE/TRUE - report/don't report error to + the client (using my_error() call). + + NOTES + Table privileges are cached in the table list for GRANT checking. + This functions assumes that table list used and + thd->lex->query_tables_own_last value correspond to each other + (the latter should be either 0 or point to next_global member + of one of elements of this table list). + + RETURN VALUE + FALSE - OK + TRUE - Access denied */ bool @@ -7068,14 +7086,28 @@ bool multi_delete_precheck(THD *thd, TABLE_LIST *tables) SELECT_LEX *select_lex= &thd->lex->select_lex; TABLE_LIST *aux_tables= (TABLE_LIST *)thd->lex->auxilliary_table_list.first; + TABLE_LIST **save_query_tables_own_last= thd->lex->query_tables_own_last; DBUG_ENTER("multi_delete_precheck"); /* sql_yacc guarantees that tables and aux_tables are not zero */ DBUG_ASSERT(aux_tables != 0); if (check_db_used(thd, tables) || check_db_used(thd,aux_tables) || - check_table_access(thd,SELECT_ACL, tables,0) || - check_table_access(thd,DELETE_ACL, aux_tables,0)) + check_table_access(thd, SELECT_ACL, tables, 0)) DBUG_RETURN(TRUE); + + /* + Since aux_tables list is not part of LEX::query_tables list we + have to juggle with LEX::query_tables_own_last value to be able + call check_table_access() safely. + */ + thd->lex->query_tables_own_last= 0; + if (check_table_access(thd, DELETE_ACL, aux_tables, 0)) + { + thd->lex->query_tables_own_last= save_query_tables_own_last; + DBUG_RETURN(TRUE); + } + thd->lex->query_tables_own_last= save_query_tables_own_last; + if ((thd->options & OPTION_SAFE_UPDATES) && !select_lex->where) { my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE, From cf16c8ec3c198ff7acbd8564cccc89f1e7c794a3 Mon Sep 17 00:00:00 2001 From: "andrey@lmy004." <> Date: Wed, 21 Jun 2006 08:58:56 +0200 Subject: [PATCH 04/16] add event_timed.h also to the distribution --- sql/Makefile.am | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/Makefile.am b/sql/Makefile.am index e3b2447341d..387f18c2ae9 100644 --- a/sql/Makefile.am +++ b/sql/Makefile.am @@ -65,7 +65,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \ sp_head.h sp_pcontext.h sp_rcontext.h sp.h sp_cache.h \ parse_file.h sql_view.h sql_trigger.h \ sql_array.h sql_cursor.h events.h events_priv.h \ - sql_plugin.h authors.h sql_partition.h \ + sql_plugin.h authors.h sql_partition.h event_timed.h \ partition_info.h partition_element.h event_scheduler.h \ contributors.h mysqld_SOURCES = sql_lex.cc sql_handler.cc sql_partition.cc \ From ce8734699b5a965e11221e236c3124a91c324c48 Mon Sep 17 00:00:00 2001 From: "anozdrin@mysql.com" <> Date: Wed, 21 Jun 2006 16:02:51 +0400 Subject: [PATCH 05/16] Fix for BUG#20294: Instance manager test im_instance_conf fails randomly. The problem is that the test was affected by other running test-suites on the same box. The fix affects the test only, no code touched. --- mysql-test/r/im_instance_conf.result | 83 +++++++++++++++++++--------- mysql-test/t/disabled.def | 6 +- mysql-test/t/im_instance_conf.imtest | 46 ++++++++++++--- 3 files changed, 96 insertions(+), 39 deletions(-) diff --git a/mysql-test/r/im_instance_conf.result b/mysql-test/r/im_instance_conf.result index efda9439f38..f68fcca25a3 100644 --- a/mysql-test/r/im_instance_conf.result +++ b/mysql-test/r/im_instance_conf.result @@ -13,7 +13,9 @@ Variable_name Value server_id 1 ---> connection: default -CREATE INSTANCE mysqld3; +CREATE INSTANCE mysqld3 +server_id = 3, +socket = "$MYSQL_TMP_DIR/mysqld_3.sock"; SHOW INSTANCES; instance_name state mysqld3 offline @@ -22,6 +24,7 @@ mysqld1 online -------------------------------------------------------------------- server_id = 1 server_id = 2 +server_id=3 -------------------------------------------------------------------- CREATE INSTANCE mysqld1; ERROR HY000: Instance already exists @@ -32,7 +35,10 @@ ERROR HY000: Instance already exists -------------------------------------------------------------------- nonguarded -------------------------------------------------------------------- -CREATE INSTANCE mysqld4 nonguarded; +CREATE INSTANCE mysqld4 +nonguarded, +server_id = 4, +socket = "$MYSQL_TMP_DIR/mysqld_4.sock"; SHOW INSTANCES; instance_name state mysqld3 offline @@ -46,7 +52,11 @@ nonguarded -------------------------------------------------------------------- -------------------------------------------------------------------- -------------------------------------------------------------------- -CREATE INSTANCE mysqld5 test-A = 000, test-B = test; +CREATE INSTANCE mysqld5 +test-A = 000, +test-B = test, +server_id = 5, +socket = "$MYSQL_TMP_DIR/mysqld_5.sock"; SHOW INSTANCES; instance_name state mysqld1 online @@ -61,7 +71,11 @@ test-B=test -------------------------------------------------------------------- -------------------------------------------------------------------- -------------------------------------------------------------------- -CREATE INSTANCE mysqld6 test-C1 = 10 , test-C2 = 02 ; +CREATE INSTANCE mysqld6 +test-C1 = 10 , +test-C2 = 02 , +server_id = 6, +socket = "$MYSQL_TMP_DIR/mysqld_6.sock"; SHOW INSTANCES; instance_name state mysqld1 online @@ -116,7 +130,11 @@ mysqld4 offline -------------------------------------------------------------------- -------------------------------------------------------------------- -------------------------------------------------------------------- -CREATE INSTANCE mysqld9 test-1=" hello world ", test-2=' '; +CREATE INSTANCE mysqld9 +test-1=" hello world ", +test-2=' ', +server_id = 9, +socket = "$MYSQL_TMP_DIR/mysqld_9.sock"; SHOW INSTANCES; instance_name state mysqld1 online @@ -126,56 +144,67 @@ mysqld6 offline mysqld3 offline mysqld4 offline mysqld9 offline -CREATE INSTANCE mysqld9a test-3='\b\babc\sdef'; +CREATE INSTANCE mysqld10 +test-3='\b\babc\sdef', +server_id = 10, +socket = "$MYSQL_TMP_DIR/mysqld_10.sock"; SHOW INSTANCES; instance_name state mysqld1 online -mysqld9a offline +mysqld9 offline mysqld5 offline mysqld6 offline mysqld3 offline mysqld4 offline -mysqld9 offline +mysqld10 offline mysqld2 offline -CREATE INSTANCE mysqld9b test-4='abc\tdef', test-5='abc\ndef'; +CREATE INSTANCE mysqld11 +test-4='abc\tdef', +test-5='abc\ndef', +server_id = 11, +socket = "$MYSQL_TMP_DIR/mysqld_11.sock"; SHOW INSTANCES; instance_name state -mysqld9b offline -mysqld9a offline +mysqld1 online +mysqld11 offline mysqld5 offline mysqld6 offline mysqld3 offline mysqld4 offline -mysqld9 offline +mysqld10 offline mysqld2 offline -mysqld1 online -CREATE INSTANCE mysqld9c test-6="abc\rdef", test-7="abc\\def"; +mysqld9 offline +CREATE INSTANCE mysqld12 +test-6="abc\rdef", +test-7="abc\\def", +server_id = 12, +socket = "$MYSQL_TMP_DIR/mysqld_12.sock"; SHOW INSTANCES; instance_name state -mysqld9b offline -mysqld6 offline +mysqld1 online +mysqld9 offline mysqld5 offline -mysqld9c offline +mysqld6 offline mysqld3 offline mysqld4 offline -mysqld9 offline +mysqld10 offline mysqld2 offline -mysqld1 online -mysqld9a offline -CREATE INSTANCE mysqld10 test-bad=' \ '; +mysqld12 offline +mysqld11 offline +CREATE INSTANCE mysqld13 test-bad=' \ '; ERROR 42000: You have an error in your command syntax. Check the manual that corresponds to your MySQL Instance Manager version for the right syntax to use SHOW INSTANCES; instance_name state -mysqld9b offline -mysqld6 offline +mysqld1 online +mysqld9 offline mysqld5 offline -mysqld9c offline +mysqld6 offline mysqld3 offline mysqld4 offline -mysqld9 offline +mysqld10 offline mysqld2 offline -mysqld1 online -mysqld9a offline +mysqld12 offline +mysqld11 offline -------------------------------------------------------------------- test-1= hello world -------------------------------------------------------------------- diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 96f31133e65..d0087568b58 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -13,9 +13,9 @@ #events_stress : BUG#17619 2006-02-21 andrey Race conditions #events : BUG#17619 2006-02-21 andrey Race conditions #events_scheduling : BUG#19170 2006-04-26 andrey Test case of 19170 fails on some platforms. Has to be checked. -im_instance_conf : Bug#20294 2006-06-06 monty Instance manager test im_instance_conf fails randomly -im_options : Bug#20294 2006-06-06 monty Instance manager test im_instance_conf fails randomly -im_life_cycle : Bug#20368 2006-06-10 alik im_life_cycle test fails +#im_instance_conf : Bug#20294 2006-06-06 monty Instance manager test im_instance_conf fails randomly +#im_options : Bug#20294 2006-06-06 monty Instance manager test im_instance_conf fails randomly +#im_life_cycle : Bug#20368 2006-06-10 alik im_life_cycle test fails ndb_autodiscover : BUG#18952 2006-02-16 jmiller Needs to be fixed w.r.t binlog ndb_autodiscover2 : BUG#18952 2006-02-16 jmiller Needs to be fixed w.r.t binlog #ndb_binlog_discover : BUG#19395 2006-04-28 tomas/knielsen mysqld does not always detect cluster shutdown diff --git a/mysql-test/t/im_instance_conf.imtest b/mysql-test/t/im_instance_conf.imtest index 17703fdd303..2cd7b955978 100644 --- a/mysql-test/t/im_instance_conf.imtest +++ b/mysql-test/t/im_instance_conf.imtest @@ -69,7 +69,9 @@ SHOW VARIABLES LIKE 'server_id'; # Check that CREATE INSTANCE succeeds for non-existing instance and also check # that both config file and internal configuration cache have been updated. -CREATE INSTANCE mysqld3; +CREATE INSTANCE mysqld3 + server_id = 3, + socket = "$MYSQL_TMP_DIR/mysqld_3.sock"; SHOW INSTANCES; @@ -99,7 +101,10 @@ CREATE INSTANCE mysqld3; --exec grep nonguarded $MYSQLTEST_VARDIR/im.cnf; --echo -------------------------------------------------------------------- -CREATE INSTANCE mysqld4 nonguarded; +CREATE INSTANCE mysqld4 + nonguarded, + server_id = 4, + socket = "$MYSQL_TMP_DIR/mysqld_4.sock"; SHOW INSTANCES; @@ -115,7 +120,11 @@ SHOW INSTANCES; --exec grep test-B $MYSQLTEST_VARDIR/im.cnf || true; --echo -------------------------------------------------------------------- -CREATE INSTANCE mysqld5 test-A = 000, test-B = test; +CREATE INSTANCE mysqld5 + test-A = 000, + test-B = test, + server_id = 5, + socket = "$MYSQL_TMP_DIR/mysqld_5.sock"; SHOW INSTANCES; @@ -135,7 +144,11 @@ SHOW INSTANCES; --exec grep test-C $MYSQLTEST_VARDIR/im.cnf || true; --echo -------------------------------------------------------------------- -CREATE INSTANCE mysqld6 test-C1 = 10 , test-C2 = 02 ; +CREATE INSTANCE mysqld6 + test-C1 = 10 , + test-C2 = 02 , + server_id = 6, + socket = "$MYSQL_TMP_DIR/mysqld_6.sock"; SHOW INSTANCES; @@ -183,22 +196,37 @@ SHOW INSTANCES; --exec grep test-4 $MYSQLTEST_VARDIR/im.cnf || true; --echo -------------------------------------------------------------------- -CREATE INSTANCE mysqld9 test-1=" hello world ", test-2=' '; +CREATE INSTANCE mysqld9 + test-1=" hello world ", + test-2=' ', + server_id = 9, + socket = "$MYSQL_TMP_DIR/mysqld_9.sock"; SHOW INSTANCES; -CREATE INSTANCE mysqld9a test-3='\b\babc\sdef'; +CREATE INSTANCE mysqld10 + test-3='\b\babc\sdef', + server_id = 10, + socket = "$MYSQL_TMP_DIR/mysqld_10.sock"; # test-3='abc def' SHOW INSTANCES; -CREATE INSTANCE mysqld9b test-4='abc\tdef', test-5='abc\ndef'; +CREATE INSTANCE mysqld11 + test-4='abc\tdef', + test-5='abc\ndef', + server_id = 11, + socket = "$MYSQL_TMP_DIR/mysqld_11.sock"; SHOW INSTANCES; -CREATE INSTANCE mysqld9c test-6="abc\rdef", test-7="abc\\def"; +CREATE INSTANCE mysqld12 + test-6="abc\rdef", + test-7="abc\\def", + server_id = 12, + socket = "$MYSQL_TMP_DIR/mysqld_12.sock"; # test-6=abc SHOW INSTANCES; --error ER_SYNTAX_ERROR -CREATE INSTANCE mysqld10 test-bad=' \ '; +CREATE INSTANCE mysqld13 test-bad=' \ '; SHOW INSTANCES; --echo -------------------------------------------------------------------- From c59a58c4ba8a0beecb02a16f4940f67c9e9c6adb Mon Sep 17 00:00:00 2001 From: "andrey@lmy004." <> Date: Thu, 22 Jun 2006 13:01:08 +0200 Subject: [PATCH 06/16] fix for bug#16992 (Events: Information_schema troubles) Introduced EVENTS.EVENT_DEFINITION, like ROUTINES.ROUTINE_DEFINITION Hence, the contents of the current EVENTS.EVENT_BODY become the contents of EVENT_DEFINITION. EVENT_BODY will contain always, for now, "SQL" (wo quotes). --- mysql-test/r/events.result | 12 +-- mysql-test/r/events_grant.result | 78 +++++++++--------- mysql-test/r/information_schema.result | 2 +- mysql-test/t/events.test | 6 +- mysql-test/t/events_grant.test | 18 ++--- sql/sql_show.cc | 105 +++++++++++++++++-------- 6 files changed, 132 insertions(+), 89 deletions(-) diff --git a/mysql-test/r/events.result b/mysql-test/r/events.result index 77280f99b7c..e115e077535 100644 --- a/mysql-test/r/events.result +++ b/mysql-test/r/events.result @@ -365,19 +365,19 @@ on schedule every 10 hour disable do select 1; -select event_schema, event_name, definer, event_body from information_schema.events where event_name='white_space'; -event_schema event_name definer event_body +select event_schema, event_name, definer, event_definition from information_schema.events where event_name='white_space'; +event_schema event_name definer event_definition events_test white_space root@localhost select 1 drop event white_space; create event white_space on schedule every 10 hour disable do select 2; -select event_schema, event_name, definer, event_body from information_schema.events where event_name='white_space'; -event_schema event_name definer event_body +select event_schema, event_name, definer, event_definition from information_schema.events where event_name='white_space'; +event_schema event_name definer event_definition events_test white_space root@localhost select 2 drop event white_space; create event white_space on schedule every 10 hour disable do select 3; -select event_schema, event_name, definer, event_body from information_schema.events where event_name='white_space'; -event_schema event_name definer event_body +select event_schema, event_name, definer, event_definition from information_schema.events where event_name='white_space'; +event_schema event_name definer event_definition events_test white_space root@localhost select 3 drop event white_space; create event e1 on schedule every 1 year do set @a = 5; diff --git a/mysql-test/r/events_grant.result b/mysql-test/r/events_grant.result index 6c140f91eaa..eda0759d518 100644 --- a/mysql-test/r/events_grant.result +++ b/mysql-test/r/events_grant.result @@ -4,9 +4,9 @@ CREATE EVENT one_event ON SCHEDULE EVERY 10 SECOND DO SELECT 123; SHOW EVENTS; Db Name Definer Type Execute at Interval value Interval field Starts Ends Status events_test one_event root@localhost RECURRING NULL 10 SECOND # # ENABLED -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT from information_schema.events; -EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT -NULL events_test one_event root@localhost SELECT 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT from information_schema.events; +EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_DEFINITION EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT +NULL events_test one_event root@localhost SQL SELECT 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE CREATE DATABASE events_test2; CREATE USER ev_test@localhost; GRANT ALL ON events_test.* to ev_test@localhost; @@ -57,65 +57,65 @@ USE events_test2; CREATE EVENT four_event ON SCHEDULE EVERY 20 SECOND DO SELECT 42; USE events_test; "We should see 4 events : one_event, two_event, three_event & four_event" -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; -EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT -NULL events_test one_event root@localhost SELECT 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE -NULL events_test two_event ev_test@localhost SELECT 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event -NULL events_test three_event ev_test@localhost SELECT 123 RECURRING NULL 20 SECOND ENABLED PRESERVE three event -NULL events_test2 four_event ev_test@localhost SELECT 42 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; +EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_DEFINITION EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT +NULL events_test one_event root@localhost SQL SELECT 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE +NULL events_test two_event ev_test@localhost SQL SELECT 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event +NULL events_test three_event ev_test@localhost SQL SELECT 123 RECURRING NULL 20 SECOND ENABLED PRESERVE three event +NULL events_test2 four_event ev_test@localhost SQL SELECT 42 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE DROP DATABASE events_test2; "We should see 3 events : one_event, two_event, three_event" -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; -EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT -NULL events_test one_event root@localhost SELECT 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE -NULL events_test two_event ev_test@localhost SELECT 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event -NULL events_test three_event ev_test@localhost SELECT 123 RECURRING NULL 20 SECOND ENABLED PRESERVE three event +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; +EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_DEFINITION EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT +NULL events_test one_event root@localhost SQL SELECT 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE +NULL events_test two_event ev_test@localhost SQL SELECT 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event +NULL events_test three_event ev_test@localhost SQL SELECT 123 RECURRING NULL 20 SECOND ENABLED PRESERVE three event CREATE DATABASE events_test2; USE events_test2; CREATE EVENT five_event ON SCHEDULE EVERY 20 SECOND DO SELECT 42; "Should see 4 events - one, two, three & five" -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; -EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT -NULL events_test one_event root@localhost SELECT 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE -NULL events_test two_event ev_test@localhost SELECT 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event -NULL events_test three_event ev_test@localhost SELECT 123 RECURRING NULL 20 SECOND ENABLED PRESERVE three event -NULL events_test2 five_event root@localhost SELECT 42 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; +EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_DEFINITION EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT +NULL events_test one_event root@localhost SQL SELECT 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE +NULL events_test two_event ev_test@localhost SQL SELECT 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event +NULL events_test three_event ev_test@localhost SQL SELECT 123 RECURRING NULL 20 SECOND ENABLED PRESERVE three event +NULL events_test2 five_event root@localhost SQL SELECT 42 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE REVOKE EVENT ON events_test2.* FROM ev_test@localhost; USE test; "Should see 3 events - one, two & three" -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; -EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT -NULL events_test one_event root@localhost SELECT 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE -NULL events_test two_event ev_test@localhost SELECT 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event -NULL events_test three_event ev_test@localhost SELECT 123 RECURRING NULL 20 SECOND ENABLED PRESERVE three event +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; +EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_DEFINITION EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT +NULL events_test one_event root@localhost SQL SELECT 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE +NULL events_test two_event ev_test@localhost SQL SELECT 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event +NULL events_test three_event ev_test@localhost SQL SELECT 123 RECURRING NULL 20 SECOND ENABLED PRESERVE three event "Let's test ALTER EVENT which changes the definer" USE events_test; ALTER EVENT one_event ON SCHEDULE EVERY 10 SECOND; "The definer should be ev_test@localhost" -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME='one_event'; -EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT -NULL events_test one_event ev_test@localhost SELECT 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME='one_event'; +EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_DEFINITION EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT +NULL events_test one_event ev_test@localhost SQL SELECT 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE USE events_test; ALTER EVENT one_event COMMENT "comment"; "The definer should be root@localhost" -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME='one_event'; -EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT -NULL events_test one_event root@localhost SELECT 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE comment +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME='one_event'; +EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_DEFINITION EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT +NULL events_test one_event root@localhost SQL SELECT 123 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE comment ALTER EVENT one_event DO SELECT 12; "The definer should be ev_test@localhost" -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME='one_event'; -EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT -NULL events_test one_event ev_test@localhost SELECT 12 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE comment +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME='one_event'; +EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_DEFINITION EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT +NULL events_test one_event ev_test@localhost SQL SELECT 12 RECURRING NULL 10 SECOND ENABLED NOT PRESERVE comment "make the definer again root@localhost" ALTER EVENT one_event COMMENT "new comment"; "test DROP by another user" DROP EVENT one_event; "One event should not be there" -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; -EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT -NULL events_test two_event ev_test@localhost SELECT 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event -NULL events_test three_event ev_test@localhost SELECT 123 RECURRING NULL 20 SECOND ENABLED PRESERVE three event -NULL events_test2 five_event root@localhost SELECT 42 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; +EVENT_CATALOG EVENT_SCHEMA EVENT_NAME DEFINER EVENT_BODY EVENT_DEFINITION EVENT_TYPE EXECUTE_AT INTERVAL_VALUE INTERVAL_FIELD STATUS ON_COMPLETION EVENT_COMMENT +NULL events_test two_event ev_test@localhost SQL SELECT 123 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE two event +NULL events_test three_event ev_test@localhost SQL SELECT 123 RECURRING NULL 20 SECOND ENABLED PRESERVE three event +NULL events_test2 five_event root@localhost SQL SELECT 42 RECURRING NULL 20 SECOND ENABLED NOT PRESERVE DROP USER ev_test@localhost; DROP DATABASE events_test2; DROP DATABASE events_test; diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result index 070049b303a..7157175a60f 100644 --- a/mysql-test/r/information_schema.result +++ b/mysql-test/r/information_schema.result @@ -754,7 +754,7 @@ information_schema.columns where data_type = 'longtext'; table_schema table_name column_name information_schema COLUMNS COLUMN_TYPE -information_schema EVENTS EVENT_BODY +information_schema EVENTS EVENT_DEFINITION information_schema EVENTS SQL_MODE information_schema PARTITIONS PARTITION_EXPRESSION information_schema PARTITIONS SUBPARTITION_EXPRESSION diff --git a/mysql-test/t/events.test b/mysql-test/t/events.test index a3e2bbc0998..f8dc5dd804b 100644 --- a/mysql-test/t/events.test +++ b/mysql-test/t/events.test @@ -327,15 +327,15 @@ on schedule every 10 hour disable do select 1; -select event_schema, event_name, definer, event_body from information_schema.events where event_name='white_space'; +select event_schema, event_name, definer, event_definition from information_schema.events where event_name='white_space'; drop event white_space; create event white_space on schedule every 10 hour disable do select 2; -select event_schema, event_name, definer, event_body from information_schema.events where event_name='white_space'; +select event_schema, event_name, definer, event_definition from information_schema.events where event_name='white_space'; drop event white_space; create event white_space on schedule every 10 hour disable do select 3; -select event_schema, event_name, definer, event_body from information_schema.events where event_name='white_space'; +select event_schema, event_name, definer, event_definition from information_schema.events where event_name='white_space'; drop event white_space; # # END: BUG #17453: Creating Event crash the server diff --git a/mysql-test/t/events_grant.test b/mysql-test/t/events_grant.test index ba94944a3cf..8a3ef3a19de 100644 --- a/mysql-test/t/events_grant.test +++ b/mysql-test/t/events_grant.test @@ -6,7 +6,7 @@ use events_test; CREATE EVENT one_event ON SCHEDULE EVERY 10 SECOND DO SELECT 123; --replace_column 8 # 9 # SHOW EVENTS; -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT from information_schema.events; +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT from information_schema.events; CREATE DATABASE events_test2; CREATE USER ev_test@localhost; GRANT ALL ON events_test.* to ev_test@localhost; @@ -52,10 +52,10 @@ CREATE EVENT four_event ON SCHEDULE EVERY 20 SECOND DO SELECT 42; connection default; USE events_test; --echo "We should see 4 events : one_event, two_event, three_event & four_event" -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; DROP DATABASE events_test2; --echo "We should see 3 events : one_event, two_event, three_event" -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; connection default; CREATE DATABASE events_test2; @@ -64,27 +64,27 @@ CREATE EVENT five_event ON SCHEDULE EVERY 20 SECOND DO SELECT 42; connection ev_con1; --echo "Should see 4 events - one, two, three & five" -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; connection default; REVOKE EVENT ON events_test2.* FROM ev_test@localhost; connection ev_con1; USE test; --echo "Should see 3 events - one, two & three" -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; --echo "Let's test ALTER EVENT which changes the definer" USE events_test; ALTER EVENT one_event ON SCHEDULE EVERY 10 SECOND; --echo "The definer should be ev_test@localhost" -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME='one_event'; +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME='one_event'; connection default; USE events_test; ALTER EVENT one_event COMMENT "comment"; connection ev_con1; --echo "The definer should be root@localhost" -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME='one_event'; +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME='one_event'; ALTER EVENT one_event DO SELECT 12; --echo "The definer should be ev_test@localhost" -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME='one_event'; +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS WHERE EVENT_NAME='one_event'; connection default; --echo "make the definer again root@localhost" ALTER EVENT one_event COMMENT "new comment"; @@ -93,7 +93,7 @@ connection ev_con1; DROP EVENT one_event; connection default; --echo "One event should not be there" -SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; +SELECT EVENT_CATALOG, EVENT_SCHEMA, EVENT_NAME, DEFINER, EVENT_BODY, EVENT_DEFINITION, EVENT_TYPE, EXECUTE_AT, INTERVAL_VALUE, INTERVAL_FIELD, STATUS,ON_COMPLETION, EVENT_COMMENT FROM INFORMATION_SCHEMA.EVENTS; disconnect ev_con1; connection default; DROP USER ev_test@localhost; diff --git a/sql/sql_show.cc b/sql/sql_show.cc index 940b157e8b7..ca0ca50eae0 100644 --- a/sql/sql_show.cc +++ b/sql/sql_show.cc @@ -34,6 +34,30 @@ #include "ha_partition.h" #endif +enum enum_i_s_events_fields +{ + ISE_EVENT_CATALOG= 0, + ISE_EVENT_SCHEMA, + ISE_EVENT_NAME, + ISE_DEFINER, + ISE_EVENT_BODY, + ISE_EVENT_DEFINITION, + ISE_EVENT_TYPE, + ISE_EXECUTE_AT, + ISE_INTERVAL_VALUE, + ISE_INTERVAL_FIELD, + ISE_SQL_MODE, + ISE_STARTS, + ISE_ENDS, + ISE_STATUS, + ISE_ON_COMPLETION, + ISE_CREATED, + ISE_LAST_ALTERED, + ISE_LAST_EXECUTED, + ISE_EVENT_COMMENT +}; + + static const char *grant_names[]={ "select","insert","update","delete","create","drop","reload","shutdown", "process","file","grant","references","index","alter"}; @@ -4109,6 +4133,8 @@ static interval_type get_real_interval_type(interval_type i_type) case INTERVAL_SECOND_MICROSECOND: case INTERVAL_MICROSECOND: return INTERVAL_MICROSECOND; + case INTERVAL_LAST: + DBUG_ASSERT(0); } DBUG_ASSERT(0); return INTERVAL_SECOND; @@ -4164,85 +4190,101 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table) /* ->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[4]->store(et.body.str, et.body.length, scs); + sch_table->field[ISE_EVENT_SCHEMA]-> + store(et.dbname.str, et.dbname.length,scs); + sch_table->field[ISE_EVENT_NAME]-> + store(et.name.str, et.name.length, scs); + sch_table->field[ISE_DEFINER]-> + store(et.definer.str, et.definer.length, scs); + sch_table->field[ISE_EVENT_BODY]-> + store(STRING_WITH_LEN("SQL"), scs); + sch_table->field[ISE_EVENT_DEFINITION]-> + store(et.body.str, et.body.length, scs); - /* [9] is SQL_MODE */ + /* SQL_MODE */ { byte *sql_mode_str; - ulong sql_mode_len=0; + ulong sql_mode_len= 0; sql_mode_str= sys_var_thd_sql_mode::symbolic_mode_representation(thd, et.sql_mode, &sql_mode_len); - sch_table->field[9]->store((const char*)sql_mode_str, sql_mode_len, scs); + sch_table->field[ISE_SQL_MODE]-> + store((const char*)sql_mode_str, sql_mode_len, scs); } if (et.expression) { String show_str; /* type */ - sch_table->field[5]->store(STRING_WITH_LEN("RECURRING"), scs); + sch_table->field[ISE_EVENT_TYPE]->store(STRING_WITH_LEN("RECURRING"), scs); if (Events::reconstruct_interval_expression(&show_str, et.interval, et.expression)) DBUG_RETURN(1); - sch_table->field[7]->set_notnull(); - sch_table->field[7]->store(show_str.ptr(), show_str.length(), scs); + sch_table->field[ISE_INTERVAL_VALUE]->set_notnull(); + sch_table->field[ISE_INTERVAL_VALUE]-> + store(show_str.ptr(), show_str.length(), scs); LEX_STRING *ival= &interval_type_to_name[et.interval]; - sch_table->field[8]->set_notnull(); - sch_table->field[8]->store(ival->str, ival->length, scs); + sch_table->field[ISE_INTERVAL_FIELD]->set_notnull(); + sch_table->field[ISE_INTERVAL_FIELD]->store(ival->str, ival->length, scs); - /* starts & ends */ - sch_table->field[10]->set_notnull(); - sch_table->field[10]->store_time(&et.starts, MYSQL_TIMESTAMP_DATETIME); + /* starts & ends . STARTS is always set - see sql_yacc.yy */ + sch_table->field[ISE_STARTS]->set_notnull(); + sch_table->field[ISE_STARTS]-> + store_time(&et.starts, MYSQL_TIMESTAMP_DATETIME); if (!et.ends_null) { - sch_table->field[11]->set_notnull(); - sch_table->field[11]->store_time(&et.ends, MYSQL_TIMESTAMP_DATETIME); + sch_table->field[ISE_ENDS]->set_notnull(); + sch_table->field[ISE_ENDS]-> + store_time(&et.ends, MYSQL_TIMESTAMP_DATETIME); } } else { - //type - sch_table->field[5]->store(STRING_WITH_LEN("ONE TIME"), scs); + /* type */ + sch_table->field[ISE_EVENT_TYPE]->store(STRING_WITH_LEN("ONE TIME"), scs); - sch_table->field[6]->set_notnull(); - sch_table->field[6]->store_time(&et.execute_at, MYSQL_TIMESTAMP_DATETIME); + sch_table->field[ISE_EXECUTE_AT]->set_notnull(); + sch_table->field[ISE_EXECUTE_AT]-> + store_time(&et.execute_at, MYSQL_TIMESTAMP_DATETIME); } /* status */ if (et.status == Event_timed::ENABLED) - sch_table->field[12]->store(STRING_WITH_LEN("ENABLED"), scs); + sch_table->field[ISE_STATUS]->store(STRING_WITH_LEN("ENABLED"), scs); else - sch_table->field[12]->store(STRING_WITH_LEN("DISABLED"), scs); + sch_table->field[ISE_STATUS]->store(STRING_WITH_LEN("DISABLED"), scs); /* on_completion */ if (et.on_completion == Event_timed::ON_COMPLETION_DROP) - sch_table->field[13]->store(STRING_WITH_LEN("NOT PRESERVE"), scs); + sch_table->field[ISE_ON_COMPLETION]-> + store(STRING_WITH_LEN("NOT PRESERVE"), scs); else - sch_table->field[13]->store(STRING_WITH_LEN("PRESERVE"), scs); + sch_table->field[ISE_ON_COMPLETION]-> + store(STRING_WITH_LEN("PRESERVE"), scs); int not_used=0; number_to_datetime(et.created, &time, 0, ¬_used); DBUG_ASSERT(not_used==0); - sch_table->field[14]->store_time(&time, MYSQL_TIMESTAMP_DATETIME); + sch_table->field[ISE_CREATED]->store_time(&time, MYSQL_TIMESTAMP_DATETIME); number_to_datetime(et.modified, &time, 0, ¬_used); DBUG_ASSERT(not_used==0); - sch_table->field[15]->store_time(&time, MYSQL_TIMESTAMP_DATETIME); + sch_table->field[ISE_LAST_ALTERED]-> + store_time(&time, MYSQL_TIMESTAMP_DATETIME); if (et.last_executed.year) { - sch_table->field[16]->set_notnull(); - sch_table->field[16]->store_time(&et.last_executed,MYSQL_TIMESTAMP_DATETIME); + sch_table->field[ISE_LAST_EXECUTED]->set_notnull(); + sch_table->field[ISE_LAST_EXECUTED]-> + store_time(&et.last_executed, MYSQL_TIMESTAMP_DATETIME); } - sch_table->field[17]->store(et.comment.str, et.comment.length, scs); + sch_table->field[ISE_EVENT_COMMENT]-> + store(et.comment.str, et.comment.length, scs); if (schema_table_store_record(thd, sch_table)) DBUG_RETURN(1); @@ -5166,7 +5208,8 @@ ST_FIELD_INFO events_fields_info[]= {"EVENT_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Db"}, {"EVENT_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name"}, {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, "Definer"}, - {"EVENT_BODY", 65535, MYSQL_TYPE_STRING, 0, 0, 0}, + {"EVENT_BODY", 8, MYSQL_TYPE_STRING, 0, 0, 0}, + {"EVENT_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 0}, {"EVENT_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, "Type"}, {"EXECUTE_AT", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Execute at"}, {"INTERVAL_VALUE", 256, MYSQL_TYPE_STRING, 0, 1, "Interval value"}, From 50c7663dbc8e7b4e96346444c3568b28ee97845d Mon Sep 17 00:00:00 2001 From: "andrey@lmy004." <> Date: Thu, 22 Jun 2006 16:13:18 +0200 Subject: [PATCH 07/16] fix for bug#20624: events_logs_tests.test fails randomly (this is a change to a faulty test file) --- mysql-test/r/events_logs_tests.result | 13 ++++++++++--- mysql-test/t/events_logs_tests.test | 13 ++++++++++--- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/mysql-test/r/events_logs_tests.result b/mysql-test/r/events_logs_tests.result index ce58e0ec059..9202d63fd2c 100644 --- a/mysql-test/r/events_logs_tests.result +++ b/mysql-test/r/events_logs_tests.result @@ -31,6 +31,8 @@ SHOW VARIABLES LIKE 'log_slow_queries'; Variable_name Value log_slow_queries ON DROP FUNCTION get_value; +"Make it quite long" +SET SESSION long_query_time=300; TRUNCATE mysql.slow_log; SELECT user_host, query_time, db, sql_text FROM mysql.slow_log; user_host query_time db sql_text @@ -44,7 +46,10 @@ SLEEP(2) SELECT user_host, query_time, db, sql_text FROM mysql.slow_log; user_host query_time db sql_text USER_HOST SLEEPVAL events_test SELECT SLEEP(2) +SET SESSION long_query_time=300; +"Make it quite long" TRUNCATE mysql.slow_log; +SET SESSION long_query_time=1; CREATE TABLE slow_event_test (slo_val tinyint, val tinyint); "This won't go to the slow log" CREATE EVENT long_event ON SCHEDULE EVERY 1 MINUTE DO INSERT INTO slow_event_test SELECT @@long_query_time, SLEEP(3); @@ -63,9 +68,9 @@ slo_val val SELECT user_host, query_time, db, sql_text FROM mysql.slow_log; user_host query_time db sql_text "This should go to the slow log" +DROP EVENT long_event; SET SESSION long_query_time=10; SET GLOBAL long_query_time=1; -DROP EVENT long_event; CREATE EVENT long_event2 ON SCHEDULE EVERY 1 MINUTE DO INSERT INTO slow_event_test SELECT @@long_query_time, SLEEP(2); "Sleep some more time than the actual event run will take" "Check our table. Should see 2 rows" @@ -78,8 +83,10 @@ SELECT user_host, query_time, db, sql_text FROM mysql.slow_log; user_host query_time db sql_text USER_HOST SLEEPVAL events_test INSERT INTO slow_event_test SELECT @@long_query_time, SLEEP(2) DROP EVENT long_event2; -SET GLOBAL long_query_time =@old_global_long_query_time; -SET SESSION long_query_time =@old_session_long_query_time; +"Make it quite long" +SET SESSION long_query_time=300; TRUNCATE mysql.slow_log; DROP TABLE slow_event_test; +SET GLOBAL long_query_time =@old_global_long_query_time; +SET SESSION long_query_time =@old_session_long_query_time; drop database events_test; diff --git a/mysql-test/t/events_logs_tests.test b/mysql-test/t/events_logs_tests.test index 6d3b3292630..8ee34e2d32c 100644 --- a/mysql-test/t/events_logs_tests.test +++ b/mysql-test/t/events_logs_tests.test @@ -51,6 +51,8 @@ SET @old_global_long_query_time:=(select get_value()); SET @old_session_long_query_time:=@@long_query_time; SHOW VARIABLES LIKE 'log_slow_queries'; DROP FUNCTION get_value; +--echo "Make it quite long" +SET SESSION long_query_time=300; TRUNCATE mysql.slow_log; --replace_column 1 USER_HOST SELECT user_host, query_time, db, sql_text FROM mysql.slow_log; @@ -61,7 +63,10 @@ SET SESSION long_query_time=1; SELECT SLEEP(2); --replace_column 1 USER_HOST 2 SLEEPVAL SELECT user_host, query_time, db, sql_text FROM mysql.slow_log; +SET SESSION long_query_time=300; +--echo "Make it quite long" TRUNCATE mysql.slow_log; +SET SESSION long_query_time=1; CREATE TABLE slow_event_test (slo_val tinyint, val tinyint); --echo "This won't go to the slow log" CREATE EVENT long_event ON SCHEDULE EVERY 1 MINUTE DO INSERT INTO slow_event_test SELECT @@long_query_time, SLEEP(3); @@ -75,9 +80,9 @@ SELECT * FROM slow_event_test; --echo "Check slow log. Should not see anything because 3 is under the threshold of 4 for GLOBAL, though over SESSION which is 2" SELECT user_host, query_time, db, sql_text FROM mysql.slow_log; --echo "This should go to the slow log" +DROP EVENT long_event; SET SESSION long_query_time=10; SET GLOBAL long_query_time=1; -DROP EVENT long_event; CREATE EVENT long_event2 ON SCHEDULE EVERY 1 MINUTE DO INSERT INTO slow_event_test SELECT @@long_query_time, SLEEP(2); --echo "Sleep some more time than the actual event run will take" --sleep 3 @@ -87,9 +92,11 @@ SELECT * FROM slow_event_test; --replace_column 1 USER_HOST 2 SLEEPVAL SELECT user_host, query_time, db, sql_text FROM mysql.slow_log; DROP EVENT long_event2; -SET GLOBAL long_query_time =@old_global_long_query_time; -SET SESSION long_query_time =@old_session_long_query_time; +--echo "Make it quite long" +SET SESSION long_query_time=300; TRUNCATE mysql.slow_log; DROP TABLE slow_event_test; +SET GLOBAL long_query_time =@old_global_long_query_time; +SET SESSION long_query_time =@old_session_long_query_time; drop database events_test; From d5dca744cdde82c3cb6cf64b9df78a5ffa71bfb6 Mon Sep 17 00:00:00 2001 From: "anozdrin@mysql.com" <> Date: Thu, 22 Jun 2006 18:56:22 +0400 Subject: [PATCH 08/16] Additional fix for BUG#20294: Instance manager test im_instance_conf fails randomly. --- mysql-test/r/im_options.result | 7 ++++++- mysql-test/t/im_instance_conf.imtest | 3 +++ mysql-test/t/im_options.imtest | 10 ++++++++-- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/mysql-test/r/im_options.result b/mysql-test/r/im_options.result index 8039333b7d9..cb678581533 100644 --- a/mysql-test/r/im_options.result +++ b/mysql-test/r/im_options.result @@ -13,7 +13,10 @@ UNSET mysqld1.server_id; ERROR HY000: The instance is active. Stop the instance first SET mysqld1.server_id = 11; ERROR HY000: The instance is active. Stop the instance first -CREATE INSTANCE mysqld3 datadir = '/'; +CREATE INSTANCE mysqld3 +datadir = '/', +server_id = 3, +socket = "$MYSQL_TMP_DIR/mysqld_3.sock"; START INSTANCE mysqld3; UNSET mysqld3.server_id; ERROR HY000: The instance is active. Stop the instance first @@ -101,12 +104,14 @@ ERROR HY000: Bad instance name. Check that the instance with such a name exists -------------------------------------------------------------------- server_id = 1 server_id=2 +server_id=3 -------------------------------------------------------------------- UNSET mysqld2.server_id, mysqld3.server_id, mysqld1.ccc; ERROR HY000: The instance is active. Stop the instance first -------------------------------------------------------------------- server_id = 1 server_id=2 +server_id=3 -------------------------------------------------------------------- DROP INSTANCE mysqld3; SET mysqld2.server_id=222; diff --git a/mysql-test/t/im_instance_conf.imtest b/mysql-test/t/im_instance_conf.imtest index 2cd7b955978..3d254b16ca5 100644 --- a/mysql-test/t/im_instance_conf.imtest +++ b/mysql-test/t/im_instance_conf.imtest @@ -21,6 +21,9 @@ # - DROP INSTANCE fails for active instance. # - DROP INSTANCE updates both config file and internal configuration cache; # +# NOTE: each CREATE INSTANCE statement must specify socket-file-name, otherwise +# this results of the test can be affected by another running test suite. +# ########################################################################### --source include/im_check_os.inc diff --git a/mysql-test/t/im_options.imtest b/mysql-test/t/im_options.imtest index cd905416cda..55bd29c9ee1 100644 --- a/mysql-test/t/im_options.imtest +++ b/mysql-test/t/im_options.imtest @@ -21,12 +21,15 @@ # - server_id # - port # - nonguarded - +# # Let's test SET statement on the option 'server_id'. It's expected that # originally the instances have the following server ids and states: # - mysqld1: server_id: 1; running (online) # - mysqld2: server_id: 2; stopped (offline) # +# NOTE: each CREATE INSTANCE statement must specify socket-file-name, otherwise +# this results of the test can be affected by another running test suite. +# ########################################################################### --source include/im_check_os.inc @@ -76,7 +79,10 @@ SET mysqld1.server_id = 11; # - start it; # - try to set/unset options; -CREATE INSTANCE mysqld3 datadir = '/'; +CREATE INSTANCE mysqld3 + datadir = '/', + server_id = 3, + socket = "$MYSQL_TMP_DIR/mysqld_3.sock"; START INSTANCE mysqld3; # FIXME: START INSTANCE should be synchronous. From 3b58c95d6e05d8860e61cfe22ba3bb9729327389 Mon Sep 17 00:00:00 2001 From: "kroki@mysql.com" <> Date: Thu, 22 Jun 2006 19:15:03 +0400 Subject: [PATCH 09/16] Bug#15811: extremely long time for mysql client to execute long INSERT The problem was in redundant calls to strlen() in string functions, where we may then return after checking only the small number of characters. No test case is provided since it's a performance fix. --- strings/ctype-mb.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c index a3e10ba7650..0d73c7d1e51 100644 --- a/strings/ctype-mb.c +++ b/strings/ctype-mb.c @@ -24,12 +24,12 @@ void my_caseup_str_mb(CHARSET_INFO * cs, char *str) { register uint32 l; - register char *end=str+strlen(str); /* BAR TODO: remove strlen() call */ register uchar *map=cs->to_upper; while (*str) { - if ((l=my_ismbchar(cs, str,end))) + /* Pointing after the '\0' is safe here. */ + if ((l=my_ismbchar(cs, str, str + cs->mbmaxlen))) str+=l; else { @@ -42,12 +42,12 @@ void my_caseup_str_mb(CHARSET_INFO * cs, char *str) void my_casedn_str_mb(CHARSET_INFO * cs, char *str) { register uint32 l; - register char *end=str+strlen(str); register uchar *map=cs->to_lower; while (*str) { - if ((l=my_ismbchar(cs, str,end))) + /* Pointing after the '\0' is safe here. */ + if ((l=my_ismbchar(cs, str, str + cs->mbmaxlen))) str+=l; else { @@ -101,15 +101,18 @@ uint my_casedn_mb(CHARSET_INFO * cs, char *src, uint srclen, return srclen; } +/* + my_strcasecmp_mb() returns 0 if strings are equal, non-zero otherwise. + */ int my_strcasecmp_mb(CHARSET_INFO * cs,const char *s, const char *t) { register uint32 l; - register const char *end=s+strlen(s); register uchar *map=cs->to_upper; - while (smbmaxlen))) { while (l--) if (*s++ != *t++) @@ -120,7 +123,8 @@ int my_strcasecmp_mb(CHARSET_INFO * cs,const char *s, const char *t) else if (map[(uchar) *s++] != map[(uchar) *t++]) return 1; } - return *t; + /* At least one of '*s' and '*t' is zero here. */ + return (*t != *s); } From e20898a5076237f66063ed0ae0cf2cb40b8261f4 Mon Sep 17 00:00:00 2001 From: "konstantin@mysql.com" <> Date: Thu, 22 Jun 2006 19:29:48 +0400 Subject: [PATCH 10/16] A fix and a test case for Bug#15217 "Using a SP cursor on a table created with PREPARE fails with weird error". More generally, re-executing a stored procedure with a complex SP cursor query could lead to a crash. The cause of the problem was that SP cursor queries were not optimized properly at first execution: their parse tree belongs to sp_instr_cpush, not sp_instr_copen, and thus the tree was tagged "EXECUTED" when the cursor was declared, not when it was opened. This led to loss of optimization transformations performed at first execution, as sp_instr_copen saw that the query is already "EXECUTED" and therefore either not ran first-execution related blocks or wrongly rolled back the transformations caused by first-execution code. The fix is to update the state of the parsed tree only when the tree is executed, as opposed to when the instruction containing the tree is executed. Assignment if i->state is moved to reset_lex_and_exec_core. --- mysql-test/r/sp.result | 21 +++++++++++++++++++++ mysql-test/t/sp.test | 27 +++++++++++++++++++++++++++ sql/sp_head.cc | 4 +++- 3 files changed, 51 insertions(+), 1 deletion(-) diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index ff378f1f43b..d3874c769fa 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -4990,4 +4990,25 @@ CALL bug18037_p2()| DROP FUNCTION bug18037_f1| DROP PROCEDURE bug18037_p1| DROP PROCEDURE bug18037_p2| +drop table if exists t3| +drop procedure if exists bug15217| +create table t3 as select 1| +create procedure bug15217() +begin +declare var1 char(255); +declare cur1 cursor for select * from t3; +open cur1; +fetch cur1 into var1; +select concat('data was: /', var1, '/'); +close cur1; +end | +call bug15217()| +concat('data was: /', var1, '/') +data was: /1/ +flush tables | +call bug15217()| +concat('data was: /', var1, '/') +data was: /1/ +drop table t3| +drop procedure bug15217| drop table t1,t2; diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 1d21a5da187..66498198157 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -5888,6 +5888,33 @@ DROP FUNCTION bug18037_f1| DROP PROCEDURE bug18037_p1| DROP PROCEDURE bug18037_p2| +# +# Bug#15217 "Using a SP cursor on a table created with PREPARE fails with +# weird error". Check that the code that is supposed to work at +# the first execution of a stored procedure actually works for +# sp_instr_copen. + +--disable_warnings +drop table if exists t3| +drop procedure if exists bug15217| +--enable_warnings +create table t3 as select 1| +create procedure bug15217() +begin + declare var1 char(255); + declare cur1 cursor for select * from t3; + open cur1; + fetch cur1 into var1; + select concat('data was: /', var1, '/'); + close cur1; +end | +# Returns expected result +call bug15217()| +flush tables | +# Returns error with garbage as column name +call bug15217()| +drop table t3| +drop procedure bug15217| # # BUG#NNNN: New bug synopsis diff --git a/sql/sp_head.cc b/sql/sp_head.cc index 3b29a841966..ef2f895c8b2 100644 --- a/sql/sp_head.cc +++ b/sql/sp_head.cc @@ -1075,7 +1075,6 @@ sp_head::execute(THD *thd) thd->net.no_send_error= 0; if (i->free_list) cleanup_items(i->free_list); - i->state= Query_arena::EXECUTED; /* If we've set thd->user_var_events_alloc to mem_root of this SP @@ -2210,6 +2209,9 @@ sp_lex_keeper::reset_lex_and_exec_core(THD *thd, uint *nextp, m_lex->mark_as_requiring_prelocking(NULL); } thd->rollback_item_tree_changes(); + /* Update the state of the active arena. */ + thd->stmt_arena->state= Query_arena::EXECUTED; + /* Unlike for PS we should not call Item's destructors for newly created From 3d445c52ddb97a6b670d73f987f669a5e34f82bc Mon Sep 17 00:00:00 2001 From: "jmiller@mysql.com" <> Date: Thu, 22 Jun 2006 23:42:11 +0200 Subject: [PATCH 11/16] disabled.def: Enabled rpl_ndb_auto_inc per Tomas and Lars --- mysql-test/t/disabled.def | 1 - 1 file changed, 1 deletion(-) diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 20462ad62cb..740d69cc849 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -26,7 +26,6 @@ partition_03ndb : BUG#16385 2006-03-24 mikael Partitions: crash when up ps_7ndb : BUG#18950 2006-02-16 jmiller create table like does not obtain LOCK_open rpl_ndb_2innodb : BUG#19227 2006-04-20 pekka pk delete apparently not replicated rpl_ndb_2myisam : BUG#19227 Seems to pass currently -rpl_ndb_auto_inc : BUG#17086 2006-02-16 jmiller CR: auto_increment_increment and auto_increment_offset produce duplicate key er #rpl_ndb_commit_afterflush : BUG#19328 2006-05-04 tomas Slave timeout with COM_REGISTER_SLAVE error causing stop rpl_ndb_dd_partitions : BUG#19259 2006-04-21 rpl_ndb_dd_partitions fails on s/AMD rpl_ndb_ddl : BUG#18946 result file needs update + test needs to checked From 08f9d359d46e0c6ce29eedf839a4fbecfc438943 Mon Sep 17 00:00:00 2001 From: "andrey@lmy004." <> Date: Fri, 23 Jun 2006 09:40:06 +0200 Subject: [PATCH 12/16] disable events tests in embedded (fix for bug#20290 Event mechanism incompatible with embedded server, but tests tried) --- mysql-test/t/events.test | 3 +++ mysql-test/t/events_bugs.test | 3 +++ mysql-test/t/events_grant.test | 3 +++ mysql-test/t/events_logs_tests.test | 3 +++ mysql-test/t/events_microsec.test | 3 +++ mysql-test/t/events_scheduling.test | 3 +++ mysql-test/t/events_stress.test | 3 +++ 7 files changed, 21 insertions(+) diff --git a/mysql-test/t/events.test b/mysql-test/t/events.test index a3e2bbc0998..da4a1cdda05 100644 --- a/mysql-test/t/events.test +++ b/mysql-test/t/events.test @@ -1,3 +1,6 @@ +# Can't test with embedded server that doesn't support grants +-- source include/not_embedded.inc + create database if not exists events_test; use events_test; diff --git a/mysql-test/t/events_bugs.test b/mysql-test/t/events_bugs.test index e3b79a6bd13..28d5acc69e6 100644 --- a/mysql-test/t/events_bugs.test +++ b/mysql-test/t/events_bugs.test @@ -1,3 +1,6 @@ +# Can't test with embedded server that doesn't support grants +-- source include/not_embedded.inc + create database if not exists events_test; use events_test; diff --git a/mysql-test/t/events_grant.test b/mysql-test/t/events_grant.test index ba94944a3cf..4957a4ca44a 100644 --- a/mysql-test/t/events_grant.test +++ b/mysql-test/t/events_grant.test @@ -1,3 +1,6 @@ +# Can't test with embedded server that doesn't support grants +-- source include/not_embedded.inc + CREATE DATABASE IF NOT EXISTS events_test; use events_test; # diff --git a/mysql-test/t/events_logs_tests.test b/mysql-test/t/events_logs_tests.test index 8ee34e2d32c..5f4ec852cd3 100644 --- a/mysql-test/t/events_logs_tests.test +++ b/mysql-test/t/events_logs_tests.test @@ -1,3 +1,6 @@ +# Can't test with embedded server that doesn't support grants +-- source include/not_embedded.inc + create database if not exists events_test; use events_test; --echo "We use procedure here because its statements won't be logged into the general log" diff --git a/mysql-test/t/events_microsec.test b/mysql-test/t/events_microsec.test index e01120a0756..b2164c7eaa6 100644 --- a/mysql-test/t/events_microsec.test +++ b/mysql-test/t/events_microsec.test @@ -1,3 +1,6 @@ +# Can't test with embedded server that doesn't support grants +-- source include/not_embedded.inc + create database if not exists events_test; use events_test; diff --git a/mysql-test/t/events_scheduling.test b/mysql-test/t/events_scheduling.test index c688864a1e6..987939bc162 100644 --- a/mysql-test/t/events_scheduling.test +++ b/mysql-test/t/events_scheduling.test @@ -1,3 +1,6 @@ +# Can't test with embedded server that doesn't support grants +-- source include/not_embedded.inc + CREATE DATABASE IF NOT EXISTS events_test; USE events_test; CREATE TABLE table_1(a int); diff --git a/mysql-test/t/events_stress.test b/mysql-test/t/events_stress.test index 8d0034c232e..cf6cc73df8a 100644 --- a/mysql-test/t/events_stress.test +++ b/mysql-test/t/events_stress.test @@ -1,3 +1,6 @@ +# Can't test with embedded server that doesn't support grants +-- source include/not_embedded.inc + CREATE DATABASE IF NOT EXISTS events_test; # # DROP DATABASE test start (bug #16406) From e71ef73d538386227cc9e0d67f384648e1572d9e Mon Sep 17 00:00:00 2001 From: "andrey@lmy004." <> Date: Fri, 23 Jun 2006 17:29:01 +0200 Subject: [PATCH 14/16] Fix for bug #18897 "Events: unauthorized action possible with alter event rename". ALTER EVENT ... RENAME statement hasn't checked privileges for the target database. It also caused server crashes when target database was not specified explicitly and there was no current database. This fix adds missing privilege check and check for the case when target database is not specified explicitly or implicitly. --- mysql-test/r/events_bugs.result | 23 ++++++++++++++++++++++ mysql-test/t/events_bugs.test | 34 +++++++++++++++++++++++++++++++++ sql/sql_parse.cc | 9 +++++++-- 3 files changed, 64 insertions(+), 2 deletions(-) diff --git a/mysql-test/r/events_bugs.result b/mysql-test/r/events_bugs.result index bc89c692f9a..a7c2964a253 100644 --- a/mysql-test/r/events_bugs.result +++ b/mysql-test/r/events_bugs.result @@ -178,4 +178,27 @@ drop procedure ee_16407_6_pendant; set global event_scheduler= 2; drop table events_smode_test; set sql_mode=@old_sql_mode; +set global event_scheduler=2; +delete from mysql.user where User like 'mysqltest_%'; +delete from mysql.db where User like 'mysqltest_%'; +flush privileges; +drop database if exists mysqltest_db1; +create user mysqltest_user1@localhost; +create database mysqltest_db1; +grant event on events_test.* to mysqltest_user1@localhost; +create event mysqltest_user1 on schedule every 10 second do select 42; +alter event mysqltest_user1 rename to mysqltest_db1.mysqltest_user1; +ERROR 42000: Access denied for user 'mysqltest_user1'@'localhost' to database 'mysqltest_db1' +"Let's test now rename when there is no select DB" +select database(); +database() +NULL +alter event events_test.mysqltest_user1 rename to mysqltest_user1; +ERROR 3D000: No database selected +select event_schema, event_name, definer, event_type, status from information_schema.events; +event_schema event_name definer event_type status +events_test mysqltest_user1 mysqltest_user1@localhost RECURRING ENABLED +drop event events_test.mysqltest_user1; +drop user mysqltest_user1@localhost; +drop database mysqltest_db1; drop database events_test; diff --git a/mysql-test/t/events_bugs.test b/mysql-test/t/events_bugs.test index e3b79a6bd13..12d75fede5c 100644 --- a/mysql-test/t/events_bugs.test +++ b/mysql-test/t/events_bugs.test @@ -172,4 +172,38 @@ set sql_mode=@old_sql_mode; # # End - 16407: Events: Changes in sql_mode won't be taken into account # + +# +# START - 18897: Events: unauthorized action possible with alter event rename +# +set global event_scheduler=2; +--disable_warnings +delete from mysql.user where User like 'mysqltest_%'; +delete from mysql.db where User like 'mysqltest_%'; +flush privileges; +drop database if exists mysqltest_db1; +--enable_warnings +create user mysqltest_user1@localhost; +create database mysqltest_db1; +grant event on events_test.* to mysqltest_user1@localhost; +connect (conn2,localhost,mysqltest_user1,,events_test); +create event mysqltest_user1 on schedule every 10 second do select 42; +--error ER_DBACCESS_DENIED_ERROR +alter event mysqltest_user1 rename to mysqltest_db1.mysqltest_user1; +--echo "Let's test now rename when there is no select DB" +disconnect conn2; +connect (conn2,localhost,mysqltest_user1,,*NO-ONE*); +select database(); +--error ER_NO_DB_ERROR +alter event events_test.mysqltest_user1 rename to mysqltest_user1; +select event_schema, event_name, definer, event_type, status from information_schema.events; +drop event events_test.mysqltest_user1; +disconnect conn2; +connection default; +drop user mysqltest_user1@localhost; +drop database mysqltest_db1; +# +# END - 18897: Events: unauthorized action possible with alter event rename +# + drop database events_test; diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc index 14847a9906d..2c92c98db5f 100644 --- a/sql/sql_parse.cc +++ b/sql/sql_parse.cc @@ -3823,7 +3823,9 @@ end_with_restore_list: uint rows_affected= 1; DBUG_ASSERT(lex->et); do { - if (! lex->et->dbname.str) + if (! lex->et->dbname.str || + (lex->sql_command == SQLCOM_ALTER_EVENT && lex->spname && + !lex->spname->m_db.str)) { my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0)); res= true; @@ -3831,7 +3833,10 @@ end_with_restore_list: } if (check_access(thd, EVENT_ACL, lex->et->dbname.str, 0, 0, 0, - is_schema_db(lex->et->dbname.str))) + is_schema_db(lex->et->dbname.str)) || + (lex->sql_command == SQLCOM_ALTER_EVENT && lex->spname && + (check_access(thd, EVENT_ACL, lex->spname->m_db.str, 0, 0, 0, + is_schema_db(lex->spname->m_db.str))))) break; if (end_active_trans(thd)) From b9b25ada28f7e48d6c543ad8ddef5def2d947aec Mon Sep 17 00:00:00 2001 From: "knielsen@mysql.com" <> Date: Sun, 25 Jun 2006 08:59:44 +0200 Subject: [PATCH 15/16] BUG#20677: Sporadic failure of test case 'ndb_binlog_multi'. Start test case with a dummy table create and drop. This ensures that NDB event subscription is properly set up before the real test starts, which otherwise could sometimes cause INSERT events to be lost. --- mysql-test/r/ndb_binlog_multi.result | 6 ++++-- mysql-test/t/ndb_binlog_multi.test | 11 +++++++++-- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/mysql-test/r/ndb_binlog_multi.result b/mysql-test/r/ndb_binlog_multi.result index be5dc695d24..119174039f9 100644 --- a/mysql-test/r/ndb_binlog_multi.result +++ b/mysql-test/r/ndb_binlog_multi.result @@ -1,5 +1,7 @@ -drop table if exists t1,t2; -drop table if exists t1,t2; +drop table if exists t1,t2,t3; +drop table if exists t1,t2,t3; +CREATE TABLE t3 (dummy INT PRIMARY KEY) ENGINE = NDB; +DROP TABLE t3; reset master; reset master; CREATE TABLE t2 (a INT PRIMARY KEY, b int) ENGINE = NDB; diff --git a/mysql-test/t/ndb_binlog_multi.test b/mysql-test/t/ndb_binlog_multi.test index 6adacf73208..e023a54b61c 100644 --- a/mysql-test/t/ndb_binlog_multi.test +++ b/mysql-test/t/ndb_binlog_multi.test @@ -4,11 +4,18 @@ --disable_warnings connection server2; -drop table if exists t1,t2; +drop table if exists t1,t2,t3; connection server1; -drop table if exists t1,t2; +drop table if exists t1,t2,t3; --enable_warnings +# Dummy table create/drop to avoid a race where table is created +# before event subscription is set up, causing test failure (BUG#20677). +connection server2; +CREATE TABLE t3 (dummy INT PRIMARY KEY) ENGINE = NDB; +connection server1; +DROP TABLE t3; + # reset for test connection server1; reset master; From 3ba774f1d7ba4bcf25278b1790132984cef39fd2 Mon Sep 17 00:00:00 2001 From: "knielsen@mysql.com" <> Date: Mon, 26 Jun 2006 15:49:58 +0200 Subject: [PATCH 16/16] BUG#20676: debug warnings about too many lock waiters cause test failure. The 250 simultaneous events all accessing the same table caused the events_stress test to fail due to debug warnings about too many table waiters. Fixed by using three different tables. --- mysql-test/r/events_stress.result | 8 ++++++-- mysql-test/t/events_stress.test | 22 ++++++++++++++-------- 2 files changed, 20 insertions(+), 10 deletions(-) diff --git a/mysql-test/r/events_stress.result b/mysql-test/r/events_stress.result index ead618e8136..050fe324426 100644 --- a/mysql-test/r/events_stress.result +++ b/mysql-test/r/events_stress.result @@ -1,6 +1,8 @@ CREATE DATABASE IF NOT EXISTS events_test; CREATE DATABASE events_conn1_test2; -CREATE TABLE events_test.fill_it(test_name varchar(20), occur datetime); +CREATE TABLE events_test.fill_it1(test_name varchar(20), occur datetime); +CREATE TABLE events_test.fill_it2(test_name varchar(20), occur datetime); +CREATE TABLE events_test.fill_it3(test_name varchar(20), occur datetime); CREATE USER event_user2@localhost; CREATE DATABASE events_conn2_db; GRANT ALL ON *.* TO event_user2@localhost; @@ -57,5 +59,7 @@ SET GLOBAL event_scheduler=2; DROP DATABASE events_conn1_test4; SET GLOBAL event_scheduler=1; USE events_test; -DROP TABLE fill_it; +DROP TABLE fill_it1; +DROP TABLE fill_it2; +DROP TABLE fill_it3; DROP DATABASE events_test; diff --git a/mysql-test/t/events_stress.test b/mysql-test/t/events_stress.test index 8d0034c232e..94aa99592d3 100644 --- a/mysql-test/t/events_stress.test +++ b/mysql-test/t/events_stress.test @@ -3,7 +3,11 @@ CREATE DATABASE IF NOT EXISTS events_test; # DROP DATABASE test start (bug #16406) # CREATE DATABASE events_conn1_test2; -CREATE TABLE events_test.fill_it(test_name varchar(20), occur datetime); +# BUG#20676: MySQL in debug mode has a limit of 100 waiters +# (in mysys/thr_lock.c), so use three different tables to insert into. +CREATE TABLE events_test.fill_it1(test_name varchar(20), occur datetime); +CREATE TABLE events_test.fill_it2(test_name varchar(20), occur datetime); +CREATE TABLE events_test.fill_it3(test_name varchar(20), occur datetime); CREATE USER event_user2@localhost; CREATE DATABASE events_conn2_db; GRANT ALL ON *.* TO event_user2@localhost; @@ -16,7 +20,7 @@ connect (conn2,localhost,event_user2,,events_conn2_db); let $1= 50; while ($1) { - eval CREATE EVENT conn2_ev$1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO events_test.fill_it VALUES("conn2_ev$1", NOW()); + eval CREATE EVENT conn2_ev$1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO events_test.fill_it1 VALUES("conn2_ev$1", NOW()); dec $1; } --enable_query_log @@ -26,7 +30,7 @@ connect (conn3,localhost,event_user3,,events_conn3_db); let $1= 50; while ($1) { - eval CREATE EVENT conn3_ev$1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO events_test.fill_it VALUES("conn3_ev$1", NOW()); + eval CREATE EVENT conn3_ev$1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO events_test.fill_it1 VALUES("conn3_ev$1", NOW()); dec $1; } --enable_query_log @@ -48,7 +52,7 @@ USE events_conn1_test2; let $1= 50; while ($1) { - eval CREATE EVENT conn1_round1_ev$1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO events_test.fill_it VALUES("conn1_round1_ev$1", NOW()); + eval CREATE EVENT conn1_round1_ev$1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO events_test.fill_it2 VALUES("conn1_round1_ev$1", NOW()); dec $1; } --enable_query_log @@ -65,7 +69,7 @@ USE events_conn1_test3; let $1= 50; while ($1) { - eval CREATE EVENT conn1_round2_ev$1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO events_test.fill_it VALUES("conn1_round2_ev$1", NOW()); + eval CREATE EVENT conn1_round2_ev$1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO events_test.fill_it2 VALUES("conn1_round2_ev$1", NOW()); dec $1; } --enable_query_log @@ -77,7 +81,7 @@ USE events_conn1_test4; let $1= 50; while ($1) { - eval CREATE EVENT conn1_round3_ev$1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO events_test.fill_it VALUES("conn1_round3_ev$1", NOW()); + eval CREATE EVENT conn1_round3_ev$1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO events_test.fill_it3 VALUES("conn1_round3_ev$1", NOW()); dec $1; } --enable_query_log @@ -88,7 +92,7 @@ USE events_conn1_test2; let $1= 50; while ($1) { - eval CREATE EVENT ev_round4_drop$1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO events_test.fill_it VALUES("conn1_round4_ev$1", NOW()); + eval CREATE EVENT ev_round4_drop$1 ON SCHEDULE EVERY 1 SECOND DO INSERT INTO events_test.fill_it3 VALUES("conn1_round4_ev$1", NOW()); dec $1; } --enable_query_log @@ -115,7 +119,9 @@ reap; disconnect conn3; connection default; USE events_test; -DROP TABLE fill_it; +DROP TABLE fill_it1; +DROP TABLE fill_it2; +DROP TABLE fill_it3; --disable_query_log DROP USER event_user2@localhost; DROP USER event_user3@localhost;