Commit 92b3a32b authored by unknown's avatar unknown

Remove direct mapping of enum interval_type to mysql.event.interval_field

  This decoupling allows in further versions of MySQL enum interval_type to
  be reordered without this affecting any backward compatibility in the
  events code.
  This changeset doesn't change any exposed behavior but makes events' code
  more durable to changes outside of their code base.
  
  To the reviewer: There is no regression test included as it is impossible
  to construct one with the current infrastructure which can test it. To test
  the code one has create and event, then change the order of
  enum interval_type in my_time.h, update sql/time.cc, recompile the server
  and run it with scheduler running.


include/my_time.h:
  Add a reminder to keep enum interval_type and
  interval_type_to_name in sync
sql/event_data_objects.cc:
  When loading from disk don't use the integer value of
  mysql.event.interval_field because it could be different of the
  values of enum interval_type, if the latter is reordered in a later
  version of MySQL. Loaded from disk is the string value which is then
  resolved against interval_type_to_name to get the exact enum value we
  need for Event_queue_element::interval.
sql/event_db_repository.cc:
  Use interval_type_to_name from sql/time.cc during storage thus
  decoupling the value stored on disk (the enum) from the integer
  representation in memory. interval_type can be changed and as
  long as interval_type_to_name is kept in sync correct values will
  be saved to disk.
sql/mysql_priv.h:
  add proto of find_string_in_array
sql/strfunc.cc:
  Add a function for searching a LEX_STRING in an array of LEX_STRINGs
parent a7f8da29
......@@ -100,6 +100,8 @@ int my_TIME_to_str(const MYSQL_TIME *l_time, char *to);
/*
The following must be sorted so that simple intervals comes first.
(get_interval_value() depends on this)
When updating this enum please update
LEX_STRING interval_type_to_name[] in sql/time.cc
*/
enum interval_type
......
......@@ -886,14 +886,29 @@ Event_queue_element::load_from_row(TABLE *table)
goto error;
/*
In DB the values start from 1 but enum interval_type starts
from 0
We load the interval type from disk as string and then map it to
an integer. This decouples the values of enum interval_type
and values actually stored on disk. Therefore the type can be
reordered without risking incompatibilities of data between versions.
*/
if (!table->field[ET_FIELD_TRANSIENT_INTERVAL]->is_null())
interval= (interval_type) ((ulonglong)
table->field[ET_FIELD_TRANSIENT_INTERVAL]->val_int() - 1);
else
interval= (interval_type) 0;
{
int i;
char buff[MAX_FIELD_WIDTH];
String str(buff, sizeof(buff), &my_charset_bin);
LEX_STRING tmp;
table->field[ET_FIELD_TRANSIENT_INTERVAL]->val_str(&str);
if (!(tmp.length= str.length()))
goto error;
tmp.str= str.c_ptr_safe();
i= find_string_in_array(interval_type_to_name, &tmp, system_charset_info);
if (i < 0)
goto error;
interval= (interval_type) i;
}
table->field[ET_FIELD_LAST_EXECUTED]->get_date(&last_executed,
TIME_NO_ZERO_DATE);
......
......@@ -188,11 +188,11 @@ mysql_event_fill_row(THD *thd, TABLE *table, Event_parse_data *et,
fields[ET_FIELD_INTERVAL_EXPR]->store((longlong)et->expression, TRUE);
fields[ET_FIELD_TRANSIENT_INTERVAL]->set_notnull();
/*
In the enum (C) intervals start from 0 but in mysql enum valid values
start from 1. Thus +1 offset is needed!
*/
fields[ET_FIELD_TRANSIENT_INTERVAL]->store((longlong)et->interval+1, TRUE);
fields[ET_FIELD_TRANSIENT_INTERVAL]->
store(interval_type_to_name[et->interval].str,
interval_type_to_name[et->interval].length,
scs);
fields[ET_FIELD_EXECUTE_AT]->set_null();
......
......@@ -1481,6 +1481,8 @@ uint find_type2(TYPELIB *lib, const char *find, uint length, CHARSET_INFO *cs);
void unhex_type2(TYPELIB *lib);
uint check_word(TYPELIB *lib, const char *val, const char *end,
const char **end_of_word);
int find_string_in_array(LEX_STRING * const haystack, LEX_STRING * const needle,
CHARSET_INFO *cs);
bool is_keyword(const char *name, uint len);
......
......@@ -312,3 +312,33 @@ uint strconvert(CHARSET_INFO *from_cs, const char *from,
return (uint32) (to - to_start);
}
/*
Searches for a LEX_STRING in an LEX_STRING array.
SYNOPSIS
find_string_in_array()
heap The array
needle The string to search for
NOTE
The last LEX_STRING in the array should have str member set to NULL
RETURN VALUES
-1 Not found
>=0 Ordinal position
*/
int find_string_in_array(LEX_STRING * const haystack, LEX_STRING * const needle,
CHARSET_INFO * const cs)
{
const LEX_STRING *pos;
for (pos= haystack; pos->str; pos++)
if (!cs->coll->strnncollsp(cs, (uchar *) pos->str, pos->length,
(uchar *) needle->str, needle->length, 0))
{
return (pos - haystack);
}
return -1;
}
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