summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sql/event_db_repository.cc173
-rw-r--r--sql/event_db_repository.h28
-rw-r--r--sql/event_scheduler.cc2
-rw-r--r--sql/events.cc47
-rw-r--r--sql/events.h3
-rw-r--r--sql/sql_show.cc181
-rw-r--r--sql/sql_show.h2
7 files changed, 247 insertions, 189 deletions
diff --git a/sql/event_db_repository.cc b/sql/event_db_repository.cc
index 249910c5f50..96d2b6c957f 100644
--- a/sql/event_db_repository.cc
+++ b/sql/event_db_repository.cc
@@ -20,6 +20,7 @@
#include "sp_head.h"
#include "sp.h"
#include "events.h"
+#include "sql_show.h"
#define EVEX_DB_FIELD_LEN 64
#define EVEX_NAME_FIELD_LEN 64
@@ -188,8 +189,7 @@ evex_fill_row(THD *thd, TABLE *table, Event_timed *et, my_bool is_update)
if (et->expression)
{
table->field[ET_FIELD_INTERVAL_EXPR]->set_notnull();
- table->field[ET_FIELD_INTERVAL_EXPR]->
- store((longlong)et->expression, true);
+ table->field[ET_FIELD_INTERVAL_EXPR]->store((longlong)et->expression, true);
table->field[ET_FIELD_TRANSIENT_INTERVAL]->set_notnull();
/*
@@ -277,15 +277,180 @@ evex_db_find_event_by_name(THD *thd, const LEX_STRING dbname,
/*
+ Performs an index scan of event_table (mysql.event) and fills schema_table.
+
+ Synopsis
+ Event_db_repository::index_read_for_db_for_i_s()
+ thd Thread
+ schema_table The I_S.EVENTS table
+ event_table The event table to use for loading (mysql.event)
+
+ Returns
+ 0 OK
+ 1 Error
+*/
+
+int
+Event_db_repository::index_read_for_db_for_i_s(THD *thd, TABLE *schema_table,
+ TABLE *event_table, char *db)
+{
+ int ret=0;
+ CHARSET_INFO *scs= system_charset_info;
+ KEY *key_info;
+ uint key_len;
+ byte *key_buf= NULL;
+ LINT_INIT(key_buf);
+
+ DBUG_ENTER("Event_db_repository::index_read_for_db_for_i_s");
+
+ DBUG_PRINT("info", ("Using prefix scanning on PK"));
+ event_table->file->ha_index_init(0, 1);
+ event_table->field[ET_FIELD_DB]->store(db, strlen(db), scs);
+ key_info= event_table->key_info;
+ key_len= key_info->key_part[0].store_length;
+
+ if (!(key_buf= (byte *)alloc_root(thd->mem_root, key_len)))
+ {
+ ret= 1;
+ /* don't send error, it would be done by sql_alloc_error_handler() */
+ }
+ else
+ {
+ key_copy(key_buf, event_table->record[0], key_info, key_len);
+ if (!(ret= event_table->file->index_read(event_table->record[0], key_buf,
+ key_len, HA_READ_PREFIX)))
+ {
+ DBUG_PRINT("info",("Found rows. Let's retrieve them. ret=%d", ret));
+ do
+ {
+ ret= copy_event_to_schema_table(thd, schema_table, event_table);
+ if (ret == 0)
+ ret= event_table->file->index_next_same(event_table->record[0],
+ key_buf, key_len);
+ } while (ret == 0);
+ }
+ DBUG_PRINT("info", ("Scan finished. ret=%d", ret));
+ }
+ event_table->file->ha_index_end();
+ /* ret is guaranteed to be != 0 */
+ if (ret == HA_ERR_END_OF_FILE || ret == HA_ERR_KEY_NOT_FOUND)
+ DBUG_RETURN(0);
+ DBUG_RETURN(1);
+}
+
+
+/*
+ Performs a table scan of event_table (mysql.event) and fills schema_table.
+
+ Synopsis
+ Events_db_repository::table_scan_all_for_i_s()
+ thd Thread
+ schema_table The I_S.EVENTS in memory table
+ event_table The event table to use for loading.
+
+ Returns
+ 0 OK
+ 1 Error
+*/
+
+int
+Event_db_repository::table_scan_all_for_i_s(THD *thd, TABLE *schema_table,
+ TABLE *event_table)
+{
+ int ret;
+ READ_RECORD read_record_info;
+
+ DBUG_ENTER("Event_db_repository::table_scan_all_for_i_s");
+ init_read_record(&read_record_info, thd, event_table, NULL, 1, 0);
+
+ /*
+ rr_sequential, in read_record(), returns 137==HA_ERR_END_OF_FILE,
+ but rr_handle_error returns -1 for that reason. Thus, read_record()
+ returns -1 eventually.
+ */
+ do
+ {
+ ret= read_record_info.read_record(&read_record_info);
+ if (ret == 0)
+ ret= copy_event_to_schema_table(thd, schema_table, event_table);
+ }
+ while (ret == 0);
+
+ DBUG_PRINT("info", ("Scan finished. ret=%d", ret));
+ end_read_record(&read_record_info);
+
+ /* ret is guaranteed to be != 0 */
+ DBUG_RETURN(ret == -1? 0:1);
+}
+
+
+/*
+ Fills I_S.EVENTS with data loaded from mysql.event. Also used by
+ SHOW EVENTS
+
+ Synopsis
+ Event_db_repository::fill_schema_events()
+ thd Thread
+ tables The schema table
+ db If not NULL then get events only from this schema
+
+ Returns
+ 0 OK
+ 1 Error
+*/
+
+int
+Event_db_repository::fill_schema_events(THD *thd, TABLE_LIST *tables, char *db)
+{
+ TABLE *schema_table= tables->table;
+ TABLE *event_table= NULL;
+ Open_tables_state backup;
+ int ret= 0;
+
+ DBUG_ENTER("Event_db_repository::fill_schema_events");
+ DBUG_PRINT("info",("db=%s", db? db:"(null)"));
+
+ thd->reset_n_backup_open_tables_state(&backup);
+ if (open_event_table(thd, TL_READ, &event_table))
+ {
+ sql_print_error("Table mysql.event is damaged.");
+ thd->restore_backup_open_tables_state(&backup);
+ DBUG_RETURN(1);
+ }
+
+ /*
+ 1. SELECT I_S => use table scan. I_S.EVENTS does not guarantee order
+ thus we won't order it. OTOH, SHOW EVENTS will be
+ ordered.
+ 2. SHOW EVENTS => PRIMARY KEY with prefix scanning on (db)
+ Reasoning: Events are per schema, therefore a scan over an index
+ will save use from doing a table scan and comparing
+ every single row's `db` with the schema which we show.
+ */
+ if (db)
+ ret= index_read_for_db_for_i_s(thd, schema_table, event_table, db);
+ else
+ ret= table_scan_all_for_i_s(thd, schema_table, event_table);
+
+ close_thread_tables(thd);
+ thd->restore_backup_open_tables_state(&backup);
+
+ DBUG_PRINT("info", ("Return code=%d", ret));
+ DBUG_RETURN(ret);
+}
+
+
+/*
Looks for a named event in mysql.event and in case of success returns
an object will data loaded from the table.
SYNOPSIS
- db_find_event()
+ Event_db_repository::find_event()
thd THD
name the name of the event to find
ett event's data if event is found
tbl TABLE object to use when not NULL
+ root On which root to load the event
NOTES
1) Use sp_name for look up, return in **ett if found
@@ -308,7 +473,7 @@ Event_db_repository::find_event(THD *thd, sp_name *name, Event_timed **ett,
if (tbl)
table= tbl;
- else if (Events::get_instance()->db_repository.open_event_table(thd, TL_READ, &table))
+ else if (open_event_table(thd, TL_READ, &table))
{
my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
ret= EVEX_GENERAL_ERROR;
diff --git a/sql/event_db_repository.h b/sql/event_db_repository.h
index c0cfccf215a..1cbee96b68f 100644
--- a/sql/event_db_repository.h
+++ b/sql/event_db_repository.h
@@ -43,6 +43,17 @@ evex_db_find_event_by_name(THD *thd, const LEX_STRING dbname,
const LEX_STRING ev_name,
TABLE *table);
+int
+events_table_index_read_for_db(THD *thd, TABLE *schema_table,
+ TABLE *event_table);
+
+int
+events_table_scan_all(THD *thd, TABLE *schema_table, TABLE *event_table);
+
+int
+fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */);
+
+
class Event_queue_element;
class Event_db_repository
@@ -58,9 +69,6 @@ public:
deinit_repository();
int
- open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
-
- int
create_event(THD *thd, Event_timed *et, my_bool create_if_not,
uint *rows_affected);
@@ -86,11 +94,23 @@ public:
int
find_event_by_name(THD *thd, LEX_STRING db, LEX_STRING name, TABLE *table);
-private:
int
+ open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
+
+ int
+ fill_schema_events(THD *thd, TABLE_LIST *tables, char *db);
+
+private:
+ int
drop_events_by_field(THD *thd, enum enum_events_table_field field,
LEX_STRING field_value);
+ int
+ index_read_for_db_for_i_s(THD *thd, TABLE *schema_table, TABLE *event_table,
+ char *db);
+
+ int
+ table_scan_all_for_i_s(THD *thd, TABLE *schema_table, TABLE *event_table);
MEM_ROOT repo_root;
diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc
index 60c9cda0a56..cb500de53b9 100644
--- a/sql/event_scheduler.cc
+++ b/sql/event_scheduler.cc
@@ -2159,7 +2159,7 @@ Event_scheduler::load_events_from_db(THD *thd)
DBUG_RETURN(EVEX_GENERAL_ERROR);
}
- if ((ret= Events::get_instance()->open_event_table(thd, TL_READ, &table)))
+ if ((ret= db_repository->open_event_table(thd, TL_READ, &table)))
{
sql_print_error("SCHEDULER: Table mysql.event is damaged. Can not open.");
DBUG_RETURN(EVEX_OPEN_TABLE_FAILED);
diff --git a/sql/events.cc b/sql/events.cc
index 52e814043d8..a5af196af2a 100644
--- a/sql/events.cc
+++ b/sql/events.cc
@@ -88,6 +88,15 @@ int sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs)
(unsigned char *) t.str,t.length, 0);
}
+/*
+ Accessor for the singleton instance.
+
+ SYNOPSIS
+ Events::get_instance()
+
+ RETURN VALUE
+ address
+*/
Events *
Events::get_instance()
@@ -110,7 +119,7 @@ Events::get_instance()
interval - the interval type (for instance YEAR_MONTH)
expression - the value in the lowest entity
- RETURNS
+ RETURN VALUE
0 - OK
1 - Error
*/
@@ -563,6 +572,42 @@ Events::dump_internal_status(THD *thd)
/*
+ Proxy for Event_db_repository::fill_schema_events.
+ Callback for I_S from sql_show.cc
+
+ SYNOPSIS
+ Events::fill_schema_events()
+ thd Thread
+ tables The schema table
+ cond Unused
+
+ RETURN VALUE
+ 0 OK
+ !0 Error
+*/
+
+int
+Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
+{
+ char *db= NULL;
+ DBUG_ENTER("Events::fill_schema_events");
+ /*
+ If it's SHOW EVENTS then thd->lex->select_lex.db is guaranteed not to
+ be NULL. Let's do an assert anyway.
+ */
+ if (thd->lex->orig_sql_command == SQLCOM_SHOW_EVENTS)
+ {
+ DBUG_ASSERT(thd->lex->select_lex.db);
+ if (check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0,
+ is_schema_db(thd->lex->select_lex.db)))
+ DBUG_RETURN(1);
+ db= thd->lex->select_lex.db;
+ }
+ DBUG_RETURN(get_instance()->db_repository.fill_schema_events(thd, tables, db));
+}
+
+
+/*
Inits Events mutexes
SYNOPSIS
diff --git a/sql/events.h b/sql/events.h
index 339f87c3806..3a7d1f8bc5e 100644
--- a/sql/events.h
+++ b/sql/events.h
@@ -90,6 +90,9 @@ public:
int
drop_schema_events(THD *thd, char *db);
+
+ static int
+ fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */);
int
dump_internal_status(THD *thd);
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 77906973a38..bf69d3a0986 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -4160,7 +4160,7 @@ extern LEX_STRING interval_type_to_name[];
1 Error
*/
-static int
+int
copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
{
const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
@@ -4295,183 +4295,6 @@ copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
}
-/*
- Performs an index scan of event_table (mysql.event) and fills schema_table.
-
- Synopsis
- events_table_index_read_for_db()
- thd Thread
- schema_table The I_S.EVENTS table
- event_table The event table to use for loading (mysql.event)
-
- Returns
- 0 OK
- 1 Error
-*/
-
-static
-int events_table_index_read_for_db(THD *thd, TABLE *schema_table,
- TABLE *event_table)
-{
- int ret=0;
- CHARSET_INFO *scs= system_charset_info;
- KEY *key_info;
- uint key_len;
- byte *key_buf= NULL;
- LINT_INIT(key_buf);
-
- DBUG_ENTER("schema_events_do_index_scan");
-
- DBUG_PRINT("info", ("Using prefix scanning on PK"));
- event_table->file->ha_index_init(0, 1);
- event_table->field[ET_FIELD_DB]->
- store(thd->lex->select_lex.db, strlen(thd->lex->select_lex.db), scs);
- key_info= event_table->key_info;
- key_len= key_info->key_part[0].store_length;
-
- if (!(key_buf= (byte *)alloc_root(thd->mem_root, key_len)))
- {
- ret= 1;
- /* don't send error, it would be done by sql_alloc_error_handler() */
- }
- else
- {
- key_copy(key_buf, event_table->record[0], key_info, key_len);
- if (!(ret= event_table->file->index_read(event_table->record[0], key_buf,
- key_len, HA_READ_PREFIX)))
- {
- DBUG_PRINT("info",("Found rows. Let's retrieve them. ret=%d", ret));
- do
- {
- ret= copy_event_to_schema_table(thd, schema_table, event_table);
- if (ret == 0)
- ret= event_table->file->index_next_same(event_table->record[0],
- key_buf, key_len);
- } while (ret == 0);
- }
- DBUG_PRINT("info", ("Scan finished. ret=%d", ret));
- }
- event_table->file->ha_index_end();
- /* ret is guaranteed to be != 0 */
- if (ret == HA_ERR_END_OF_FILE || ret == HA_ERR_KEY_NOT_FOUND)
- DBUG_RETURN(0);
- DBUG_RETURN(1);
-}
-
-
-/*
- Performs a table scan of event_table (mysql.event) and fills schema_table.
-
- Synopsis
- events_table_scan_all()
- thd Thread
- schema_table The I_S.EVENTS in memory table
- event_table The event table to use for loading.
-
- Returns
- 0 OK
- 1 Error
-*/
-
-static
-int events_table_scan_all(THD *thd, TABLE *schema_table,
- TABLE *event_table)
-{
- int ret;
- READ_RECORD read_record_info;
-
- DBUG_ENTER("schema_events_do_table_scan");
- init_read_record(&read_record_info, thd, event_table, NULL, 1, 0);
-
- /*
- rr_sequential, in read_record(), returns 137==HA_ERR_END_OF_FILE,
- but rr_handle_error returns -1 for that reason. Thus, read_record()
- returns -1 eventually.
- */
- do
- {
- ret= read_record_info.read_record(&read_record_info);
- if (ret == 0)
- ret= copy_event_to_schema_table(thd, schema_table, event_table);
- }
- while (ret == 0);
-
- DBUG_PRINT("info", ("Scan finished. ret=%d", ret));
- end_read_record(&read_record_info);
-
- /* ret is guaranteed to be != 0 */
- DBUG_RETURN(ret == -1? 0:1);
-}
-
-
-/*
- Fills I_S.EVENTS with data loaded from mysql.event. Also used by
- SHOW EVENTS
-
- Synopsis
- fill_schema_events()
- thd Thread
- tables The schema table
- cond Unused
-
- Returns
- 0 OK
- 1 Error
-*/
-
-int fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
-{
- TABLE *schema_table= tables->table;
- TABLE *event_table= NULL;
- Open_tables_state backup;
- int ret= 0;
-
- DBUG_ENTER("fill_schema_events");
- /*
- If it's SHOW EVENTS then thd->lex->select_lex.db is guaranteed not to
- be NULL. Let's do an assert anyway.
- */
- if (thd->lex->orig_sql_command == SQLCOM_SHOW_EVENTS)
- {
- DBUG_ASSERT(thd->lex->select_lex.db);
- if (check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0,
- is_schema_db(thd->lex->select_lex.db)))
- DBUG_RETURN(1);
- }
-
- DBUG_PRINT("info",("db=%s", thd->lex->select_lex.db?
- thd->lex->select_lex.db:"(null)"));
-
- thd->reset_n_backup_open_tables_state(&backup);
- if (Events::get_instance()->open_event_table(thd, TL_READ, &event_table))
- {
- sql_print_error("Table mysql.event is damaged.");
- thd->restore_backup_open_tables_state(&backup);
- DBUG_RETURN(1);
- }
-
- /*
- 1. SELECT I_S => use table scan. I_S.EVENTS does not guarantee order
- thus we won't order it. OTOH, SHOW EVENTS will be
- ordered.
- 2. SHOW EVENTS => PRIMARY KEY with prefix scanning on (db)
- Reasoning: Events are per schema, therefore a scan over an index
- will save use from doing a table scan and comparing
- every single row's `db` with the schema which we show.
- */
- if (thd->lex->orig_sql_command == SQLCOM_SHOW_EVENTS)
- ret= events_table_index_read_for_db(thd, schema_table, event_table);
- else
- ret= events_table_scan_all(thd, schema_table, event_table);
-
- close_thread_tables(thd);
- thd->restore_backup_open_tables_state(&backup);
-
- DBUG_PRINT("info", ("Return code=%d", ret));
- DBUG_RETURN(ret);
-}
-
-
int fill_open_tables(THD *thd, TABLE_LIST *tables, COND *cond)
{
DBUG_ENTER("fill_open_tables");
@@ -5568,7 +5391,7 @@ ST_SCHEMA_TABLE schema_tables[]=
{"ENGINES", engines_fields_info, create_schema_table,
fill_schema_engines, make_old_format, 0, -1, -1, 0},
{"EVENTS", events_fields_info, create_schema_table,
- fill_schema_events, make_old_format, 0, -1, -1, 0},
+ Events::fill_schema_events, make_old_format, 0, -1, -1, 0},
{"FILES", files_fields_info, create_schema_table,
fill_schema_files, 0, 0, -1, -1, 0},
{"KEY_COLUMN_USAGE", key_column_usage_fields_info, create_schema_table,
diff --git a/sql/sql_show.h b/sql/sql_show.h
index 6fce5e94ca3..681d1232b39 100644
--- a/sql/sql_show.h
+++ b/sql/sql_show.h
@@ -14,4 +14,6 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
HA_CREATE_INFO *create_info_arg);
int view_store_create_info(THD *thd, TABLE_LIST *table, String *buff);
+int copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table);
+
#endif /* SQL_SHOW_H */