Commit 1c5573a4 authored by unknown's avatar unknown
Browse files

WL #1034 update

- handle better non-latin1 identifiers


sql/event.cc:
  - introduce a wrapper to compare easily and correctly
  LEX_STRINGs
  - remove few unneeded variables
  - remove need_second_pass by restructuring the code. this brings
    performance boost because the code bails out from the loop once
    it hits what it looks for
  - handle ALTER EVENT name RENAME TO name  (throw an error message).
sql/event_executor.cc:
  - comment about DBUG_FAULTY_THR
  - indent fix
sql/event_timed.cc:
  - fix a problem when event name is not latin1. a cyrillic event name
    was crashing the parser so the I emulate SET NAMES utf8. The data is
    already in utf8, being loaded from the disk.
sql/share/errmsg.txt:
  add new error message
parent c1cb8db8
Loading
Loading
Loading
Loading
+49 −37
Original line number Diff line number Diff line
@@ -89,6 +89,15 @@ MEM_ROOT evex_mem_root;
  a < b -> -1
*/

static
int sortcmp_lex_string(LEX_STRING s, LEX_STRING t, CHARSET_INFO *cs)
{
 return cs->coll->strnncollsp(cs,
                              (unsigned char *) s.str,s.length,
                              (unsigned char *) t.str,t.length, 0);
}


