mirror of
https://github.com/MariaDB/server.git
synced 2025-01-23 23:34:34 +01:00
086fba7627
BUG#26429: SHOW CREATE EVENT is incorrect for an event that STARTS NOW() BUG#26431: Impossible to re-create an event from backup if its STARTS clause is in the past WL#3698: Events: execution in local time zone The problem was that local times specified by the user in AT, STARTS and ENDS of CREATE EVENT/ALTER EVENT statement were converted to UTC, and the original time zone was forgotten. This way, event scheduler couldn't honor Daylight Saving Time shifts, and times shown to the user were also in UTC. Additionally, CREATE EVENT didn't allow times in the past, thus preventing straightforward event restoration from old backups. This patch reworks event scheduler time computations, performing them in the time zone associated with the event. Also it allows times to be in the past. The patch adds time_zone column to mysql.event table. NOTE: The patch is almost final, but the bug#9953 should be pushed first. client/mysqldump.c: Before every CREATE EVENT, output its time zone. mysql-test/include/wait_condition.inc: Add optional $wait_timeout parameter. mysql-test/lib/init_db.sql: Add time_zone column. mysql-test/r/events.result: Update result. mysql-test/r/events_bugs.result: Update result. mysql-test/r/events_grant.result: Update result. mysql-test/r/events_restart_phase1.result: Update result. mysql-test/r/events_scheduling.result: Update result. mysql-test/r/mysqldump.result: Update result. mysql-test/r/ps.result: Update result. mysql-test/r/system_mysql_db.result: Update result. mysql-test/t/events.test: Remove STARTS from the result, as it depends on current time. mysql-test/t/events_bugs.test: Time in the past is no longer an error. mysql-test/t/events_restart_phase1.test: Fill new column 'time_zone' in mysql.event. mysql-test/t/events_scheduling.test: Cleanup: disable event scheduler. scripts/mysql_create_system_tables.sh: Add new column 'time_zone' to mysql.event. scripts/mysql_fix_privilege_tables.sql: Add new column 'time_zone' to mysql.event. sql/event_data_objects.cc: The essence of the change is the following: - for internal times use my_time_t instead of TIME. Assignment and comparison is done now on plain numbers. - in init_execute_at(), init_starts(), init_ends() convert given time to number of seconds since Epoch (aka Unix time, in UTC). - handle time_zone field loading and storing. - in get_next_time(), Unix time is converted back to event time zone, interval is added, and the result is converted to UTC again. - fix Event_timed::get_create_event() to report STARTS and ENDS. - before executing the event body we set thread time zone to the event time zone. sql/event_data_objects.h: Add time_zone member to Event_basic class. Store internal times in my_time_t (number of seconds since Epoch), rather than in broken down TIME structure. sql/event_db_repository.cc: Add time_zone column handling. Give a warning and do not create an event if its execution time is in the past, and ON COMPLETION NOT PRESERVE is set, because such an event should be dropped by that time. Also, do not allow ALTER EVENT to set execution time in the past when ON COMPLETION NOT PRESERVE is set. sql/event_db_repository.h: Add enum member for new time zone column. sql/event_queue.cc: Replace handling of broken down times with simple handling of my_time_t. sql/event_queue.h: Store internal times in my_time_t (number of seconds since Epoch), rather than in broken down TIME structure. sql/event_scheduler.cc: Add TODO comment. sql/events.cc: Send time_zone column for SHOW CREATE EVENT. sql/share/errmsg.txt: Update error message, and add two more errors. sql/sql_show.cc: Add TIME_ZONE column to the output of SHOW EVENTS. mysql-test/r/events_time_zone.result: BitKeeper file /home/tomash/src/mysql_ab/mysql-5.1-wl3698/mysql-test/r/events_time_zone.result mysql-test/t/events_time_zone.test: BitKeeper file /home/tomash/src/mysql_ab/mysql-5.1-wl3698/mysql-test/t/events_time_zone.test
314 lines
5.8 KiB
C++
314 lines
5.8 KiB
C++
#ifndef _EVENT_DATA_OBJECTS_H_
|
|
#define _EVENT_DATA_OBJECTS_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; version 2 of the License.
|
|
|
|
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_GET_FIELD_FAILED -2
|
|
#define EVEX_COMPILE_ERROR -3
|
|
#define EVEX_GENERAL_ERROR -4
|
|
#define EVEX_BAD_PARAMS -5
|
|
#define EVEX_MICROSECOND_UNSUP -6
|
|
|
|
|
|
class sp_head;
|
|
class Sql_alloc;
|
|
|
|
|
|
class Event_queue_element_for_exec
|
|
{
|
|
public:
|
|
Event_queue_element_for_exec(){};
|
|
~Event_queue_element_for_exec();
|
|
|
|
bool
|
|
init(LEX_STRING dbname, LEX_STRING name);
|
|
|
|
LEX_STRING dbname;
|
|
LEX_STRING name;
|
|
bool dropped;
|
|
THD *thd;
|
|
|
|
private:
|
|
/* Prevent use of these */
|
|
Event_queue_element_for_exec(const Event_queue_element_for_exec &);
|
|
void operator=(Event_queue_element_for_exec &);
|
|
};
|
|
|
|
|
|
class Event_basic
|
|
{
|
|
protected:
|
|
MEM_ROOT mem_root;
|
|
|
|
public:
|
|
LEX_STRING dbname;
|
|
LEX_STRING name;
|
|
LEX_STRING definer;// combination of user and host
|
|
|
|
Time_zone *time_zone;
|
|
|
|
Event_basic();
|
|
virtual ~Event_basic();
|
|
|
|
virtual int
|
|
load_from_row(THD *thd, TABLE *table) = 0;
|
|
|
|
protected:
|
|
bool
|
|
load_string_fields(Field **fields, ...);
|
|
|
|
bool
|
|
load_time_zone(THD *thd, const LEX_STRING tz_name);
|
|
};
|
|
|
|
|
|
|
|
class Event_queue_element : public Event_basic
|
|
{
|
|
protected:
|
|
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
|
|
};
|
|
|
|
enum enum_on_completion on_completion;
|
|
enum enum_status status;
|
|
|
|
my_time_t last_executed;
|
|
my_time_t execute_at;
|
|
my_time_t starts;
|
|
my_time_t ends;
|
|
my_bool starts_null;
|
|
my_bool ends_null;
|
|
my_bool execute_at_null;
|
|
|
|
longlong expression;
|
|
interval_type interval;
|
|
|
|
bool dropped;
|
|
|
|
uint execution_count;
|
|
|
|
Event_queue_element();
|
|
virtual ~Event_queue_element();
|
|
|
|
virtual int
|
|
load_from_row(THD *thd, TABLE *table);
|
|
|
|
bool
|
|
compute_next_execution_time();
|
|
|
|
void
|
|
mark_last_executed(THD *thd);
|
|
|
|
bool
|
|
update_timing_fields(THD *thd);
|
|
|
|
static void *operator new(size_t size)
|
|
{
|
|
void *p;
|
|
DBUG_ENTER("Event_queue_element::new(size)");
|
|
p= my_malloc(size, MYF(0));
|
|
DBUG_PRINT("info", ("alloc_ptr: 0x%lx", (long) p));
|
|
DBUG_RETURN(p);
|
|
}
|
|
|
|
static void operator delete(void *ptr, size_t size)
|
|
{
|
|
DBUG_ENTER("Event_queue_element::delete(ptr,size)");
|
|
DBUG_PRINT("enter", ("free_ptr: 0x%lx", (long) ptr));
|
|
TRASH(ptr, size);
|
|
my_free((gptr) ptr, MYF(0));
|
|
DBUG_VOID_RETURN;
|
|
}
|
|
};
|
|
|
|
|
|
class Event_timed : public Event_queue_element
|
|
{
|
|
Event_timed(const Event_timed &); /* Prevent use of these */
|
|
void operator=(Event_timed &);
|
|
|
|
public:
|
|
LEX_STRING body;
|
|
|
|
LEX_STRING definer_user;
|
|
LEX_STRING definer_host;
|
|
|
|
LEX_STRING comment;
|
|
|
|
ulonglong created;
|
|
ulonglong modified;
|
|
|
|
ulong sql_mode;
|
|
|
|
Event_timed();
|
|
virtual ~Event_timed();
|
|
|
|
void
|
|
init();
|
|
|
|
virtual int
|
|
load_from_row(THD *thd, TABLE *table);
|
|
|
|
int
|
|
get_create_event(THD *thd, String *buf);
|
|
};
|
|
|
|
|
|
class Event_job_data : public Event_basic
|
|
{
|
|
public:
|
|
sp_head *sphead;
|
|
|
|
LEX_STRING body;
|
|
LEX_STRING definer_user;
|
|
LEX_STRING definer_host;
|
|
|
|
ulong sql_mode;
|
|
|
|
uint execution_count;
|
|
|
|
Event_job_data();
|
|
virtual ~Event_job_data();
|
|
|
|
virtual int
|
|
load_from_row(THD *thd, TABLE *table);
|
|
|
|
int
|
|
execute(THD *thd);
|
|
|
|
int
|
|
compile(THD *thd, MEM_ROOT *mem_root);
|
|
private:
|
|
int
|
|
get_fake_create_event(THD *thd, String *buf);
|
|
|
|
Event_job_data(const Event_job_data &); /* Prevent use of these */
|
|
void operator=(Event_job_data &);
|
|
};
|
|
|
|
|
|
class Event_parse_data : public Sql_alloc
|
|
{
|
|
public:
|
|
enum enum_status
|
|
{
|
|
ENABLED = 1,
|
|
DISABLED
|
|
};
|
|
|
|
enum enum_on_completion
|
|
{
|
|
ON_COMPLETION_DROP = 1,
|
|
ON_COMPLETION_PRESERVE
|
|
};
|
|
enum enum_on_completion on_completion;
|
|
enum enum_status status;
|
|
/*
|
|
do_not_create will be set if STARTS time is in the past and
|
|
on_completion == ON_COMPLETION_DROP.
|
|
*/
|
|
bool do_not_create;
|
|
|
|
const uchar *body_begin;
|
|
|
|
LEX_STRING dbname;
|
|
LEX_STRING name;
|
|
LEX_STRING definer;// combination of user and host
|
|
LEX_STRING body;
|
|
LEX_STRING comment;
|
|
|
|
Item* item_starts;
|
|
Item* item_ends;
|
|
Item* item_execute_at;
|
|
|
|
my_time_t starts;
|
|
my_time_t ends;
|
|
my_time_t execute_at;
|
|
my_bool starts_null;
|
|
my_bool ends_null;
|
|
my_bool execute_at_null;
|
|
|
|
sp_name *identifier;
|
|
Item* item_expression;
|
|
longlong expression;
|
|
interval_type interval;
|
|
|
|
static Event_parse_data *
|
|
new_instance(THD *thd);
|
|
|
|
bool
|
|
check_parse_data(THD *thd);
|
|
|
|
void
|
|
init_body(THD *thd);
|
|
|
|
private:
|
|
|
|
void
|
|
init_definer(THD *thd);
|
|
|
|
void
|
|
init_name(THD *thd, sp_name *spn);
|
|
|
|
int
|
|
init_execute_at(THD *thd);
|
|
|
|
int
|
|
init_interval(THD *thd);
|
|
|
|
int
|
|
init_starts(THD *thd);
|
|
|
|
int
|
|
init_ends(THD *thd);
|
|
|
|
Event_parse_data();
|
|
~Event_parse_data();
|
|
|
|
void
|
|
report_bad_value(const char *item_name, Item *bad_item);
|
|
|
|
void
|
|
check_if_in_the_past(THD *thd, my_time_t ltime_utc);
|
|
|
|
Event_parse_data(const Event_parse_data &); /* Prevent use of these */
|
|
void operator=(Event_parse_data &);
|
|
};
|
|
|
|
|
|
/* Compares only the schema part of the identifier */
|
|
bool
|
|
event_basic_db_equal(LEX_STRING db, Event_basic *et);
|
|
|
|
/* Compares the whole identifier*/
|
|
bool
|
|
event_basic_identifier_equal(LEX_STRING db, LEX_STRING name, Event_basic *b);
|
|
|
|
|
|
#endif /* _EVENT_DATA_OBJECTS_H_ */
|