Commit 3a8e50e0 authored by unknown's avatar unknown
Browse files

fix for bug#16431 (Events: An event which alters itself disappears)

WL#1034 (Internal CRON)


mysql-test/r/events.result:
  add a test for to test bug #16431
mysql-test/t/events.test:
  results of new tests
sql/event.cc:
  - more debug info
  - pass info to evex_remove_from_cache() whether the operation 
    was drop or alter. this fixes possible bug that may lead to dropping
    of an event when it's altered. also fix for bug#16431
sql/event_executor.cc:
  be more verbose and throw more errors
sql/event_timed.cc:
  - add ` around the names of the db and the event_name and not
  their concatenation. remove ; from the end - unneeded. this fixes bug #16431,
  which was failing because after some recursion the query was ending on ;;
  which is normally an error in the parser because that's the delimiter
  
  - more debug info
  - don't execute lex_end() two times when there's a parse error or thd->is_fatal_error
parent 2dc2a430
Loading
Loading
Loading
Loading
+17 −0
Original line number Diff line number Diff line
@@ -12,6 +12,23 @@ alter event event3 rename to event2;
drop event event2;
create event event2 on schedule every 2 second starts now() ends date_add(now(), interval 5 hour) comment "some" DO begin end;
drop event event2;
create event e_43 on schedule every 1 second do set @a = 5;
set global event_scheduler = 1;
select sleep(2);
sleep(2)
0
alter event e_43 do alter event e_43 do set @a = 4;
select sleep(3);
sleep(3)
0
select db, name, body, status, interval_field, interval_value from mysql.event;
db	name	body	status	interval_field	interval_value
events_test	e_43	 set @a = 4	ENABLED	SECOND	1
drop event e_43;
select sleep(1);
sleep(1)
0
set global event_scheduler = 0;
create table t_event3 (a int, b float);
drop event if exists event3;
Warnings:
+10 −0
Original line number Diff line number Diff line
@@ -14,6 +14,16 @@ drop event event2;
create event event2 on schedule every 2 second starts now() ends date_add(now(), interval 5 hour) comment "some" DO begin end;
drop event event2;

create event e_43 on schedule every 1 second do set @a = 5;
set global event_scheduler = 1;
select sleep(2);
alter event e_43 do alter event e_43 do set @a = 4;
select sleep(3);
select db, name, body, status, interval_field, interval_value from mysql.event;
drop event e_43;
select sleep(1);
set global event_scheduler = 0;

create table t_event3 (a int, b float);
drop event if exists event3;
create event event3 on schedule every 50 + 10 minute starts date_add("20010101", interval 5 minute) ends date_add("20151010", interval 5 day) comment "portokala_comment" DO insert into t_event3 values (unix_timestamp(), rand());
+12 −6
Original line number Diff line number Diff line
@@ -237,8 +237,9 @@ evex_fill_row(THD *thd, TABLE *table, event_timed *et, my_bool is_update)
    DBUG_RETURN(EVEX_GET_FIELD_FAILED);
  }
  
  DBUG_PRINT("info", ("dbname.len=%d",et->dbname.length));  
  DBUG_PRINT("info", ("name.len=%d",et->name.length));  
  DBUG_PRINT("info", ("dbname.len=[%s]",et->dbname.str));  
  DBUG_PRINT("info", ("name.len=[%s]",et->name.str));  
  DBUG_PRINT("info", ("body=[%s]",et->body.str));  

  if (table->field[field_num= EVEX_FIELD_DB]->
                  store(et->dbname.str, et->dbname.length, system_charset_info))
@@ -674,7 +675,8 @@ evex_load_and_compile_event(THD * thd, sp_name *spn, bool use_lock)


static int
evex_remove_from_cache(LEX_STRING *db, LEX_STRING *name, bool use_lock)
evex_remove_from_cache(LEX_STRING *db, LEX_STRING *name, bool use_lock,
                       bool is_drop)
{
  uint i;

@@ -697,14 +699,18 @@ evex_remove_from_cache(LEX_STRING *db, LEX_STRING *name, bool use_lock)
    {
      if (!et->is_running())
      {
        DBUG_PRINT("evex_remove_from_cache", ("not running - free and delete"));
        et->free_sp();
        delete et;
      }
      else
      {
        DBUG_PRINT("evex_remove_from_cache",
               ("running.defer mem free. is_drop=%d", is_drop));
        et->flags|= EVENT_EXEC_NO_MORE;
        et->dropped= true;
        et->dropped= is_drop;
      }
      DBUG_PRINT("evex_remove_from_cache", ("delete from queue"));
      evex_queue_delete_element(&EVEX_EQ_NAME, i);
      // ok, we have cleaned
      goto done;
@@ -805,7 +811,7 @@ evex_update_event(THD *thd, event_timed *et, sp_name *new_name,
    UNLOCK_MUTEX_AND_BAIL_OUT(LOCK_evex_running, done);

  VOID(pthread_mutex_lock(&LOCK_event_arrays));
  evex_remove_from_cache(&et->dbname, &et->name, false);
  evex_remove_from_cache(&et->dbname, &et->name, false, false);
  if (et->status == MYSQL_EVENT_ENABLED)
  {
    if (new_name)
@@ -874,7 +880,7 @@ evex_drop_event(THD *thd, event_timed *et, bool drop_if_exists,

  VOID(pthread_mutex_lock(&LOCK_evex_running));
  if (evex_is_running)
    ret= evex_remove_from_cache(&et->dbname, &et->name, true);
    ret= evex_remove_from_cache(&et->dbname, &et->name, true, true);
  VOID(pthread_mutex_unlock(&LOCK_evex_running));

done:
+6 −0
Original line number Diff line number Diff line
@@ -492,12 +492,18 @@ event_executor_worker(void *event_void)
    sql_print_information("    EVEX EXECUTED event %s.%s  [EXPR:%d]. RetCode=%d",
                          event->dbname.str, event->name.str,
                          (int) event->expression, ret);
    if (ret == EVEX_COMPILE_ERROR)
      sql_print_information("    EVEX COMPILE ERROR for event %s.%s",
                             event->dbname.str, event->name.str);
    
    DBUG_PRINT("info", ("    EVEX EXECUTED event %s.%s  [EXPR:%d]. RetCode=%d",
                        event->dbname.str, event->name.str,
                        (int) event->expression, ret));
  }
  if ((event->flags & EVENT_EXEC_NO_MORE) || event->status==MYSQL_EVENT_DISABLED)
  {
    DBUG_PRINT("event_executor_worker",
               ("%s exec no more. to drop=%d",event->name.str, event->dropped));
    if (event->dropped)
      event->drop(thd);
    delete event;
+17 −11
Original line number Diff line number Diff line
@@ -806,16 +806,18 @@ event_timed::get_show_create_event(THD *thd, uint *length)
{
  char *dst, *ret;
  uint len, tmp_len;
  DBUG_ENTER("get_show_create_event");
  DBUG_PRINT("ret_info",("body_len=[%d]body=[%s]", body.length, body.str));

  len = strlen("CREATE EVENT `") + dbname.length + strlen(".") + name.length +
        strlen("` ON SCHEDULE EVERY 5 MINUTE DO ") + body.length + strlen(";");
  len = strlen("CREATE EVENT `") + dbname.length + strlen("`.`") + name.length +
        strlen("` ON SCHEDULE EVERY 5 MINUTE DO ") + body.length;// + strlen(";");
  
  ret= dst= (char*) alloc_root(thd->mem_root, len + 1);
  memcpy(dst, "CREATE EVENT `", tmp_len= strlen("CREATE EVENT `"));
  dst+= tmp_len;
  memcpy(dst, dbname.str, tmp_len=dbname.length);
  dst+= tmp_len;
  memcpy(dst, ".", tmp_len= strlen("."));
  memcpy(dst, "`.`", tmp_len= strlen("`.`"));
  dst+= tmp_len;
  memcpy(dst, name.str, tmp_len= name.length);
  dst+= tmp_len;