inline int
my_time_compare(TIME *a, TIME *b)
{
@@ -472,12 +481,21 @@ db_update_event(THD *thd, event_timed *et, sp_name *new_name)
  }
  
  // first look whether we overwrite
  if (new_name && !evex_db_find_event_aux(thd, new_name->m_db, new_name->m_name,
                                            table))
  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))
    {
      my_error(ER_EVENT_SAME_NAME, MYF(0), et->name.str);
      goto err;    
    }
  
    if (!evex_db_find_event_aux(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
    because you will get error 120 from table handler because new_name will
@@ -676,7 +694,6 @@ static int
evex_remove_from_cache(LEX_STRING *db, LEX_STRING *name, bool use_lock)
{
  uint i;
  bool need_second_pass= true;

  DBUG_ENTER("evex_remove_from_cache");
  /*
@@ -689,37 +706,31 @@ evex_remove_from_cache(LEX_STRING *db, LEX_STRING *name, bool use_lock)
 
  for (i= 0; i < evex_executing_queue.elements; ++i)
  {
    event_timed **p_et= dynamic_element(&evex_executing_queue, i, event_timed**);
    event_timed *ett= *p_et;
    DBUG_PRINT("info", ("[%s.%s]==[%s.%s]?",db->str,name->str,
                ett->dbname.str, ett->name.str));
    if (name->length == ett->name.length &&
        db->length == ett->dbname.length &&
        0 == strncmp(db->str, ett->dbname.str, db->length) &&
        0 == strncmp(name->str, ett->name.str, name->length)
       )
    {
      int idx;
    event_timed *et= *dynamic_element(&evex_executing_queue, i, event_timed**);
    DBUG_PRINT("info", ("[%s.%s]==[%s.%s]?",db->str,name->str, et->dbname.str, 
                        et->name.str));
    if (!sortcmp_lex_string(*name, et->name, system_charset_info) &&
        !sortcmp_lex_string(*db, et->dbname, system_charset_info))
    {
      int idx= get_index_dynamic(&events_array, (gptr) et);
      //we are lucky the event is in the executing queue, no need of second pass
      need_second_pass= false;
      idx= get_index_dynamic(&events_array, (gptr) ett);
      if (idx == -1)
      {
        //this should never happen
        DBUG_PRINT("error", (" get_index_dynamic problem. %d."
               "i=%d idx=%d evex_ex_queue.buf=%p evex_ex_queue.elements=%d ett=%p\n"
               "events_array=%p events_array.elements=%d events_array.buf=%p\n"
               "p_et=%p ett=%p",
          "i=%d idx=%d evex_ex_queue.buf=%p evex_ex_queue.elements=%d et=%p\n"
          "events_array=%p events_array.elements=%d events_array.buf=%p et=%p\n",
           __LINE__, i, idx, &evex_executing_queue.buffer,
               evex_executing_queue.elements, ett, &events_array,
               events_array.elements, events_array.buffer, p_et, ett));
           evex_executing_queue.elements, et, &events_array,
           events_array.elements, events_array.buffer, et));
        DBUG_ASSERT(0);
      }
      //destruct first and then remove. the destructor will delete sp_head
      ett->free_sp();
      et->free_sp();
      delete_dynamic_element(&events_array, idx);
      delete_dynamic_element(&evex_executing_queue, i);
      // ok, we have cleaned
      goto done;
    }
  }

@@ -733,19 +744,20 @@ evex_remove_from_cache(LEX_STRING *db, LEX_STRING *name, bool use_lock)
                  For instance, second_pass is needed when an event
                  was created as DISABLED but then altered as ENABLED.
  */
  if (need_second_pass)
    //we haven't found the event in the executing queue. This is nice! :)
    //Look for it in the events_array.
  /*
    we haven't found the event in the executing queue. This is nice! :)
    Look for it in the events_array.
  */
  for (i= 0; i < events_array.elements; ++i)
  {
      event_timed *ett= dynamic_element(&events_array, i, event_timed*);
    event_timed *et= dynamic_element(&events_array, i, event_timed*);
      
      if (name->length == ett->name.length &&
          db->length == ett->dbname.length &&
          0 == strncmp(db->str, ett->dbname.str, db->length) &&
          0 == strncmp(name->str, ett->name.str, name->length)
         )
    if (!sortcmp_lex_string(*name, et->name, system_charset_info) &&
        !sortcmp_lex_string(*db, et->dbname, system_charset_info))
    {
      delete_dynamic_element(&events_array, i);
      break;
    }
  } 

done:
+10 −1
Original line number Diff line number Diff line
@@ -19,6 +19,15 @@
#include "event_priv.h"
#include "sp.h"


/* 
  Make this define DBUG_FAULTY_THR to be able to put breakpoints inside
  code used by the scheduler's thread(s). In this case user connections
  are not possible because the scheduler thread code is ran inside the
  main thread (no spawning takes place. If you want to debug client 
  connection then start with --one-thread and make the define
  DBUG_FAULTY_THR2 !
*/
#define DBUG_FAULTY_THR2

extern  ulong thread_created;
+26 −2
Original line number Diff line number Diff line
@@ -904,6 +904,7 @@ event_timed::execute(THD *thd, MEM_ROOT *mem_root)
int
event_timed::compile(THD *thd, MEM_ROOT *mem_root)
{
  int ret= 0;
  MEM_ROOT *tmp_mem_root= 0;
  LEX *old_lex= thd->lex, lex;
  char *old_db;
@@ -912,6 +913,19 @@ event_timed::compile(THD *thd, MEM_ROOT *mem_root)
  char *old_query;
  uint old_query_len;
  st_sp_chistics *p;
  CHARSET_INFO *old_character_set_client, *old_collation_connection,
               *old_character_set_results;

  old_character_set_client= thd->variables.character_set_client;
  old_character_set_results= thd->variables.character_set_results;
  old_collation_connection= thd->variables.collation_connection;
  
  thd->variables.character_set_client= 
    thd->variables.character_set_results=
      thd->variables.collation_connection=
           get_charset_by_csname("utf8", MY_CS_PRIMARY, MYF(MY_WME));

  thd->update_charset();
  
  DBUG_ENTER("event_timed::compile");
  // change the memory root for the execution time
@@ -944,7 +958,9 @@ event_timed::compile(THD *thd, MEM_ROOT *mem_root)
    // QQ: anything else ?
    lex_end(&lex);
    thd->lex= old_lex;
    DBUG_RETURN(EVEX_COMPILE_ERROR);

    ret= EVEX_COMPILE_ERROR;
    goto done;
  }
  
  sphead= lex.sphead;
@@ -954,17 +970,25 @@ event_timed::compile(THD *thd, MEM_ROOT *mem_root)
  sphead->set_definer(definer.str, definer.length);
  sphead->set_info(0, 0, &lex.sp_chistics, 0/*sql_mode*/);
  sphead->optimize();
  ret= 0;
done:
  lex_end(&lex);
  thd->lex= old_lex;
  thd->query= old_query;
  thd->query_length= old_query_len;
  thd->db= old_db;

  thd->variables.character_set_client= old_character_set_client;
  thd->variables.character_set_results= old_character_set_results;
  thd->variables.collation_connection= old_collation_connection;
  thd->update_charset();

  /*
    Change the memory root for the execution time.
  */
  if (mem_root)
    thd->mem_root= tmp_mem_root;

  DBUG_RETURN(0);
  DBUG_RETURN(ret);
}
+2 −0
Original line number Diff line number Diff line
@@ -5749,3 +5749,5 @@ ER_EVENT_CANNOT_DELETE
        eng "Failed to delete the event from mysql.event"
ER_EVENT_COMPILE_ERROR
        eng "Error during compilation of event's body"
ER_EVENT_SAME_NAME
        eng "Same old and new event name"