Commit 8ca78787 authored by unknown's avatar unknown
Browse files

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.


sql/event_db_repository.cc:
  move code that works with mysql.event from sql_show.cc to 
  event_db_repository.cc . Route through Event_db_repository's interface
  which is proxied by class Events. The code relies on a function from
  sql_show.cc which does the actual storage in the schema table. I think
  it's better to leave the function there because the structure of 
  I_S.EVENTS is defined in sql_show.cc
sql/event_db_repository.h:
  I_S / SHOW EVENTS handling hooks
sql/event_scheduler.cc:
  use the pointer to db_repository which Event_scheduler already has
sql/events.cc:
  Put a comment to get_instance
sql/events.h:
  callback for I_S (sql_show.cc)
sql/sql_show.cc:
  move code that belongs more to Event_db_repository than to here.
  Use a callback of class Events. Only 1 function is left here, because
  it copies data into the actual rows of I_S.EVENTS and belongs to this file.
sql/sql_show.h:
  export this function will be called from event_db_repository.cc
parent acefb78b
Loading
Loading
Loading
Loading
+169 −4
Original line number Diff line number Diff line
@@ -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();
    /*
@@ -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
  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;
+24 −4
Original line number Diff line number Diff line
@@ -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
@@ -57,9 +68,6 @@ class Event_db_repository
  void
  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 @@ class Event_db_repository

  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;

+1 −1
Original line number Diff line number Diff line
@@ -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);
+46 −1
Original line number Diff line number Diff line
@@ -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
*/
@@ -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

+3 −0
Original line number Diff line number Diff line
@@ -91,6 +91,9 @@ class Events
  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);

Loading