summaryrefslogtreecommitdiff
path: root/sql
diff options
context:
space:
mode:
authorunknown <andrey@lmy004.>2006-05-29 15:16:07 +0200
committerunknown <andrey@lmy004.>2006-05-29 15:16:07 +0200
commitf32d0ec6bfaad7a1512f283ae0f9c2e2f7b234e8 (patch)
treed4042ff7b73cd9d3b537a6781cdf1d21216e36db /sql
parente05d55de5ff6c95143fb1096da8019ab5fb7c6a2 (diff)
parent606abf255d65acfee5e14ea8cf9dc9faacef0e09 (diff)
downloadmariadb-git-f32d0ec6bfaad7a1512f283ae0f9c2e2f7b234e8.tar.gz
Merge lmy004.:/work/mysql-5.1-new-vanilla
into lmy004.:/work/mysql-5.1-runtime sql/event_scheduler.cc: Auto merged sql/sql_parse.cc: Auto merged sql/sql_show.cc: Auto merged
Diffstat (limited to 'sql')
-rw-r--r--sql/event.cc87
-rw-r--r--sql/event.h2
-rw-r--r--sql/event_priv.h5
-rw-r--r--sql/event_scheduler.cc18
-rw-r--r--sql/event_timed.cc52
-rw-r--r--sql/sql_parse.cc10
-rw-r--r--sql/sql_show.cc262
7 files changed, 272 insertions, 164 deletions
diff --git a/sql/event.cc b/sql/event.cc
index 7c3f17304aa..5273394640c 100644
--- a/sql/event.cc
+++ b/sql/event.cc
@@ -456,7 +456,7 @@ Events::open_event_table(THD *thd, enum thr_lock_type lock_type,
SYNOPSIS
evex_db_find_event_aux()
thd Thread context
- et evet_timed object containing dbname, name & definer
+ et event_timed object containing dbname & name
table TABLE object for open mysql.event table.
RETURN VALUE
@@ -467,8 +467,7 @@ Events::open_event_table(THD *thd, enum thr_lock_type lock_type,
inline int
evex_db_find_event_aux(THD *thd, Event_timed *et, TABLE *table)
{
- return evex_db_find_event_by_name(thd, et->dbname, et->name,
- et->definer, table);
+ return evex_db_find_event_by_name(thd, et->dbname, et->name, table);
}
@@ -490,7 +489,6 @@ evex_db_find_event_aux(THD *thd, Event_timed *et, TABLE *table)
int
evex_db_find_event_by_name(THD *thd, const LEX_STRING dbname,
const LEX_STRING ev_name,
- const LEX_STRING user_name,
TABLE *table)
{
byte key[MAX_KEY_LENGTH];
@@ -505,18 +503,14 @@ evex_db_find_event_by_name(THD *thd, const LEX_STRING dbname,
same fields.
*/
if (dbname.length > table->field[Events::FIELD_DB]->field_length ||
- ev_name.length > table->field[Events::FIELD_NAME]->field_length ||
- user_name.length > table->field[Events::FIELD_DEFINER]->field_length)
+ ev_name.length > table->field[Events::FIELD_NAME]->field_length)
DBUG_RETURN(EVEX_KEY_NOT_FOUND);
table->field[Events::FIELD_DB]->store(dbname.str, dbname.length,
- &my_charset_bin);
+ &my_charset_bin);
table->field[Events::FIELD_NAME]->store(ev_name.str, ev_name.length,
- &my_charset_bin);
- table->field[Events::FIELD_DEFINER]->store(user_name.str,
- user_name.length,
- &my_charset_bin);
+ &my_charset_bin);
key_copy(key, table->record[0], table->key_info, table->key_info->key_length);
@@ -553,6 +547,7 @@ evex_db_find_event_by_name(THD *thd, const LEX_STRING dbname,
static int
evex_fill_row(THD *thd, TABLE *table, Event_timed *et, my_bool is_update)
{
+ CHARSET_INFO *scs= system_charset_info;
enum Events::enum_table_field field_num;
DBUG_ENTER("evex_fill_row");
@@ -561,20 +556,23 @@ evex_fill_row(THD *thd, TABLE *table, Event_timed *et, my_bool is_update)
DBUG_PRINT("info", ("name =[%s]", et->name.str));
DBUG_PRINT("info", ("body =[%s]", et->body.str));
+ if (table->field[field_num= Events::FIELD_DEFINER]->
+ store(et->definer.str, et->definer.length, scs))
+ goto err_truncate;
+
if (table->field[field_num= Events::FIELD_DB]->
- store(et->dbname.str, et->dbname.length, system_charset_info))
- goto trunc_err;
+ store(et->dbname.str, et->dbname.length, scs))
+ goto err_truncate;
if (table->field[field_num= Events::FIELD_NAME]->
- store(et->name.str, et->name.length, system_charset_info))
- goto trunc_err;
+ store(et->name.str, et->name.length, scs))
+ goto err_truncate;
/* both ON_COMPLETION and STATUS are NOT NULL thus not calling set_notnull()*/
table->field[Events::FIELD_ON_COMPLETION]->
store((longlong)et->on_completion, true);
- table->field[Events::FIELD_STATUS]->
- store((longlong)et->status, true);
+ table->field[Events::FIELD_STATUS]->store((longlong)et->status, true);
/*
Change the SQL_MODE only if body was present in an ALTER EVENT and of course
@@ -586,8 +584,8 @@ evex_fill_row(THD *thd, TABLE *table, Event_timed *et, my_bool is_update)
store((longlong)thd->variables.sql_mode, true);
if (table->field[field_num= Events::FIELD_BODY]->
- store(et->body.str, et->body.length, system_charset_info))
- goto trunc_err;
+ store(et->body.str, et->body.length, scs))
+ goto err_truncate;
}
if (et->expression)
@@ -645,12 +643,12 @@ evex_fill_row(THD *thd, TABLE *table, Event_timed *et, my_bool is_update)
if (et->comment.str)
{
if (table->field[field_num= Events::FIELD_COMMENT]->
- store(et->comment.str, et->comment.length, system_charset_info))
- goto trunc_err;
+ store(et->comment.str, et->comment.length, scs))
+ goto err_truncate;
}
DBUG_RETURN(0);
-trunc_err:
+err_truncate:
my_error(ER_EVENT_DATA_TOO_LONG, MYF(0), table->field[field_num]->field_name);
DBUG_RETURN(EVEX_GENERAL_ERROR);
}
@@ -746,13 +744,6 @@ db_create_event(THD *thd, Event_timed *et, my_bool create_if_not,
goto err;
}
- if ((ret=table->field[Events::FIELD_DEFINER]->
- store(et->definer.str, et->definer.length, scs)))
- {
- my_error(ER_EVENT_STORE_FAILED, MYF(0), et->name.str, ret);
- goto err;
- }
-
((Field_timestamp *)table->field[Events::FIELD_CREATED])->set_time();
/*
@@ -816,6 +807,7 @@ err:
static int
db_update_event(THD *thd, Event_timed *et, sp_name *new_name)
{
+ CHARSET_INFO *scs= system_charset_info;
TABLE *table;
int ret= EVEX_OPEN_TABLE_FAILED;
DBUG_ENTER("db_update_event");
@@ -835,22 +827,21 @@ db_update_event(THD *thd, Event_timed *et, sp_name *new_name)
/* first look whether we overwrite */
if (new_name)
{
- if (!sortcmp_lex_string(et->name, new_name->m_name, system_charset_info) &&
- !sortcmp_lex_string(et->dbname, new_name->m_db, system_charset_info))
+ if (!sortcmp_lex_string(et->name, new_name->m_name, scs) &&
+ !sortcmp_lex_string(et->dbname, new_name->m_db, scs))
{
my_error(ER_EVENT_SAME_NAME, MYF(0), et->name.str);
goto err;
}
- if (!evex_db_find_event_by_name(thd, new_name->m_db, new_name->m_name,
- et->definer, table))
+ if (!evex_db_find_event_by_name(thd,new_name->m_db,new_name->m_name,table))
{
my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), new_name->m_name.str);
goto err;
}
}
/*
- ...and then whether there is such an event. don't exchange the blocks
+ ...and then if there is such an event. Don't exchange the blocks
because you will get error 120 from table handler because new_name will
overwrite the key and SE will tell us that it cannot find the already found
row (copied into record[1] later
@@ -866,16 +857,19 @@ db_update_event(THD *thd, Event_timed *et, sp_name *new_name)
/* Don't update create on row update. */
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
- /* evex_fill_row() calls my_error() in case of error so no need to handle it here */
+ /*
+ evex_fill_row() calls my_error() in case of error so no need to
+ handle it here
+ */
if ((ret= evex_fill_row(thd, table, et, true)))
goto err;
if (new_name)
{
table->field[Events::FIELD_DB]->
- store(new_name->m_db.str, new_name->m_db.length, system_charset_info);
+ store(new_name->m_db.str, new_name->m_db.length, scs);
table->field[Events::FIELD_NAME]->
- store(new_name->m_name.str, new_name->m_name.length, system_charset_info);
+ store(new_name->m_name.str, new_name->m_name.length, scs);
}
if ((ret= table->file->ha_update_row(table->record[1], table->record[0])))
@@ -903,7 +897,6 @@ err:
db_find_event()
thd THD
name the name of the event to find
- definer who owns the event
ett event's data if event is found
tbl TABLE object to use when not NULL
@@ -917,12 +910,12 @@ err:
*/
int
-db_find_event(THD *thd, sp_name *name, LEX_STRING *definer, Event_timed **ett,
- TABLE *tbl, MEM_ROOT *root)
+db_find_event(THD *thd, sp_name *name, Event_timed **ett, TABLE *tbl,
+ MEM_ROOT *root)
{
TABLE *table;
int ret;
- Event_timed *et=NULL;
+ Event_timed *et= NULL;
DBUG_ENTER("db_find_event");
DBUG_PRINT("enter", ("name: %*s", name->m_name.length, name->m_name.str));
@@ -938,8 +931,7 @@ db_find_event(THD *thd, sp_name *name, LEX_STRING *definer, Event_timed **ett,
goto done;
}
- if ((ret= evex_db_find_event_by_name(thd, name->m_db, name->m_name, *definer,
- table)))
+ if ((ret= evex_db_find_event_by_name(thd, name->m_db, name->m_name, table)))
{
my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name->m_name.str);
goto done;
@@ -959,7 +951,7 @@ db_find_event(THD *thd, sp_name *name, LEX_STRING *definer, Event_timed **ett,
}
done:
- if (ret && et)
+ if (ret)
{
delete et;
et= 0;
@@ -994,7 +986,7 @@ done:
int
Events::create_event(THD *thd, Event_timed *et, uint create_options,
- uint *rows_affected)
+ uint *rows_affected)
{
int ret;
@@ -1166,7 +1158,6 @@ Events::drop_event(THD *thd, Event_timed *et, bool drop_if_exists,
Events::show_create_event()
thd THD
spn the name of the event (db, name)
- definer the definer of the event
RETURN VALUE
0 OK
@@ -1174,7 +1165,7 @@ Events::drop_event(THD *thd, Event_timed *et, bool drop_if_exists,
*/
int
-Events::show_create_event(THD *thd, sp_name *spn, LEX_STRING definer)
+Events::show_create_event(THD *thd, sp_name *spn)
{
int ret;
Event_timed *et= NULL;
@@ -1184,7 +1175,7 @@ Events::show_create_event(THD *thd, sp_name *spn, LEX_STRING definer)
DBUG_PRINT("enter", ("name: %*s", spn->m_name.length, spn->m_name.str));
thd->reset_n_backup_open_tables_state(&backup);
- ret= db_find_event(thd, spn, &definer, &et, NULL, thd->mem_root);
+ ret= db_find_event(thd, spn, &et, NULL, thd->mem_root);
thd->restore_backup_open_tables_state(&backup);
if (!ret)
diff --git a/sql/event.h b/sql/event.h
index 40ede7b0c5f..02c5fa78150 100644
--- a/sql/event.h
+++ b/sql/event.h
@@ -85,7 +85,7 @@ public:
open_event_table(THD *thd, enum thr_lock_type lock_type, TABLE **table);
static int
- show_create_event(THD *thd, sp_name *spn, LEX_STRING definer);
+ show_create_event(THD *thd, sp_name *spn);
static int
reconstruct_interval_expression(String *buf, interval_type interval,
diff --git a/sql/event_priv.h b/sql/event_priv.h
index b0a18377ace..43ef30a659f 100644
--- a/sql/event_priv.h
+++ b/sql/event_priv.h
@@ -33,7 +33,6 @@ my_time_compare(TIME *a, TIME *b);
int
evex_db_find_event_by_name(THD *thd, const LEX_STRING dbname,
const LEX_STRING ev_name,
- const LEX_STRING user_name,
TABLE *table);
int
@@ -43,8 +42,8 @@ int
db_drop_event(THD *thd, Event_timed *et, bool drop_if_exists,
uint *rows_affected);
int
-db_find_event(THD *thd, sp_name *name, LEX_STRING *definer, Event_timed **ett,
- TABLE *tbl, MEM_ROOT *root);
+db_find_event(THD *thd, sp_name *name, Event_timed **ett, TABLE *tbl,
+ MEM_ROOT *root);
int
db_create_event(THD *thd, Event_timed *et, my_bool create_if_not,
diff --git a/sql/event_scheduler.cc b/sql/event_scheduler.cc
index 0644f8ec534..e360254fdd2 100644
--- a/sql/event_scheduler.cc
+++ b/sql/event_scheduler.cc
@@ -1299,11 +1299,17 @@ Event_scheduler::run(THD *thd)
/* Skip disabled events */
if (et->status != Event_timed::ENABLED)
{
- sql_print_error("SCHEDULER: Found a disabled event %*s.%*s in the queue",
- et->dbname.length, et->dbname.str, et->name.length,
- et->name.str);
+ /*
+ It could be a one-timer scheduled for a time, already in the past when the
+ scheduler was suspended.
+ */
+ sql_print_information("SCHEDULER: Found a disabled event %*s.%*s in the queue",
+ et->dbname.length, et->dbname.str, et->name.length,
+ et->name.str);
queue_remove(&queue, 0);
/* ToDo: check this again */
+ if (et->dropped)
+ et->drop(thd);
delete et;
UNLOCK_SCHEDULER_DATA();
continue;
@@ -1812,7 +1818,10 @@ Event_scheduler::check_n_suspend_if_needed(THD *thd)
DBUG_PRINT("info", ("We have to recompute the execution times"));
for (i= 0; i < queue.elements; i++)
+ {
((Event_timed*)queue_element(&queue, i))->compute_next_execution_time();
+ ((Event_timed*)queue_element(&queue, i))->update_fields(thd);
+ }
queue_fix(&queue);
}
/* This will implicitly unlock LOCK_scheduler_data */
@@ -2057,8 +2066,7 @@ Event_scheduler::load_named_event(THD *thd, Event_timed *etn, Event_timed **etn_
/* No need to use my_error() here because db_find_event() has done it */
{
sp_name spn(etn->dbname, etn->name);
- ret= db_find_event(thd, &spn, &etn->definer, &et_loaded, NULL,
- &scheduler_root);
+ ret= db_find_event(thd, &spn, &et_loaded, NULL, &scheduler_root);
}
thd->restore_backup_open_tables_state(&backup);
/* In this case no memory was allocated so we don't need to clean */
diff --git a/sql/event_timed.cc b/sql/event_timed.cc
index fd85f5ebecc..d6d6dddf971 100644
--- a/sql/event_timed.cc
+++ b/sql/event_timed.cc
@@ -324,7 +324,7 @@ int
Event_timed::init_interval(THD *thd, Item *expr, interval_type new_interval)
{
String value;
- INTERVAL interval;
+ INTERVAL interval_tmp;
DBUG_ENTER("Event_timed::init_interval");
@@ -332,71 +332,74 @@ Event_timed::init_interval(THD *thd, Item *expr, interval_type new_interval)
DBUG_RETURN(EVEX_PARSE_ERROR);
value.alloc(MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN);
- if (get_interval_value(expr, new_interval, &value, &interval))
+ if (get_interval_value(expr, new_interval, &value, &interval_tmp))
DBUG_RETURN(EVEX_PARSE_ERROR);
expression= 0;
switch (new_interval) {
case INTERVAL_YEAR:
- expression= interval.year;
+ expression= interval_tmp.year;
break;
case INTERVAL_QUARTER:
case INTERVAL_MONTH:
- expression= interval.month;
+ expression= interval_tmp.month;
break;
case INTERVAL_WEEK:
case INTERVAL_DAY:
- expression= interval.day;
+ expression= interval_tmp.day;
break;
case INTERVAL_HOUR:
- expression= interval.hour;
+ expression= interval_tmp.hour;
break;
case INTERVAL_MINUTE:
- expression= interval.minute;
+ expression= interval_tmp.minute;
break;
case INTERVAL_SECOND:
- expression= interval.second;
+ expression= interval_tmp.second;
break;
case INTERVAL_YEAR_MONTH: // Allow YEAR-MONTH YYYYYMM
- expression= interval.year* 12 + interval.month;
+ expression= interval_tmp.year* 12 + interval_tmp.month;
break;
case INTERVAL_DAY_HOUR:
- expression= interval.day* 24 + interval.hour;
+ expression= interval_tmp.day* 24 + interval_tmp.hour;
break;
case INTERVAL_DAY_MINUTE:
- expression= (interval.day* 24 + interval.hour) * 60 + interval.minute;
+ expression= (interval_tmp.day* 24 + interval_tmp.hour) * 60 +
+ interval_tmp.minute;
break;
case INTERVAL_HOUR_SECOND: /* day is anyway 0 */
case INTERVAL_DAY_SECOND:
/* DAY_SECOND having problems because of leap seconds? */
- expression= ((interval.day* 24 + interval.hour) * 60 + interval.minute)*60
- + interval.second;
+ expression= ((interval_tmp.day* 24 + interval_tmp.hour) * 60 +
+ interval_tmp.minute)*60
+ + interval_tmp.second;
break;
case INTERVAL_MINUTE_MICROSECOND: /* day and hour are 0 */
case INTERVAL_HOUR_MICROSECOND: /* day is anyway 0 */
case INTERVAL_DAY_MICROSECOND:
DBUG_RETURN(EVEX_MICROSECOND_UNSUP);
- expression= ((((interval.day*24) + interval.hour)*60+interval.minute)*60 +
- interval.second) * 1000000L + interval.second_part;
+ expression= ((((interval_tmp.day*24) + interval_tmp.hour)*60+
+ interval_tmp.minute)*60 +
+ interval_tmp.second) * 1000000L + interval_tmp.second_part;
break;
case INTERVAL_HOUR_MINUTE:
- expression= interval.hour * 60 + interval.minute;
+ expression= interval_tmp.hour * 60 + interval_tmp.minute;
break;
case INTERVAL_MINUTE_SECOND:
- expression= interval.minute * 60 + interval.second;
+ expression= interval_tmp.minute * 60 + interval_tmp.second;
break;
case INTERVAL_SECOND_MICROSECOND:
DBUG_RETURN(EVEX_MICROSECOND_UNSUP);
- expression= interval.second * 1000000L + interval.second_part;
+ expression= interval_tmp.second * 1000000L + interval_tmp.second_part;
break;
case INTERVAL_MICROSECOND:
DBUG_RETURN(EVEX_MICROSECOND_UNSUP);
}
- if (interval.neg || expression > EVEX_MAX_INTERVAL_VALUE)
+ if (interval_tmp.neg || expression > EVEX_MAX_INTERVAL_VALUE)
DBUG_RETURN(EVEX_BAD_PARAMS);
- this->interval= new_interval;
+ interval= new_interval;
DBUG_RETURN(0);
}
@@ -961,7 +964,7 @@ Event_timed::compute_next_execution_time()
}
goto ret;
}
- current_thd->end_time();
+
my_tz_UTC->gmt_sec_to_TIME(&time_now, current_thd->query_start());
DBUG_PRINT("info",("NOW=[%llu]", TIME_to_ulonglong_datetime(&time_now)));
@@ -975,6 +978,7 @@ Event_timed::compute_next_execution_time()
execute_at_null= TRUE;
if (on_completion == Event_timed::ON_COMPLETION_DROP)
dropped= true;
+ DBUG_PRINT("info", ("Dropped=%d", dropped));
status= Event_timed::DISABLED;
status_changed= true;
@@ -1225,7 +1229,7 @@ Event_timed::update_fields(THD *thd)
{
TABLE *table;
Open_tables_state backup;
- int ret= 0;
+ int ret;
DBUG_ENTER("Event_timed::update_time_fields");
@@ -1233,7 +1237,7 @@ Event_timed::update_fields(THD *thd)
/* No need to update if nothing has changed */
if (!(status_changed || last_executed_changed))
- goto done;
+ DBUG_RETURN(0);
thd->reset_n_backup_open_tables_state(&backup);
@@ -1244,7 +1248,7 @@ Event_timed::update_fields(THD *thd)
}
- if ((ret= evex_db_find_event_by_name(thd, dbname, name, definer, table)))
+ if ((ret= evex_db_find_event_by_name(thd, dbname, name, table)))
goto done;
store_record(table,record[1]);
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 95f3f455351..3206cfa2d52 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -3840,16 +3840,16 @@ end_with_restore_list:
switch (lex->sql_command) {
case SQLCOM_CREATE_EVENT:
res= Events::create_event(thd, lex->et,
- (uint) lex->create_info.options,
- &rows_affected);
+ (uint) lex->create_info.options,
+ &rows_affected);
break;
case SQLCOM_ALTER_EVENT:
res= Events::update_event(thd, lex->et, lex->spname,
- &rows_affected);
+ &rows_affected);
break;
case SQLCOM_DROP_EVENT:
res= Events::drop_event(thd, lex->et, lex->drop_if_exists,
- &rows_affected);
+ &rows_affected);
default:;
}
DBUG_PRINT("info", ("CREATE/ALTER/DROP returned error code=%d af_rows=%d",
@@ -3887,7 +3887,7 @@ end_with_restore_list:
my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str);
goto error;
}
- res= Events::show_create_event(thd, lex->spname, lex->et->definer);
+ res= Events::show_create_event(thd, lex->spname);
break;
}
#ifndef DBUG_OFF
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index ac1825d7c84..bdf0724ee96 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -4078,8 +4078,24 @@ static interval_type get_real_interval_type(interval_type i_type)
extern LEX_STRING interval_type_to_name[];
+
+/*
+ Loads an event from mysql.event and copies it's data to a row of
+ I_S.EVENTS
+
+ Synopsis
+ copy_event_to_schema_table()
+ thd Thread
+ sch_table The schema table (information_schema.event)
+ event_table The event table to use for loading (mysql.event).
+
+ Returns
+ 0 OK
+ 1 Error
+*/
+
static int
-fill_events_copy_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;
CHARSET_INFO *scs= system_charset_info;
@@ -4097,9 +4113,19 @@ fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
if (!(!wild || !wild[0] || !wild_compare(et.name.str, wild, 0)))
DBUG_RETURN(0);
-
+
+ /*
+ Skip events in schemas one does not have access to. The check is
+ optimized. It's guaranteed in case of SHOW EVENTS that the user
+ has access.
+ */
+ if (thd->lex->orig_sql_command != SQLCOM_SHOW_EVENTS &&
+ check_access(thd, EVENT_ACL, et.dbname.str, 0, 0, 1,
+ is_schema_db(et.dbname.str)))
+ DBUG_RETURN(0);
+
/* ->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);
@@ -4111,19 +4137,18 @@ fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
ulong sql_mode_len=0;
sql_mode_str=
sys_var_thd_sql_mode::symbolic_mode_representation(thd, et.sql_mode,
- &sql_mode_len);
+ &sql_mode_len);
sch_table->field[9]->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);
- if (Events::reconstruct_interval_expression(&show_str,
- et.interval,
- et.expression))
+ if (Events::reconstruct_interval_expression(&show_str, et.interval,
+ et.expression))
DBUG_RETURN(1);
sch_table->field[7]->set_notnull();
@@ -4133,7 +4158,7 @@ fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
sch_table->field[8]->set_notnull();
sch_table->field[8]->store(ival->str, ival->length, scs);
- //starts & ends
+ /* starts & ends */
sch_table->field[10]->set_notnull();
sch_table->field[10]->store_time(&et.starts, MYSQL_TIMESTAMP_DATETIME);
@@ -4152,13 +4177,13 @@ fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
sch_table->field[6]->store_time(&et.execute_at, MYSQL_TIMESTAMP_DATETIME);
}
- //status
+ /* status */
if (et.status == Event_timed::ENABLED)
sch_table->field[12]->store(STRING_WITH_LEN("ENABLED"), scs);
else
sch_table->field[12]->store(STRING_WITH_LEN("DISABLED"), scs);
- //on_completion
+ /* on_completion */
if (et.on_completion == Event_timed::ON_COMPLETION_DROP)
sch_table->field[13]->store(STRING_WITH_LEN("NOT PRESERVE"), scs);
else
@@ -4188,98 +4213,179 @@ fill_events_copy_to_schema_table(THD *thd, TABLE *sch_table, TABLE *event_table)
}
-int fill_schema_events(THD *thd, TABLE_LIST *tables, COND *cond)
+/*
+ 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)
{
- TABLE *table= tables->table;
- CHARSET_INFO *scs= system_charset_info;
- TABLE *event_table= NULL;
- Open_tables_state backup;
int ret=0;
- bool verbose= false;
- char definer[HOSTNAME_LENGTH+USERNAME_LENGTH+2];
- bool use_prefix_scanning= true;
- uint key_len= 0;
+ CHARSET_INFO *scs= system_charset_info;
+ KEY *key_info;
+ uint key_len;
byte *key_buf= NULL;
LINT_INIT(key_buf);
- DBUG_ENTER("fill_schema_events");
-
- strxmov(definer, thd->security_ctx->priv_user,"@",thd->security_ctx->priv_host,
- NullS);
-
- DBUG_PRINT("info",("db=%s current_user=%s", thd->lex->select_lex.db, definer));
+ DBUG_ENTER("schema_events_do_index_scan");
- thd->reset_n_backup_open_tables_state(&backup);
+ DBUG_PRINT("info", ("Using prefix scanning on PK"));
+ event_table->file->ha_index_init(0, 1);
+ event_table->field[Events::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 ((ret= Events::open_event_table(thd, TL_READ, &event_table)))
+ if (!(key_buf= (byte *)alloc_root(thd->mem_root, key_len)))
{
- sql_print_error("Table mysql.event is damaged.");
ret= 1;
- goto err;
- }
-
- event_table->file->ha_index_init(0, 1);
-
- /* see others' events only if you have PROCESS_ACL !! */
- verbose= ((thd->lex->verbose ||
- thd->lex->orig_sql_command != SQLCOM_SHOW_EVENTS) &&
- (thd->security_ctx->master_access & PROCESS_ACL));
-
- if (verbose && thd->security_ctx->user)
- {
- ret= event_table->file->index_first(event_table->record[0]);
- use_prefix_scanning= false;
+ /* don't send error, it would be done by sql_alloc_error_handler() */
}
else
{
- event_table->field[Events::FIELD_DEFINER]->
- store(definer, strlen(definer), scs);
- key_len= event_table->key_info->key_part[0].store_length;
-
- if (thd->lex->select_lex.db)
+ 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)))
{
- event_table->field[Events::FIELD_DB]->
- store(thd->lex->select_lex.db, strlen(thd->lex->select_lex.db), scs);
- key_len+= event_table->key_info->key_part[1].store_length;
- }
- if (!(key_buf= (byte *)alloc_root(thd->mem_root, key_len)))
- {
- ret= 1;
- goto err;
+ 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);
}
-
- key_copy(key_buf, event_table->record[0], event_table->key_info, key_len);
- ret= event_table->file->index_read(event_table->record[0], key_buf, key_len,
- HA_READ_PREFIX);
+ 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.
- if (ret)
+ 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= (ret == HA_ERR_END_OF_FILE || ret == HA_ERR_KEY_NOT_FOUND) ? 0 : 1;
- goto err;
+ 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);
- while (!ret)
- {
- if ((ret= fill_events_copy_to_schema_table(thd, table, event_table)))
- goto err;
+ DBUG_PRINT("info", ("Scan finished. ret=%d", ret));
+ end_read_record(&read_record_info);
- if (use_prefix_scanning)
- ret= event_table->file->
- index_next_same(event_table->record[0], key_buf, key_len);
- else
- ret= event_table->file->index_next(event_table->record[0]);
+ /* 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);
}
- // ret is guaranteed to be != 0
- ret= (ret != HA_ERR_END_OF_FILE);
-err:
- if (event_table)
+
+ 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::open_event_table(thd, TL_READ, &event_table))
{
- event_table->file->ha_index_end();
- close_thread_tables(thd);
+ 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);
}