@@ -825,13 +827,14 @@ event_timed::get_show_create_event(THD *thd, uint *length)

  memcpy(dst, body.str, tmp_len= body.length);
  dst+= tmp_len;
  memcpy(dst, ";", 1);
  ++dst;
//  memcpy(dst, ";", 1);
//  ++dst;
  *dst= '\0';
 
  *length= len;
  
  return ret;
  DBUG_PRINT("ret_info",("len=%d",*length));
  DBUG_RETURN(ret);
}


@@ -944,8 +947,12 @@ event_timed::compile(THD *thd, MEM_ROOT *mem_root)
  lex.et_compile_phase= TRUE;
  if (yyparse((void *)thd) || thd->is_fatal_error)
  {
    DBUG_PRINT("error", ("error during compile or thd->is_fatal_error=%d",
                          thd->is_fatal_error));
    //  Free lex associated resources
    //  QQ: Do we really need all this stuff here ?
    sql_print_error("error during compile of %s.%s or thd->is_fatal_error=%d",
                    dbname.str, name.str, thd->is_fatal_error);
    if (lex.sphead)
    {
      if (&lex != thd->lex)
@@ -953,13 +960,10 @@ event_timed::compile(THD *thd, MEM_ROOT *mem_root)
      delete lex.sphead;
      lex.sphead= 0;
    }
    // QQ: anything else ?
    lex_end(&lex);
    thd->lex= old_lex;

    ret= EVEX_COMPILE_ERROR;
    goto done;
  }
  DBUG_PRINT("note", ("success compiling %s.%s", dbname.str, name.str));
  
  sphead= lex.et->sphead;
  sphead->m_db= dbname;
@@ -973,6 +977,8 @@ event_timed::compile(THD *thd, MEM_ROOT *mem_root)
  lex.et->free_sphead_on_delete= false;
  delete lex.et;
  lex_end(&lex);
  DBUG_PRINT("note", ("return old data on its place. set back NAMES"));

  thd->lex= old_lex;
  thd->query= old_query;
  thd->query_length= old_query_len;