MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
event_data_objects.cc
1 /* Copyright (c) 2005, 2011, Oracle and/or its affiliates. All rights reserved.
2 
3  This program is free software; you can redistribute it and/or modify
4  it under the terms of the GNU General Public License as published by
5  the Free Software Foundation; version 2 of the License.
6 
7  This program is distributed in the hope that it will be useful,
8  but WITHOUT ANY WARRANTY; without even the implied warranty of
9  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  GNU General Public License for more details.
11 
12  You should have received a copy of the GNU General Public License
13  along with this program; if not, write to the Free Software
14  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
15 
16 #define MYSQL_LEX 1
17 #include "my_global.h" /* NO_EMBEDDED_ACCESS_CHECKS */
18 #include "sql_priv.h"
19 #include "unireg.h"
20 #include "sql_parse.h" // parse_sql
21 #include "strfunc.h" // find_string_in_array
22 #include "sql_db.h" // get_default_db_collation
23 #include "sql_time.h" // interval_type_to_name,
24  // date_add_interval,
25  // calc_time_diff
26 #include "tztime.h" // my_tz_find, my_tz_OFFSET0, struct Time_zone
27 #include "sql_acl.h" // EVENT_ACL, SUPER_ACL
28 #include "sp.h" // load_charset, load_collation
29 #include "events.h"
30 #include "event_data_objects.h"
31 #include "event_db_repository.h"
32 #include "sp_head.h"
33 #include "sql_show.h" // append_definer, append_identifier
34 
40 /*************************************************************************/
41 
47  public Sql_alloc
48 {
49 public:
50  static bool load_from_db(THD *thd,
51  MEM_ROOT *event_mem_root,
52  const char *db_name,
53  const char *event_name,
54  TABLE *event_tbl,
56 
57 public:
58  virtual Stored_program_creation_ctx *clone(MEM_ROOT *mem_root)
59  {
60  return new (mem_root)
62  }
63 
64 protected:
65  virtual Object_creation_ctx *create_backup_ctx(THD *thd) const
66  {
67  /*
68  We can avoid usual backup/restore employed in stored programs since we
69  know that this is a top level statement and the worker thread is
70  allocated exclusively to execute this event.
71  */
72 
73  return NULL;
74  }
75 
76 private:
77  Event_creation_ctx(const CHARSET_INFO *client_cs,
78  const CHARSET_INFO *connection_cl,
79  const CHARSET_INFO *db_cl)
80  : Stored_program_creation_ctx(client_cs, connection_cl, db_cl)
81  { }
82 };
83 
84 /**************************************************************************
85  Event_creation_ctx implementation.
86 **************************************************************************/
87 
88 bool
89 Event_creation_ctx::load_from_db(THD *thd,
90  MEM_ROOT *event_mem_root,
91  const char *db_name,
92  const char *event_name,
93  TABLE *event_tbl,
95 {
96  /* Load character set/collation attributes. */
97 
98  const CHARSET_INFO *client_cs;
99  const CHARSET_INFO *connection_cl;
100  const CHARSET_INFO *db_cl;
101 
102  bool invalid_creation_ctx= FALSE;
103 
104  if (load_charset(event_mem_root,
105  event_tbl->field[ET_FIELD_CHARACTER_SET_CLIENT],
106  thd->variables.character_set_client,
107  &client_cs))
108  {
109  sql_print_warning("Event '%s'.'%s': invalid value "
110  "in column mysql.event.character_set_client.",
111  (const char *) db_name,
112  (const char *) event_name);
113 
114  invalid_creation_ctx= TRUE;
115  }
116 
117  if (load_collation(event_mem_root,
118  event_tbl->field[ET_FIELD_COLLATION_CONNECTION],
119  thd->variables.collation_connection,
120  &connection_cl))
121  {
122  sql_print_warning("Event '%s'.'%s': invalid value "
123  "in column mysql.event.collation_connection.",
124  (const char *) db_name,
125  (const char *) event_name);
126 
127  invalid_creation_ctx= TRUE;
128  }
129 
130  if (load_collation(event_mem_root,
131  event_tbl->field[ET_FIELD_DB_COLLATION],
132  NULL,
133  &db_cl))
134  {
135  sql_print_warning("Event '%s'.'%s': invalid value "
136  "in column mysql.event.db_collation.",
137  (const char *) db_name,
138  (const char *) event_name);
139 
140  invalid_creation_ctx= TRUE;
141  }
142 
143  /*
144  If we failed to resolve the database collation, load the default one
145  from the disk.
146  */
147 
148  if (!db_cl)
149  db_cl= get_default_db_collation(thd, db_name);
150 
151  /* Create the context. */
152 
153  *ctx= new Event_creation_ctx(client_cs, connection_cl, db_cl);
154 
155  return invalid_creation_ctx;
156 }
157 
158 /*************************************************************************/
159 
160 /*
161  Initiliazes dbname and name of an Event_queue_element_for_exec
162  object
163 
164  SYNOPSIS
165  Event_queue_element_for_exec::init()
166 
167  RETURN VALUE
168  FALSE OK
169  TRUE Error (OOM)
170 */
171 
172 bool
173 Event_queue_element_for_exec::init(LEX_STRING db, LEX_STRING n)
174 {
175  if (!(dbname.str= my_strndup(db.str, dbname.length= db.length, MYF(MY_WME))))
176  return TRUE;
177  if (!(name.str= my_strndup(n.str, name.length= n.length, MYF(MY_WME))))
178  {
179  my_free(dbname.str);
180  return TRUE;
181  }
182  return FALSE;
183 }
184 
185 
186 /*
187  Destructor
188 
189  SYNOPSIS
190  Event_queue_element_for_exec::~Event_queue_element_for_exec()
191 */
192 
193 Event_queue_element_for_exec::~Event_queue_element_for_exec()
194 {
195  my_free(dbname.str);
196  my_free(name.str);
197 }
198 
199 
200 /*
201  Constructor
202 
203  SYNOPSIS
204  Event_basic::Event_basic()
205 */
206 
207 Event_basic::Event_basic()
208 {
209  DBUG_ENTER("Event_basic::Event_basic");
210  /* init memory root */
211  init_sql_alloc(&mem_root, 256, 512);
212  dbname.str= name.str= NULL;
213  dbname.length= name.length= 0;
214  time_zone= NULL;
215  DBUG_VOID_RETURN;
216 }
217 
218 
219 /*
220  Destructor
221 
222  SYNOPSIS
223  Event_basic::Event_basic()
224 */
225 
226 Event_basic::~Event_basic()
227 {
228  DBUG_ENTER("Event_basic::~Event_basic");
229  free_root(&mem_root, MYF(0));
230  DBUG_VOID_RETURN;
231 }
232 
233 
234 /*
235  Short function to load a char column into a LEX_STRING
236 
237  SYNOPSIS
238  Event_basic::load_string_field()
239  field_name The field( enum_events_table_field is not actually used
240  because it's unknown in event_data_objects.h)
241  fields The Field array
242  field_value The value
243 */
244 
245 bool
246 Event_basic::load_string_fields(Field **fields, ...)
247 {
248  bool ret= FALSE;
249  va_list args;
250  enum enum_events_table_field field_name;
251  LEX_STRING *field_value;
252 
253  DBUG_ENTER("Event_basic::load_string_fields");
254 
255  va_start(args, fields);
256  field_name= (enum enum_events_table_field) va_arg(args, int);
257  while (field_name < ET_FIELD_COUNT)
258  {
259  field_value= va_arg(args, LEX_STRING *);
260  if ((field_value->str= get_field(&mem_root, fields[field_name])) == NullS)
261  {
262  ret= TRUE;
263  break;
264  }
265  field_value->length= strlen(field_value->str);
266 
267  field_name= (enum enum_events_table_field) va_arg(args, int);
268  }
269  va_end(args);
270 
271  DBUG_RETURN(ret);
272 }
273 
274 
275 bool
276 Event_basic::load_time_zone(THD *thd, const LEX_STRING tz_name)
277 {
278  String str(tz_name.str, &my_charset_latin1);
279  time_zone= my_tz_find(thd, &str);
280 
281  return (time_zone == NULL);
282 }
283 
284 
285 /*
286  Constructor
287 
288  SYNOPSIS
289  Event_queue_element::Event_queue_element()
290 */
291 
292 Event_queue_element::Event_queue_element():
293  on_completion(Event_parse_data::ON_COMPLETION_DROP),
294  status(Event_parse_data::ENABLED), expression(0), dropped(FALSE),
295  execution_count(0)
296 {
297  DBUG_ENTER("Event_queue_element::Event_queue_element");
298 
299  starts= ends= execute_at= last_executed= 0;
300  starts_null= ends_null= execute_at_null= TRUE;
301 
302  DBUG_VOID_RETURN;
303 }
304 
305 
306 /*
307  Destructor
308 
309  SYNOPSIS
310  Event_queue_element::Event_queue_element()
311 */
312 Event_queue_element::~Event_queue_element()
313 {
314 }
315 
316 
317 /*
318  Constructor
319 
320  SYNOPSIS
321  Event_timed::Event_timed()
322 */
323 
324 Event_timed::Event_timed():
325  created(0), modified(0), sql_mode(0)
326 {
327  DBUG_ENTER("Event_timed::Event_timed");
328  init();
329  DBUG_VOID_RETURN;
330 }
331 
332 
333 /*
334  Destructor
335 
336  SYNOPSIS
337  Event_timed::~Event_timed()
338 */
339 
340 Event_timed::~Event_timed()
341 {
342 }
343 
344 
345 /*
346  Constructor
347 
348  SYNOPSIS
349  Event_job_data::Event_job_data()
350 */
351 
352 Event_job_data::Event_job_data()
353  :sql_mode(0)
354 {
355 }
356 
357 /*
358  Init all member variables
359 
360  SYNOPSIS
361  Event_timed::init()
362 */
363 
364 void
365 Event_timed::init()
366 {
367  DBUG_ENTER("Event_timed::init");
368 
369  definer_user.str= definer_host.str= body.str= comment.str= NULL;
370  definer_user.length= definer_host.length= body.length= comment.length= 0;
371 
372  sql_mode= 0;
373 
374  DBUG_VOID_RETURN;
375 }
376 
377 
390 bool
392 {
393  char *ptr;
394  size_t len;
395  LEX_STRING tz_name;
396 
397  DBUG_ENTER("Event_job_data::load_from_row");
398 
399  if (!table)
400  DBUG_RETURN(TRUE);
401 
402  if (table->s->fields < ET_FIELD_COUNT)
403  DBUG_RETURN(TRUE);
404 
405  if (load_string_fields(table->field,
406  ET_FIELD_DB, &dbname,
407  ET_FIELD_NAME, &name,
408  ET_FIELD_BODY, &body,
409  ET_FIELD_DEFINER, &definer,
410  ET_FIELD_TIME_ZONE, &tz_name,
411  ET_FIELD_COUNT))
412  DBUG_RETURN(TRUE);
413 
414  if (load_time_zone(thd, tz_name))
415  DBUG_RETURN(TRUE);
416 
417  Event_creation_ctx::load_from_db(thd, &mem_root, dbname.str, name.str, table,
418  &creation_ctx);
419 
420  ptr= strchr(definer.str, '@');
421 
422  if (! ptr)
423  ptr= definer.str;
424 
425  len= ptr - definer.str;
426  definer_user.str= strmake_root(&mem_root, definer.str, len);
427  definer_user.length= len;
428  len= definer.length - len - 1;
429  /* 1:because of @ */
430  definer_host.str= strmake_root(&mem_root, ptr + 1, len);
431  definer_host.length= len;
432 
433  sql_mode= (sql_mode_t) table->field[ET_FIELD_SQL_MODE]->val_int();
434 
435  DBUG_RETURN(FALSE);
436 }
437 
438 
451 bool
453 {
454  char *ptr;
455  MYSQL_TIME time;
456  LEX_STRING tz_name;
457 
458  DBUG_ENTER("Event_queue_element::load_from_row");
459 
460  if (!table)
461  DBUG_RETURN(TRUE);
462 
463  if (table->s->fields < ET_FIELD_COUNT)
464  DBUG_RETURN(TRUE);
465 
466  if (load_string_fields(table->field,
467  ET_FIELD_DB, &dbname,
468  ET_FIELD_NAME, &name,
469  ET_FIELD_DEFINER, &definer,
470  ET_FIELD_TIME_ZONE, &tz_name,
471  ET_FIELD_COUNT))
472  DBUG_RETURN(TRUE);
473 
474  if (load_time_zone(thd, tz_name))
475  DBUG_RETURN(TRUE);
476 
477  starts_null= table->field[ET_FIELD_STARTS]->is_null();
478  my_bool not_used= FALSE;
479  if (!starts_null)
480  {
481  table->field[ET_FIELD_STARTS]->get_date(&time, TIME_NO_ZERO_DATE);
482  starts= my_tz_OFFSET0->TIME_to_gmt_sec(&time,&not_used);
483  }
484 
485  ends_null= table->field[ET_FIELD_ENDS]->is_null();
486  if (!ends_null)
487  {
488  table->field[ET_FIELD_ENDS]->get_date(&time, TIME_NO_ZERO_DATE);
489  ends= my_tz_OFFSET0->TIME_to_gmt_sec(&time,&not_used);
490  }
491 
492  if (!table->field[ET_FIELD_INTERVAL_EXPR]->is_null())
493  expression= table->field[ET_FIELD_INTERVAL_EXPR]->val_int();
494  else
495  expression= 0;
496  /*
497  If neigher STARTS and ENDS is set, then both fields are empty.
498  Hence, if ET_FIELD_EXECUTE_AT is empty there is an error.
499  */
500  execute_at_null= table->field[ET_FIELD_EXECUTE_AT]->is_null();
501  DBUG_ASSERT(!(starts_null && ends_null && !expression && execute_at_null));
502  if (!expression && !execute_at_null)
503  {
504  if (table->field[ET_FIELD_EXECUTE_AT]->get_date(&time,
505  TIME_NO_ZERO_DATE))
506  DBUG_RETURN(TRUE);
507  execute_at= my_tz_OFFSET0->TIME_to_gmt_sec(&time,&not_used);
508  }
509 
510  /*
511  We load the interval type from disk as string and then map it to
512  an integer. This decouples the values of enum interval_type
513  and values actually stored on disk. Therefore the type can be
514  reordered without risking incompatibilities of data between versions.
515  */
516  if (!table->field[ET_FIELD_TRANSIENT_INTERVAL]->is_null())
517  {
518  int i;
519  char buff[MAX_FIELD_WIDTH];
520  String str(buff, sizeof(buff), &my_charset_bin);
521  LEX_STRING tmp;
522 
523  table->field[ET_FIELD_TRANSIENT_INTERVAL]->val_str(&str);
524  if (!(tmp.length= str.length()))
525  DBUG_RETURN(TRUE);
526 
527  tmp.str= str.c_ptr_safe();
528 
529  i= find_string_in_array(interval_type_to_name, &tmp, system_charset_info);
530  if (i < 0)
531  DBUG_RETURN(TRUE);
532  interval= (interval_type) i;
533  }
534 
535  if (!table->field[ET_FIELD_LAST_EXECUTED]->is_null())
536  {
537  table->field[ET_FIELD_LAST_EXECUTED]->get_date(&time,
538  TIME_NO_ZERO_DATE);
539  last_executed= my_tz_OFFSET0->TIME_to_gmt_sec(&time,&not_used);
540  }
541 
542  if ((ptr= get_field(&mem_root, table->field[ET_FIELD_STATUS])) == NullS)
543  DBUG_RETURN(TRUE);
544 
545  DBUG_PRINT("load_from_row", ("Event [%s] is [%s]", name.str, ptr));
546 
547  /* Set event status (ENABLED | SLAVESIDE_DISABLED | DISABLED) */
548  switch (ptr[0])
549  {
550  case 'E' :
551  status = Event_parse_data::ENABLED;
552  break;
553  case 'S' :
554  status = Event_parse_data::SLAVESIDE_DISABLED;
555  break;
556  case 'D' :
557  default:
558  status = Event_parse_data::DISABLED;
559  break;
560  }
561  if ((ptr= get_field(&mem_root, table->field[ET_FIELD_ORIGINATOR])) == NullS)
562  DBUG_RETURN(TRUE);
563  originator = table->field[ET_FIELD_ORIGINATOR]->val_int();
564 
565  /* ToDo : Andrey . Find a way not to allocate ptr on event_mem_root */
566  if ((ptr= get_field(&mem_root,
567  table->field[ET_FIELD_ON_COMPLETION])) == NullS)
568  DBUG_RETURN(TRUE);
569 
570  on_completion= (ptr[0]=='D'? Event_parse_data::ON_COMPLETION_DROP:
571  Event_parse_data::ON_COMPLETION_PRESERVE);
572 
573  DBUG_RETURN(FALSE);
574 }
575 
576 
589 bool
591 {
592  char *ptr;
593  size_t len;
594 
595  DBUG_ENTER("Event_timed::load_from_row");
596 
597  if (Event_queue_element::load_from_row(thd, table))
598  DBUG_RETURN(TRUE);
599 
600  if (load_string_fields(table->field,
601  ET_FIELD_BODY, &body,
602  ET_FIELD_BODY_UTF8, &body_utf8,
603  ET_FIELD_COUNT))
604  DBUG_RETURN(TRUE);
605 
606  if (Event_creation_ctx::load_from_db(thd, &mem_root, dbname.str, name.str,
607  table, &creation_ctx))
608  {
609  push_warning_printf(thd,
610  Sql_condition::WARN_LEVEL_WARN,
611  ER_EVENT_INVALID_CREATION_CTX,
612  ER(ER_EVENT_INVALID_CREATION_CTX),
613  (const char *) dbname.str,
614  (const char *) name.str);
615  }
616 
617  ptr= strchr(definer.str, '@');
618 
619  if (! ptr)
620  ptr= definer.str;
621 
622  len= ptr - definer.str;
623  definer_user.str= strmake_root(&mem_root, definer.str, len);
624  definer_user.length= len;
625  len= definer.length - len - 1;
626  /* 1:because of @ */
627  definer_host.str= strmake_root(&mem_root, ptr + 1, len);
628  definer_host.length= len;
629 
630  created= table->field[ET_FIELD_CREATED]->val_int();
631  modified= table->field[ET_FIELD_MODIFIED]->val_int();
632 
633  comment.str= get_field(&mem_root, table->field[ET_FIELD_COMMENT]);
634  if (comment.str != NullS)
635  comment.length= strlen(comment.str);
636  else
637  comment.length= 0;
638 
639  sql_mode= (sql_mode_t) table->field[ET_FIELD_SQL_MODE]->val_int();
640 
641  DBUG_RETURN(FALSE);
642 }
643 
644 
645 /*
646  add_interval() adds a specified interval to time 'ltime' in time
647  zone 'time_zone', and returns the result converted to the number of
648  seconds since epoch (aka Unix time; in UTC time zone). Zero result
649  means an error.
650 */
651 static
652 my_time_t
653 add_interval(MYSQL_TIME *ltime, const Time_zone *time_zone,
654  interval_type scale, INTERVAL interval)
655 {
656  if (date_add_interval(ltime, scale, interval))
657  return 0;
658 
659  my_bool not_used;
660  return time_zone->TIME_to_gmt_sec(ltime, &not_used);
661 }
662 
663 
664 /*
665  Computes the sum of a timestamp plus interval.
666 
667  SYNOPSIS
668  get_next_time()
669  time_zone event time zone
670  next the sum
671  start add interval_value to this time
672  time_now current time
673  i_value quantity of time type interval to add
674  i_type type of interval to add (SECOND, MINUTE, HOUR, WEEK ...)
675 
676  RETURN VALUE
677  0 OK
678  1 Error
679 
680  NOTES
681  1) If the interval is conversible to SECOND, like MINUTE, HOUR, DAY, WEEK.
682  Then we use TIMEDIFF()'s implementation as underlying and number of
683  seconds as resolution for computation.
684  2) In all other cases - MONTH, QUARTER, YEAR we use MONTH as resolution
685  and PERIOD_DIFF()'s implementation
686 */
687 
688 static
689 bool get_next_time(const Time_zone *time_zone, my_time_t *next,
690  my_time_t start, my_time_t time_now,
691  int i_value, interval_type i_type)
692 {
693  DBUG_ENTER("get_next_time");
694  DBUG_PRINT("enter", ("start: %lu now: %lu", (long) start, (long) time_now));
695 
696  DBUG_ASSERT(start <= time_now);
697 
698  longlong months=0, seconds=0;
699 
700  switch (i_type) {
701  case INTERVAL_YEAR:
702  months= i_value*12;
703  break;
704  case INTERVAL_QUARTER:
705  /* Has already been converted to months */
706  case INTERVAL_YEAR_MONTH:
707  case INTERVAL_MONTH:
708  months= i_value;
709  break;
710  case INTERVAL_WEEK:
711  /* WEEK has already been converted to days */
712  case INTERVAL_DAY:
713  seconds= i_value*24*3600;
714  break;
715  case INTERVAL_DAY_HOUR:
716  case INTERVAL_HOUR:
717  seconds= i_value*3600;
718  break;
719  case INTERVAL_DAY_MINUTE:
720  case INTERVAL_HOUR_MINUTE:
721  case INTERVAL_MINUTE:
722  seconds= i_value*60;
723  break;
724  case INTERVAL_DAY_SECOND:
725  case INTERVAL_HOUR_SECOND:
726  case INTERVAL_MINUTE_SECOND:
727  case INTERVAL_SECOND:
728  seconds= i_value;
729  break;
730  case INTERVAL_DAY_MICROSECOND:
731  case INTERVAL_HOUR_MICROSECOND:
732  case INTERVAL_MINUTE_MICROSECOND:
733  case INTERVAL_SECOND_MICROSECOND:
734  case INTERVAL_MICROSECOND:
735  /*
736  We should return an error here so SHOW EVENTS/ SELECT FROM I_S.EVENTS
737  would give an error then.
738  */
739  DBUG_RETURN(1);
740  break;
741  case INTERVAL_LAST:
742  DBUG_ASSERT(0);
743  }
744  DBUG_PRINT("info", ("seconds: %ld months: %ld", (long) seconds, (long) months));
745 
746  MYSQL_TIME local_start;
747  MYSQL_TIME local_now;
748 
749  /* Convert times from UTC to local. */
750  {
751  time_zone->gmt_sec_to_TIME(&local_start, start);
752  time_zone->gmt_sec_to_TIME(&local_now, time_now);
753  }
754 
755  INTERVAL interval;
756  memset(&interval, 0, sizeof(interval));
757  my_time_t next_time= 0;
758 
759  if (seconds)
760  {
761  longlong seconds_diff;
762  long microsec_diff;
763  bool negative= calc_time_diff(&local_now, &local_start, 1,
764  &seconds_diff, &microsec_diff);
765  if (!negative)
766  {
767  /*
768  The formula below returns the interval that, when added to
769  local_start, will always give the time in the future.
770  */
771  interval.second= seconds_diff - seconds_diff % seconds + seconds;
772  next_time= add_interval(&local_start, time_zone,
773  INTERVAL_SECOND, interval);
774  if (next_time == 0)
775  goto done;
776  }
777 
778  if (next_time <= time_now)
779  {
780  /*
781  If 'negative' is true above, then 'next_time == 0', and
782  'next_time <= time_now' is also true. If negative is false,
783  then next_time was set, but perhaps to the value that is less
784  then time_now. See below for elaboration.
785  */
786  DBUG_ASSERT(negative || next_time > 0);
787 
788  /*
789  If local_now < local_start, i.e. STARTS time is in the future
790  according to the local time (it always in the past according
791  to UTC---this is a prerequisite of this function), then
792  STARTS is almost always in the past according to the local
793  time too. However, in the time zone that has backward
794  Daylight Saving Time shift, the following may happen: suppose
795  we have a backward DST shift at certain date after 2:59:59,
796  i.e. local time goes 1:59:59, 2:00:00, ... , 2:59:59, (shift
797  here) 2:00:00 (again), ... , 2:59:59 (again), 3:00:00, ... .
798  Now suppose the time has passed the first 2:59:59, has been
799  shifted backward, and now is (the second) 2:20:00. The user
800  does CREATE EVENT with STARTS 'current-date 2:40:00'. Local
801  time 2:40:00 from create statement is treated by time
802  functions as the first such time, so according to UTC it comes
803  before the second 2:20:00. But according to local time it is
804  obviously in the future, so we end up in this branch.
805 
806  Since we are in the second pass through 2:00:00--2:59:59, and
807  any local time form this interval is treated by system
808  functions as the time from the first pass, we have to find the
809  time for the next execution that is past the DST-affected
810  interval (past the second 2:59:59 for our example,
811  i.e. starting from 3:00:00). We do this in the loop until the
812  local time is mapped onto future UTC time. 'start' time is in
813  the past, so we may use 'do { } while' here, and add the first
814  interval right away.
815 
816  Alternatively, it could be that local_now >= local_start. Now
817  for the example above imagine we do CREATE EVENT with STARTS
818  'current-date 2:10:00'. Local start 2:10 is in the past (now
819  is local 2:20), so we add an interval, and get next execution
820  time, say, 2:40. It is in the future according to local time,
821  but, again, since we are in the second pass through
822  2:00:00--2:59:59, 2:40 will be converted into UTC time in the
823  past. So we will end up in this branch again, and may add
824  intervals in a 'do { } while' loop.
825 
826  Note that for any given event we may end up here only if event
827  next execution time will map to the time interval that is
828  passed twice, and only if the server was started during the
829  second pass, or the event is being created during the second
830  pass. After that, we never will get here (unless we again
831  start the server during the second pass). In other words,
832  such a condition is extremely rare.
833  */
834  interval.second= seconds;
835  do
836  {
837  next_time= add_interval(&local_start, time_zone,
838  INTERVAL_SECOND, interval);
839  if (next_time == 0)
840  goto done;
841  }
842  while (next_time <= time_now);
843  }
844  }
845  else
846  {
847  long diff_months= ((long) local_now.year - (long) local_start.year)*12 +
848  ((long) local_now.month - (long) local_start.month);
849 
850  /*
851  Unlike for seconds above, the formula below returns the interval
852  that, when added to the local_start, will give the time in the
853  past, or somewhere in the current month. We are interested in
854  the latter case, to see if this time has already passed, or is
855  yet to come this month.
856 
857  Note that the time is guaranteed to be in the past unless
858  (diff_months % months == 0), but no good optimization is
859  possible here, because (diff_months % months == 0) is what will
860  happen most of the time, as get_next_time() will be called right
861  after the execution of the event. We could pass last_executed
862  time to this function, and see if the execution has already
863  happened this month, but for that we will have to convert
864  last_executed from seconds since epoch to local broken-down
865  time, and this will greatly reduce the effect of the
866  optimization. So instead we keep the code simple and clean.
867  */
868  interval.month= (ulong) (diff_months - diff_months % months);
869  next_time= add_interval(&local_start, time_zone,
870  INTERVAL_MONTH, interval);
871  if (next_time == 0)
872  goto done;
873 
874  if (next_time <= time_now)
875  {
876  interval.month= (ulong) months;
877  next_time= add_interval(&local_start, time_zone,
878  INTERVAL_MONTH, interval);
879  if (next_time == 0)
880  goto done;
881  }
882  }
883 
884  DBUG_ASSERT(time_now < next_time);
885 
886  *next= next_time;
887 
888 done:
889  DBUG_PRINT("info", ("next_time: %ld", (long) next_time));
890  DBUG_RETURN(next_time == 0);
891 }
892 
893 
894 /*
895  Computes next execution time.
896 
897  SYNOPSIS
898  Event_queue_element::compute_next_execution_time()
899 
900  RETURN VALUE
901  FALSE OK
902  TRUE Error
903 
904  NOTES
905  The time is set in execute_at, if no more executions the latter is
906  set to 0.
907 */
908 
909 bool
910 Event_queue_element::compute_next_execution_time()
911 {
912  my_time_t time_now;
913  DBUG_ENTER("Event_queue_element::compute_next_execution_time");
914  DBUG_PRINT("enter", ("starts: %lu ends: %lu last_executed: %lu this: 0x%lx",
915  (long) starts, (long) ends, (long) last_executed,
916  (long) this));
917 
918  if (status != Event_parse_data::ENABLED)
919  {
920  DBUG_PRINT("compute_next_execution_time",
921  ("Event %s is DISABLED", name.str));
922  goto ret;
923  }
924  /* If one-time, no need to do computation */
925  if (!expression)
926  {
927  /* Let's check whether it was executed */
928  if (last_executed)
929  {
930  DBUG_PRINT("info",("One-time event %s.%s of was already executed",
931  dbname.str, name.str));
932  dropped= (on_completion == Event_parse_data::ON_COMPLETION_DROP);
933  DBUG_PRINT("info",("One-time event will be dropped: %d.", dropped));
934 
935  status= Event_parse_data::DISABLED;
936  }
937  goto ret;
938  }
939 
940  time_now= (my_time_t) current_thd->query_start();
941 
942  DBUG_PRINT("info",("NOW: [%lu]", (ulong) time_now));
943 
944  /* if time_now is after ends don't execute anymore */
945  if (!ends_null && ends < time_now)
946  {
947  DBUG_PRINT("info", ("NOW after ENDS, don't execute anymore"));
948  /* time_now is after ends. don't execute anymore */
949  execute_at= 0;
950  execute_at_null= TRUE;
951  if (on_completion == Event_parse_data::ON_COMPLETION_DROP)
952  dropped= TRUE;
953  DBUG_PRINT("info", ("Dropped: %d", dropped));
954  status= Event_parse_data::DISABLED;
955 
956  goto ret;
957  }
958 
959  /*
960  Here time_now is before or equals ends if the latter is set.
961  Let's check whether time_now is before starts.
962  If so schedule for starts.
963  */
964  if (!starts_null && time_now <= starts)
965  {
966  if (time_now == starts && starts == last_executed)
967  {
968  /*
969  do nothing or we will schedule for second time execution at starts.
970  */
971  }
972  else
973  {
974  DBUG_PRINT("info", ("STARTS is future, NOW <= STARTS,sched for STARTS"));
975  /*
976  starts is in the future
977  time_now before starts. Scheduling for starts
978  */
979  execute_at= starts;
980  execute_at_null= FALSE;
981  goto ret;
982  }
983  }
984 
985  if (!starts_null && !ends_null)
986  {
987  /*
988  Both starts and m_ends are set and time_now is between them (incl.)
989  If last_executed is set then increase with m_expression. The new MYSQL_TIME is
990  after m_ends set execute_at to 0. And check for on_completion
991  If not set then schedule for now.
992  */
993  DBUG_PRINT("info", ("Both STARTS & ENDS are set"));
994  if (!last_executed)
995  {
996  DBUG_PRINT("info", ("Not executed so far."));
997  }
998 
999  {
1000  my_time_t next_exec;
1001 
1002  if (get_next_time(time_zone, &next_exec, starts, time_now,
1003  (int) expression, interval))
1004  goto err;
1005 
1006  /* There was previous execution */
1007  if (ends < next_exec)
1008  {
1009  DBUG_PRINT("info", ("Next execution of %s after ENDS. Stop executing.",
1010  name.str));
1011  /* Next execution after ends. No more executions */
1012  execute_at= 0;
1013  execute_at_null= TRUE;
1014  if (on_completion == Event_parse_data::ON_COMPLETION_DROP)
1015  dropped= TRUE;
1016  status= Event_parse_data::DISABLED;
1017  }
1018  else
1019  {
1020  DBUG_PRINT("info",("Next[%lu]", (ulong) next_exec));
1021  execute_at= next_exec;
1022  execute_at_null= FALSE;
1023  }
1024  }
1025  goto ret;
1026  }
1027  else if (starts_null && ends_null)
1028  {
1029  /* starts is always set, so this is a dead branch !! */
1030  DBUG_PRINT("info", ("Neither STARTS nor ENDS are set"));
1031  /*
1032  Both starts and m_ends are not set, so we schedule for the next
1033  based on last_executed.
1034  */
1035  if (last_executed)
1036  {
1037  my_time_t next_exec;
1038  if (get_next_time(time_zone, &next_exec, starts, time_now,
1039  (int) expression, interval))
1040  goto err;
1041  execute_at= next_exec;
1042  DBUG_PRINT("info",("Next[%lu]", (ulong) next_exec));
1043  }
1044  else
1045  {
1046  /* last_executed not set. Schedule the event for now */
1047  DBUG_PRINT("info", ("Execute NOW"));
1048  execute_at= time_now;
1049  }
1050  execute_at_null= FALSE;
1051  }
1052  else
1053  {
1054  /* either starts or m_ends is set */
1055  if (!starts_null)
1056  {
1057  DBUG_PRINT("info", ("STARTS is set"));
1058  /*
1059  - starts is set.
1060  - starts is not in the future according to check made before
1061  Hence schedule for starts + m_expression in case last_executed
1062  is not set, otherwise to last_executed + m_expression
1063  */
1064  if (!last_executed)
1065  {
1066  DBUG_PRINT("info", ("Not executed so far."));
1067  }
1068 
1069  {
1070  my_time_t next_exec;
1071  if (get_next_time(time_zone, &next_exec, starts, time_now,
1072  (int) expression, interval))
1073  goto err;
1074  execute_at= next_exec;
1075  DBUG_PRINT("info",("Next[%lu]", (ulong) next_exec));
1076  }
1077  execute_at_null= FALSE;
1078  }
1079  else
1080  {
1081  /* this is a dead branch, because starts is always set !!! */
1082  DBUG_PRINT("info", ("STARTS is not set. ENDS is set"));
1083  /*
1084  - m_ends is set
1085  - m_ends is after time_now or is equal
1086  Hence check for m_last_execute and increment with m_expression.
1087  If last_executed is not set then schedule for now
1088  */
1089 
1090  if (!last_executed)
1091  execute_at= time_now;
1092  else
1093  {
1094  my_time_t next_exec;
1095 
1096  if (get_next_time(time_zone, &next_exec, starts, time_now,
1097  (int) expression, interval))
1098  goto err;
1099 
1100  if (ends < next_exec)
1101  {
1102  DBUG_PRINT("info", ("Next execution after ENDS. Stop executing."));
1103  execute_at= 0;
1104  execute_at_null= TRUE;
1105  status= Event_parse_data::DISABLED;
1106  if (on_completion == Event_parse_data::ON_COMPLETION_DROP)
1107  dropped= TRUE;
1108  }
1109  else
1110  {
1111  DBUG_PRINT("info", ("Next[%lu]", (ulong) next_exec));
1112  execute_at= next_exec;
1113  execute_at_null= FALSE;
1114  }
1115  }
1116  }
1117  goto ret;
1118  }
1119 ret:
1120  DBUG_PRINT("info", ("ret: 0 execute_at: %lu", (long) execute_at));
1121  DBUG_RETURN(FALSE);
1122 err:
1123  DBUG_PRINT("info", ("ret=1"));
1124  DBUG_RETURN(TRUE);
1125 }
1126 
1127 
1128 /*
1129  Set the internal last_executed MYSQL_TIME struct to now. NOW is the
1130  time according to thd->query_start(), so the THD's clock.
1131 
1132  SYNOPSIS
1133  Event_queue_element::mark_last_executed()
1134  thd thread context
1135 */
1136 
1137 void
1138 Event_queue_element::mark_last_executed(THD *thd)
1139 {
1140  last_executed= (my_time_t) thd->query_start();
1141 
1142  execution_count++;
1143 }
1144 
1145 
1146 static
1147 void
1148 append_datetime(String *buf, Time_zone *time_zone, my_time_t secs,
1149  const char *name, uint len)
1150 {
1151  char dtime_buff[20*2+32];/* +32 to make my_snprintf_{8bit|ucs2} happy */
1152  buf->append(STRING_WITH_LEN(" "));
1153  buf->append(name, len);
1154  buf->append(STRING_WITH_LEN(" '"));
1155  /*
1156  Pass the buffer and the second param tells fills the buffer and
1157  returns the number of chars to copy.
1158  */
1159  MYSQL_TIME time;
1160  time_zone->gmt_sec_to_TIME(&time, secs);
1161  buf->append(dtime_buff, my_datetime_to_str(&time, dtime_buff, 0));
1162  buf->append(STRING_WITH_LEN("'"));
1163 }
1164 
1165 
1166 /*
1167  Get SHOW CREATE EVENT as string
1168 
1169  SYNOPSIS
1170  Event_timed::get_create_event(THD *thd, String *buf)
1171  thd Thread
1172  buf String*, should be already allocated. CREATE EVENT goes inside.
1173 
1174  RETURN VALUE
1175  0 OK
1176  EVEX_MICROSECOND_UNSUP Error (for now if mysql.event has been
1177  tampered and MICROSECONDS interval or
1178  derivative has been put there.
1179 */
1180 
1181 int
1182 Event_timed::get_create_event(THD *thd, String *buf)
1183 {
1184  char tmp_buf[2 * STRING_BUFFER_USUAL_SIZE];
1185  String expr_buf(tmp_buf, sizeof(tmp_buf), system_charset_info);
1186  expr_buf.length(0);
1187 
1188  DBUG_ENTER("get_create_event");
1189  DBUG_PRINT("ret_info",("body_len=[%d]body=[%s]",
1190  (int) body.length, body.str));
1191 
1192  if (expression && Events::reconstruct_interval_expression(&expr_buf, interval,
1193  expression))
1194  DBUG_RETURN(EVEX_MICROSECOND_UNSUP);
1195 
1196  buf->append(STRING_WITH_LEN("CREATE "));
1197  append_definer(thd, buf, &definer_user, &definer_host);
1198  buf->append(STRING_WITH_LEN("EVENT "));
1199  append_identifier(thd, buf, name.str, name.length);
1200 
1201  if (expression)
1202  {
1203  buf->append(STRING_WITH_LEN(" ON SCHEDULE EVERY "));
1204  buf->append(expr_buf);
1205  buf->append(' ');
1206  LEX_STRING *ival= &interval_type_to_name[interval];
1207  buf->append(ival->str, ival->length);
1208 
1209  if (!starts_null)
1210  append_datetime(buf, time_zone, starts, STRING_WITH_LEN("STARTS"));
1211 
1212  if (!ends_null)
1213  append_datetime(buf, time_zone, ends, STRING_WITH_LEN("ENDS"));
1214  }
1215  else
1216  {
1217  append_datetime(buf, time_zone, execute_at,
1218  STRING_WITH_LEN("ON SCHEDULE AT"));
1219  }
1220 
1221  if (on_completion == Event_parse_data::ON_COMPLETION_DROP)
1222  buf->append(STRING_WITH_LEN(" ON COMPLETION NOT PRESERVE "));
1223  else
1224  buf->append(STRING_WITH_LEN(" ON COMPLETION PRESERVE "));
1225 
1226  if (status == Event_parse_data::ENABLED)
1227  buf->append(STRING_WITH_LEN("ENABLE"));
1228  else if (status == Event_parse_data::SLAVESIDE_DISABLED)
1229  buf->append(STRING_WITH_LEN("DISABLE ON SLAVE"));
1230  else
1231  buf->append(STRING_WITH_LEN("DISABLE"));
1232 
1233  if (comment.length)
1234  {
1235  buf->append(STRING_WITH_LEN(" COMMENT "));
1236  append_unescaped(buf, comment.str, comment.length);
1237  }
1238  buf->append(STRING_WITH_LEN(" DO "));
1239  buf->append(body.str, body.length);
1240 
1241  DBUG_RETURN(0);
1242 }
1243 
1244 
1249 bool
1250 Event_job_data::construct_sp_sql(THD *thd, String *sp_sql)
1251 {
1252  LEX_STRING buffer;
1253  const uint STATIC_SQL_LENGTH= 44;
1254 
1255  DBUG_ENTER("Event_job_data::construct_sp_sql");
1256 
1257  /*
1258  Allocate a large enough buffer on the thread execution memory
1259  root to avoid multiple [re]allocations on system heap
1260  */
1261  buffer.length= STATIC_SQL_LENGTH + name.length + body.length;
1262  if (! (buffer.str= (char*) thd->alloc(buffer.length)))
1263  DBUG_RETURN(TRUE);
1264 
1265  sp_sql->set(buffer.str, buffer.length, system_charset_info);
1266  sp_sql->length(0);
1267 
1268 
1269  sp_sql->append(C_STRING_WITH_LEN("CREATE "));
1270  sp_sql->append(C_STRING_WITH_LEN("PROCEDURE "));
1271  /*
1272  Let's use the same name as the event name to perhaps produce a
1273  better error message in case it is a part of some parse error.
1274  We're using append_identifier here to successfully parse
1275  events with reserved names.
1276  */
1277  append_identifier(thd, sp_sql, name.str, name.length);
1278 
1279  /*
1280  The default SQL security of a stored procedure is DEFINER. We
1281  have already activated the security context of the event, so
1282  let's execute the procedure with the invoker rights to save on
1283  resets of security contexts.
1284  */
1285  sp_sql->append(C_STRING_WITH_LEN("() SQL SECURITY INVOKER "));
1286 
1287  sp_sql->append(body.str, body.length);
1288 
1289  DBUG_RETURN(thd->is_fatal_error);
1290 }
1291 
1292 
1298 bool
1299 Event_job_data::construct_drop_event_sql(THD *thd, String *sp_sql)
1300 {
1301  LEX_STRING buffer;
1302  const uint STATIC_SQL_LENGTH= 14;
1303 
1304  DBUG_ENTER("Event_job_data::construct_drop_event_sql");
1305 
1306  buffer.length= STATIC_SQL_LENGTH + name.length*2 + dbname.length*2;
1307  if (! (buffer.str= (char*) thd->alloc(buffer.length)))
1308  DBUG_RETURN(TRUE);
1309 
1310  sp_sql->set(buffer.str, buffer.length, system_charset_info);
1311  sp_sql->length(0);
1312 
1313  sp_sql->append(C_STRING_WITH_LEN("DROP EVENT "));
1314  append_identifier(thd, sp_sql, dbname.str, dbname.length);
1315  sp_sql->append('.');
1316  append_identifier(thd, sp_sql, name.str, name.length);
1317 
1318  DBUG_RETURN(thd->is_fatal_error);
1319 }
1320 
1328 bool
1329 Event_job_data::execute(THD *thd, bool drop)
1330 {
1331  String sp_sql;
1332 #ifndef NO_EMBEDDED_ACCESS_CHECKS
1333  Security_context event_sctx, *save_sctx= NULL;
1334 #endif
1335  List<Item> empty_item_list;
1336  bool ret= TRUE;
1337  PSI_statement_locker *parent_locker= thd->m_statement_psi;
1338 
1339  DBUG_ENTER("Event_job_data::execute");
1340 
1342 
1343  /*
1344  MySQL parser currently assumes that current database is either
1345  present in THD or all names in all statements are fully specified.
1346  And yet not fully specified names inside stored programs must be
1347  be supported, even if the current database is not set:
1348  CREATE PROCEDURE db1.p1() BEGIN CREATE TABLE t1; END//
1349  -- in this example t1 should be always created in db1 and the statement
1350  must parse even if there is no current database.
1351 
1352  To support this feature and still address the parser limitation,
1353  we need to set the current database here.
1354  We don't have to call mysql_change_db, since the checks performed
1355  in it are unnecessary for the purpose of parsing, and
1356  mysql_change_db will be invoked anyway later, to activate the
1357  procedure database before it's executed.
1358  */
1359  thd->set_db(dbname.str, dbname.length);
1360 
1361  lex_start(thd);
1362 
1363 #ifndef NO_EMBEDDED_ACCESS_CHECKS
1364  if (event_sctx.change_security_context(thd,
1365  &definer_user, &definer_host,
1366  &dbname, &save_sctx))
1367  {
1368  sql_print_error("Event Scheduler: "
1369  "[%s].[%s.%s] execution failed, "
1370  "failed to authenticate the user.",
1371  definer.str, dbname.str, name.str);
1372  goto end;
1373  }
1374 #endif
1375 
1376  if (check_access(thd, EVENT_ACL, dbname.str, NULL, NULL, 0, 0))
1377  {
1378  /*
1379  This aspect of behavior is defined in the worklog,
1380  and this is how triggers work too: if TRIGGER
1381  privilege is revoked from trigger definer,
1382  triggers are not executed.
1383  */
1384  sql_print_error("Event Scheduler: "
1385  "[%s].[%s.%s] execution failed, "
1386  "user no longer has EVENT privilege.",
1387  definer.str, dbname.str, name.str);
1388  goto end;
1389  }
1390 
1391  if (construct_sp_sql(thd, &sp_sql))
1392  goto end;
1393 
1394  /*
1395  Set up global thread attributes to reflect the properties of
1396  this Event. We can simply reset these instead of usual
1397  backup/restore employed in stored programs since we know that
1398  this is a top level statement and the worker thread is
1399  allocated exclusively to execute this event.
1400  */
1401 
1402  thd->variables.sql_mode= sql_mode;
1403  thd->variables.time_zone= time_zone;
1404 
1405  thd->set_query(sp_sql.c_ptr_safe(), sp_sql.length());
1406 
1407  {
1408  Parser_state parser_state;
1409  if (parser_state.init(thd, thd->query(), thd->query_length()))
1410  goto end;
1411 
1412  thd->m_statement_psi= NULL;
1413  if (parse_sql(thd, & parser_state, creation_ctx))
1414  {
1415  sql_print_error("Event Scheduler: "
1416  "%serror during compilation of %s.%s",
1417  thd->is_fatal_error ? "fatal " : "",
1418  (const char *) dbname.str, (const char *) name.str);
1419  thd->m_statement_psi= parent_locker;
1420  goto end;
1421  }
1422  thd->m_statement_psi= parent_locker;
1423  }
1424 
1425  {
1426  sp_head *sphead= thd->lex->sphead;
1427 
1428  DBUG_ASSERT(sphead);
1429 
1430  if (thd->enable_slow_log)
1431  sphead->m_flags|= sp_head::LOG_SLOW_STATEMENTS;
1432  sphead->m_flags|= sp_head::LOG_GENERAL_LOG;
1433 
1434  sphead->set_info(0, 0, &thd->lex->sp_chistics, sql_mode);
1435  sphead->set_creation_ctx(creation_ctx);
1436  sphead->optimize();
1437 
1438  ret= sphead->execute_procedure(thd, &empty_item_list);
1439  /*
1440  There is no pre-locking and therefore there should be no
1441  tables open and locked left after execute_procedure.
1442  */
1443  }
1444 
1445 end:
1446  if (drop && !thd->is_fatal_error)
1447  {
1448  /*
1449  We must do it here since here we're under the right authentication
1450  ID of the event definer.
1451  */
1452  sql_print_information("Event Scheduler: Dropping %s.%s",
1453  (const char *) dbname.str, (const char *) name.str);
1454  /*
1455  Construct a query for the binary log, to ensure the event is dropped
1456  on the slave
1457  */
1458  if (construct_drop_event_sql(thd, &sp_sql))
1459  ret= 1;
1460  else
1461  {
1462  ulong saved_master_access;
1463 
1464  thd->set_query(sp_sql.c_ptr_safe(), sp_sql.length());
1465 
1466  /*
1467  NOTE: even if we run in read-only mode, we should be able to lock
1468  the mysql.event table for writing. In order to achieve this, we
1469  should call mysql_lock_tables() under the super-user.
1470 
1471  Same goes for transaction access mode.
1472  Temporarily reset it to read-write.
1473  */
1474 
1475  saved_master_access= thd->security_ctx->master_access;
1476  thd->security_ctx->master_access |= SUPER_ACL;
1477  bool save_tx_read_only= thd->tx_read_only;
1478  thd->tx_read_only= false;
1479 
1480  ret= Events::drop_event(thd, dbname, name, FALSE);
1481 
1482  thd->tx_read_only= save_tx_read_only;
1483  thd->security_ctx->master_access= saved_master_access;
1484  }
1485  }
1486 #ifndef NO_EMBEDDED_ACCESS_CHECKS
1487  if (save_sctx)
1488  event_sctx.restore_security_context(thd, save_sctx);
1489 #endif
1490  thd->lex->unit.cleanup();
1491  thd->end_statement();
1492  thd->cleanup_after_query();
1493  /* Avoid races with SHOW PROCESSLIST */
1494  thd->reset_query();
1495 
1496  DBUG_PRINT("info", ("EXECUTED %s.%s ret: %d", dbname.str, name.str, ret));
1497 
1498  DBUG_RETURN(ret);
1499 }
1500 
1501 
1502 /*
1503  Checks whether two events are in the same schema
1504 
1505  SYNOPSIS
1506  event_basic_db_equal()
1507  db Schema
1508  et Compare et->dbname to `db`
1509 
1510  RETURN VALUE
1511  TRUE Equal
1512  FALSE Not equal
1513 */
1514 
1515 bool
1516 event_basic_db_equal(LEX_STRING db, Event_basic *et)
1517 {
1518  return !sortcmp_lex_string(et->dbname, db, system_charset_info);
1519 }
1520 
1521 
1522 /*
1523  Checks whether an event has equal `db` and `name`
1524 
1525  SYNOPSIS
1526  event_basic_identifier_equal()
1527  db Schema
1528  name Name
1529  et The event object
1530 
1531  RETURN VALUE
1532  TRUE Equal
1533  FALSE Not equal
1534 */
1535 
1536 bool
1537 event_basic_identifier_equal(LEX_STRING db, LEX_STRING name, Event_basic *b)
1538 {
1539  return !sortcmp_lex_string(name, b->name, system_charset_info) &&
1540  !sortcmp_lex_string(db, b->dbname, system_charset_info);
1541 }
1542