Commit 03e0a231 authored by andrey@lmy004's avatar andrey@lmy004

WL#3337 (Events new architecture)

Cut number 6. Move code from sql_show.cc to event_db_repository.cc
that more belongs to the latter.
parent 9309fae9
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "sp_head.h" #include "sp_head.h"
#include "sp.h" #include "sp.h"
#include "events.h" #include "events.h"
#include "sql_show.h"
#define EVEX_DB_FIELD_LEN 64 #define EVEX_DB_FIELD_LEN 64
#define EVEX_NAME_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) ...@@ -188,8 +189,7 @@ evex_fill_row(THD *thd, TABLE *table, Event_timed *et, my_bool is_update)
if (et->expression) if (et->expression)
{ {
table->field[ET_FIELD_INTERVAL_EXPR]->set_notnull(); table->field[ET_FIELD_INTERVAL_EXPR]->set_notnull();
table->field[ET_FIELD_INTERVAL_EXPR]-> table->field[ET_FIELD_INTERVAL_EXPR]->store((longlong)et->expression, true);
store((longlong)et->expression, true);
table->field[ET_FIELD_TRANSIENT_INTERVAL]->set_notnull(); table->field[ET_FIELD_TRANSIENT_INTERVAL]->set_notnull();
/* /*
...@@ -276,16 +276,181 @@ evex_db_find_event_by_name(THD *thd, const LEX_STRING dbname, ...@@ -276,16 +276,181 @@ 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 Looks for a named event in mysql.event and in case of success returns
an object will data loaded from the table. an object will data loaded from the table.
SYNOPSIS SYNOPSIS
db_find_event() Event_db_repository::find_event()
thd THD thd THD
name the name of the event to find name the name of the event to find
ett event's data if event is found ett event's data if event is found
tbl TABLE object to use when not NULL tbl TABLE object to use when not NULL
root On which root to load the event
NOTES NOTES
1) Use sp_name for look up, return in **ett if found 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, ...@@ -308,7 +473,7 @@ Event_db_repository::find_event(THD *thd, sp_name *name, Event_timed **ett,
if (tbl) if (tbl)
table= 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)); my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
ret= EVEX_GENERAL_ERROR; ret= EVEX_GENERAL_ERROR;
......
...@@ -43,6 +43,17 @@ evex_db_find_event_by_name(THD *thd, const LEX_STRING dbname, ...@@ -43,6 +43,17 @@ evex_db_find_event_by_name(THD *thd, const LEX_STRING dbname,
const LEX_STRING ev_name, const LEX_STRING ev_name,
TABLE *table); 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_queue_element;
class Event_db_repository class Event_db_repository
...@@ -57,9 +68,6 @@ class Event_db_repository ...@@ -57,9 +68,6 @@ class Event_db_repository
void void
deinit_repository(); deinit_repository();
int
open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
int int
create_event(THD *thd, Event_timed *et, my_bool create_if_not, create_event(THD *thd, Event_timed *et, my_bool create_if_not,
uint *rows_affected); uint *rows_affected);
...@@ -86,11 +94,23 @@ class Event_db_repository ...@@ -86,11 +94,23 @@ class Event_db_repository
int int
find_event_by_name(THD *thd, LEX_STRING db, LEX_STRING name, TABLE *table); 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 int
drop_events_by_field(THD *thd, enum enum_events_table_field field, drop_events_by_field(THD *thd, enum enum_events_table_field field,
LEX_STRING field_value); 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; MEM_ROOT repo_root;
......
...@@ -2159,7 +2159,7 @@ Event_scheduler::load_events_from_db(THD *thd) ...@@ -2159,7 +2159,7 @@ Event_scheduler::load_events_from_db(THD *thd)
DBUG_RETURN(EVEX_GENERAL_ERROR); 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."); sql_print_error("SCHEDULER: Table mysql.event is damaged. Can not open.");
DBUG_RETURN(EVEX_OPEN_TABLE_FAILED); DBUG_RETURN(EVEX_OPEN_TABLE_FAILED);
......
...@@ -88,6 +88,15 @@ int sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs) ...@@ -88,6 +88,15 @@ int sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs)
(unsigned char *) t.str,t.length, 0); (unsigned char *) t.str,t.length, 0);
} }
/*
Accessor for the singleton instance.
SYNOPSIS
Events::get_instance()
RETURN VALUE
address
*/
Events * Events *
Events::get_instance() Events::get_instance()
...@@ -110,7 +119,7 @@ Events::get_instance() ...@@ -110,7 +119,7 @@ Events::get_instance()
interval - the interval type (for instance YEAR_MONTH) interval - the interval type (for instance YEAR_MONTH)
expression - the value in the lowest entity expression - the value in the lowest entity
RETURNS RETURN VALUE
0 - OK 0 - OK
1 - Error 1 - Error
*/ */
...@@ -562,6 +571,42 @@ Events::dump_internal_status(THD *thd) ...@@ -562,6 +571,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 Inits Events mutexes
......
...@@ -90,6 +90,9 @@ class Events ...@@ -90,6 +90,9 @@ class Events
int int
drop_schema_events(THD *thd, char *db); drop_schema_events(THD *thd, char *db);
static int
fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */);
int int
dump_internal_status(THD *thd); dump_internal_status(THD *thd);
......
...@@ -4160,7 +4160,7 @@ extern LEX_STRING interval_type_to_name[]; ...@@ -4160,7 +4160,7 @@ extern LEX_STRING interval_type_to_name[];
1 Error 1 Error
*/ */
static int int
copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table) copy_event_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
{ {
const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS; 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) ...@@ -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) int fill_open_tables(THD *thd, TABLE_LIST *tables, COND *cond)
{ {
DBUG_ENTER("fill_open_tables"); DBUG_ENTER("fill_open_tables");
...@@ -5568,7 +5391,7 @@ ST_SCHEMA_TABLE schema_tables[]= ...@@ -5568,7 +5391,7 @@ ST_SCHEMA_TABLE schema_tables[]=
{"ENGINES", engines_fields_info, create_schema_table, {"ENGINES", engines_fields_info, create_schema_table,
fill_schema_engines, make_old_format, 0, -1, -1, 0}, fill_schema_engines, make_old_format, 0, -1, -1, 0},
{"EVENTS", events_fields_info, create_schema_table, {"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, {"FILES", files_fields_info, create_schema_table,
fill_schema_files, 0, 0, -1, -1, 0}, fill_schema_files, 0, 0, -1, -1, 0},
{"KEY_COLUMN_USAGE", key_column_usage_fields_info, create_schema_table, {"KEY_COLUMN_USAGE", key_column_usage_fields_info, create_schema_table,
......
...@@ -14,4 +14,6 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet, ...@@ -14,4 +14,6 @@ int store_create_info(THD *thd, TABLE_LIST *table_list, String *packet,
HA_CREATE_INFO *create_info_arg); HA_CREATE_INFO *create_info_arg);
int view_store_create_info(THD *thd, TABLE_LIST *table, String *buff); 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 */ #endif /* SQL_SHOW_H */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment