MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
event_db_repository.cc
1 /*
2  Copyright (c) 2006, 2013, Oracle and/or its affiliates. All rights reserved.
3 
4  This program is free software; you can redistribute it and/or modify
5  it under the terms of the GNU General Public License as published by
6  the Free Software Foundation; version 2 of the License.
7 
8  This program is distributed in the hope that it will be useful,
9  but WITHOUT ANY WARRANTY; without even the implied warranty of
10  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11  GNU General Public License for more details.
12 
13  You should have received a copy of the GNU General Public License
14  along with this program; if not, write to the Free Software
15  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
16 
17 #include "sql_priv.h"
18 #include "unireg.h"
19 #include "sql_base.h" // close_thread_tables
20 #include "event_db_repository.h"
21 #include "key.h" // key_copy
22 #include "sql_db.h" // get_default_db_collation
23 #include "sql_time.h" // interval_type_to_name
24 #include "tztime.h" // struct Time_zone
25 #include "sql_acl.h" // SUPER_ACL, MYSQL_DB_FIELD_COUNT, mysql_db_table_fields
26 #include "records.h" // init_read_record, end_read_record
27 #include "sp_head.h"
28 #include "event_data_objects.h"
29 #include "events.h"
30 #include "sql_show.h"
31 #include "lock.h" // MYSQL_LOCK_IGNORE_TIMEOUT
32 
38 static
39 const TABLE_FIELD_TYPE event_table_fields[ET_FIELD_COUNT] =
40 {
41  {
42  { C_STRING_WITH_LEN("db") },
43  { C_STRING_WITH_LEN("char(64)") },
44  { C_STRING_WITH_LEN("utf8") }
45  },
46  {
47  { C_STRING_WITH_LEN("name") },
48  { C_STRING_WITH_LEN("char(64)") },
49  { C_STRING_WITH_LEN("utf8") }
50  },
51  {
52  { C_STRING_WITH_LEN("body") },
53  { C_STRING_WITH_LEN("longblob") },
54  {NULL, 0}
55  },
56  {
57  { C_STRING_WITH_LEN("definer") },
58  { C_STRING_WITH_LEN("char(77)") },
59  { C_STRING_WITH_LEN("utf8") }
60  },
61  {
62  { C_STRING_WITH_LEN("execute_at") },
63  { C_STRING_WITH_LEN("datetime") },
64  {NULL, 0}
65  },
66  {
67  { C_STRING_WITH_LEN("interval_value") },
68  { C_STRING_WITH_LEN("int(11)") },
69  {NULL, 0}
70  },
71  {
72  { C_STRING_WITH_LEN("interval_field") },
73  { C_STRING_WITH_LEN("enum('YEAR','QUARTER','MONTH','DAY',"
74  "'HOUR','MINUTE','WEEK','SECOND','MICROSECOND','YEAR_MONTH','DAY_HOUR',"
75  "'DAY_MINUTE','DAY_SECOND','HOUR_MINUTE','HOUR_SECOND','MINUTE_SECOND',"
76  "'DAY_MICROSECOND','HOUR_MICROSECOND','MINUTE_MICROSECOND',"
77  "'SECOND_MICROSECOND')") },
78  {NULL, 0}
79  },
80  {
81  { C_STRING_WITH_LEN("created") },
82  { C_STRING_WITH_LEN("timestamp") },
83  {NULL, 0}
84  },
85  {
86  { C_STRING_WITH_LEN("modified") },
87  { C_STRING_WITH_LEN("timestamp") },
88  {NULL, 0}
89  },
90  {
91  { C_STRING_WITH_LEN("last_executed") },
92  { C_STRING_WITH_LEN("datetime") },
93  {NULL, 0}
94  },
95  {
96  { C_STRING_WITH_LEN("starts") },
97  { C_STRING_WITH_LEN("datetime") },
98  {NULL, 0}
99  },
100  {
101  { C_STRING_WITH_LEN("ends") },
102  { C_STRING_WITH_LEN("datetime") },
103  {NULL, 0}
104  },
105  {
106  { C_STRING_WITH_LEN("status") },
107  { C_STRING_WITH_LEN("enum('ENABLED','DISABLED','SLAVESIDE_DISABLED')") },
108  {NULL, 0}
109  },
110  {
111  { C_STRING_WITH_LEN("on_completion") },
112  { C_STRING_WITH_LEN("enum('DROP','PRESERVE')") },
113  {NULL, 0}
114  },
115  {
116  { C_STRING_WITH_LEN("sql_mode") },
117  { C_STRING_WITH_LEN("set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES',"
118  "'IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION',"
119  "'NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB',"
120  "'NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40',"
121  "'ANSI','NO_AUTO_VALUE_ON_ZERO','NO_BACKSLASH_ESCAPES','STRICT_TRANS_TABLES',"
122  "'STRICT_ALL_TABLES','NO_ZERO_IN_DATE','NO_ZERO_DATE','INVALID_DATES',"
123  "'ERROR_FOR_DIVISION_BY_ZERO','TRADITIONAL','NO_AUTO_CREATE_USER',"
124  "'HIGH_NOT_PRECEDENCE','NO_ENGINE_SUBSTITUTION','PAD_CHAR_TO_FULL_LENGTH')") },
125  {NULL, 0}
126  },
127  {
128  { C_STRING_WITH_LEN("comment") },
129  { C_STRING_WITH_LEN("char(64)") },
130  { C_STRING_WITH_LEN("utf8") }
131  },
132  {
133  { C_STRING_WITH_LEN("originator") },
134  { C_STRING_WITH_LEN("int(10)") },
135  {NULL, 0}
136  },
137  {
138  { C_STRING_WITH_LEN("time_zone") },
139  { C_STRING_WITH_LEN("char(64)") },
140  { C_STRING_WITH_LEN("latin1") }
141  },
142  {
143  { C_STRING_WITH_LEN("character_set_client") },
144  { C_STRING_WITH_LEN("char(32)") },
145  { C_STRING_WITH_LEN("utf8") }
146  },
147  {
148  { C_STRING_WITH_LEN("collation_connection") },
149  { C_STRING_WITH_LEN("char(32)") },
150  { C_STRING_WITH_LEN("utf8") }
151  },
152  {
153  { C_STRING_WITH_LEN("db_collation") },
154  { C_STRING_WITH_LEN("char(32)") },
155  { C_STRING_WITH_LEN("utf8") }
156  },
157  {
158  { C_STRING_WITH_LEN("body_utf8") },
159  { C_STRING_WITH_LEN("longblob") },
160  { NULL, 0 }
161  }
162 };
163 
164 static const TABLE_FIELD_DEF
165  event_table_def= {ET_FIELD_COUNT, event_table_fields};
166 
168 {
169 protected:
170  void report_error(uint, const char *fmt, ...)
171  {
172  va_list args;
173  va_start(args, fmt);
174  error_log_print(ERROR_LEVEL, fmt, args);
175  va_end(args);
176  }
177 };
178 
180 static Event_db_intact table_intact;
181 
182 
198 static bool
199 mysql_event_fill_row(THD *thd,
200  TABLE *table,
201  Event_parse_data *et,
202  sp_head *sp,
203  sql_mode_t sql_mode,
204  my_bool is_update)
205 {
206  CHARSET_INFO *scs= system_charset_info;
207  enum enum_events_table_field f_num;
208  Field **fields= table->field;
209  int rs= FALSE;
210 
211  DBUG_ENTER("mysql_event_fill_row");
212 
213  DBUG_PRINT("info", ("dbname=[%s]", et->dbname.str));
214  DBUG_PRINT("info", ("name =[%s]", et->name.str));
215 
216  DBUG_ASSERT(et->on_completion != Event_parse_data::ON_COMPLETION_DEFAULT);
217 
218  if (table->s->fields < ET_FIELD_COUNT)
219  {
220  /*
221  Safety: this can only happen if someone started the server
222  and then altered mysql.event.
223  */
224  my_error(ER_COL_COUNT_DOESNT_MATCH_CORRUPTED_V2, MYF(0),
225  table->s->db.str, table->s->table_name.str,
226  (int) ET_FIELD_COUNT, table->s->fields);
227  DBUG_RETURN(TRUE);
228  }
229 
230  if (fields[f_num= ET_FIELD_DEFINER]->
231  store(et->definer.str, et->definer.length, scs))
232  goto err_truncate;
233 
234  if (fields[f_num= ET_FIELD_DB]->store(et->dbname.str, et->dbname.length, scs))
235  goto err_truncate;
236 
237  if (fields[f_num= ET_FIELD_NAME]->store(et->name.str, et->name.length, scs))
238  goto err_truncate;
239 
240  /* ON_COMPLETION field is NOT NULL thus not calling set_notnull()*/
241  rs|= fields[ET_FIELD_ON_COMPLETION]->store((longlong)et->on_completion, TRUE);
242 
243  /*
244  Set STATUS value unconditionally in case of CREATE EVENT.
245  For ALTER EVENT set it only if value of this field was changed.
246  Since STATUS field is NOT NULL call to set_notnull() is not needed.
247  */
248  if (!is_update || et->status_changed)
249  rs|= fields[ET_FIELD_STATUS]->store((longlong)et->status, TRUE);
250  rs|= fields[ET_FIELD_ORIGINATOR]->store((longlong)et->originator, TRUE);
251 
252  /*
253  Change the SQL_MODE only if body was present in an ALTER EVENT and of course
254  always during CREATE EVENT.
255  */
256  if (et->body_changed)
257  {
258  DBUG_ASSERT(sp->m_body.str);
259 
260  rs|= fields[ET_FIELD_SQL_MODE]->store((longlong)sql_mode, TRUE);
261 
262  if (fields[f_num= ET_FIELD_BODY]->store(sp->m_body.str,
263  sp->m_body.length,
264  scs))
265  {
266  goto err_truncate;
267  }
268  }
269 
270  if (et->expression)
271  {
272  const String *tz_name= thd->variables.time_zone->get_name();
273  if (!is_update || !et->starts_null)
274  {
275  fields[ET_FIELD_TIME_ZONE]->set_notnull();
276  rs|= fields[ET_FIELD_TIME_ZONE]->store(tz_name->ptr(), tz_name->length(),
277  tz_name->charset());
278  }
279 
280  fields[ET_FIELD_INTERVAL_EXPR]->set_notnull();
281  rs|= fields[ET_FIELD_INTERVAL_EXPR]->store((longlong)et->expression, TRUE);
282 
283  fields[ET_FIELD_TRANSIENT_INTERVAL]->set_notnull();
284 
285  rs|= fields[ET_FIELD_TRANSIENT_INTERVAL]->
286  store(interval_type_to_name[et->interval].str,
287  interval_type_to_name[et->interval].length,
288  scs);
289 
290  fields[ET_FIELD_EXECUTE_AT]->set_null();
291 
292  if (!et->starts_null)
293  {
294  MYSQL_TIME time;
295  my_tz_OFFSET0->gmt_sec_to_TIME(&time, et->starts);
296 
297  fields[ET_FIELD_STARTS]->set_notnull();
298  fields[ET_FIELD_STARTS]->store_time(&time);
299  }
300 
301  if (!et->ends_null)
302  {
303  MYSQL_TIME time;
304  my_tz_OFFSET0->gmt_sec_to_TIME(&time, et->ends);
305 
306  fields[ET_FIELD_ENDS]->set_notnull();
307  fields[ET_FIELD_ENDS]->store_time(&time);
308  }
309  }
310  else if (et->execute_at)
311  {
312  const String *tz_name= thd->variables.time_zone->get_name();
313  fields[ET_FIELD_TIME_ZONE]->set_notnull();
314  rs|= fields[ET_FIELD_TIME_ZONE]->store(tz_name->ptr(), tz_name->length(),
315  tz_name->charset());
316 
317  fields[ET_FIELD_INTERVAL_EXPR]->set_null();
318  fields[ET_FIELD_TRANSIENT_INTERVAL]->set_null();
319  fields[ET_FIELD_STARTS]->set_null();
320  fields[ET_FIELD_ENDS]->set_null();
321 
322  MYSQL_TIME time;
323  my_tz_OFFSET0->gmt_sec_to_TIME(&time, et->execute_at);
324 
325  fields[ET_FIELD_EXECUTE_AT]->set_notnull();
326  fields[ET_FIELD_EXECUTE_AT]->store_time(&time);
327  }
328  else
329  {
330  DBUG_ASSERT(is_update);
331  /*
332  it is normal to be here when the action is update
333  this is an error if the action is create. something is borked
334  */
335  }
336 
337  Item_func_now_local::store_in(fields[ET_FIELD_MODIFIED]);
338 
339  if (et->comment.str)
340  {
341  if (fields[f_num= ET_FIELD_COMMENT]->
342  store(et->comment.str, et->comment.length, scs))
343  goto err_truncate;
344  }
345 
346  fields[ET_FIELD_CHARACTER_SET_CLIENT]->set_notnull();
347  rs|= fields[ET_FIELD_CHARACTER_SET_CLIENT]->store(
348  thd->variables.character_set_client->csname,
349  strlen(thd->variables.character_set_client->csname),
350  system_charset_info);
351 
352  fields[ET_FIELD_COLLATION_CONNECTION]->set_notnull();
353  rs|= fields[ET_FIELD_COLLATION_CONNECTION]->store(
354  thd->variables.collation_connection->name,
355  strlen(thd->variables.collation_connection->name),
356  system_charset_info);
357 
358  {
359  const CHARSET_INFO *db_cl= get_default_db_collation(thd, et->dbname.str);
360 
361  fields[ET_FIELD_DB_COLLATION]->set_notnull();
362  rs|= fields[ET_FIELD_DB_COLLATION]->store(db_cl->name,
363  strlen(db_cl->name),
364  system_charset_info);
365  }
366 
367  if (et->body_changed)
368  {
369  fields[ET_FIELD_BODY_UTF8]->set_notnull();
370  rs|= fields[ET_FIELD_BODY_UTF8]->store(sp->m_body_utf8.str,
371  sp->m_body_utf8.length,
372  system_charset_info);
373  }
374 
375  if (rs)
376  {
377  my_error(ER_EVENT_STORE_FAILED, MYF(0), fields[f_num]->field_name, rs);
378  DBUG_RETURN(TRUE);
379  }
380 
381  DBUG_RETURN(FALSE);
382 
383 err_truncate:
384  my_error(ER_EVENT_DATA_TOO_LONG, MYF(0), fields[f_num]->field_name);
385  DBUG_RETURN(TRUE);
386 }
387 
388 
389 /*
390  Performs an index scan of event_table (mysql.event) and fills schema_table.
391 
392  SYNOPSIS
393  Event_db_repository::index_read_for_db_for_i_s()
394  thd Thread
395  schema_table The I_S.EVENTS table
396  event_table The event table to use for loading (mysql.event)
397  db For which schema to do an index scan.
398 
399  RETURN VALUE
400  0 OK
401  1 Error
402 */
403 
404 bool
405 Event_db_repository::index_read_for_db_for_i_s(THD *thd, TABLE *schema_table,
406  TABLE *event_table,
407  const char *db)
408 {
409  CHARSET_INFO *scs= system_charset_info;
410  KEY *key_info;
411  uint key_len;
412  uchar *key_buf= NULL;
413  LINT_INIT(key_buf);
414 
415  DBUG_ENTER("Event_db_repository::index_read_for_db_for_i_s");
416 
417  DBUG_PRINT("info", ("Using prefix scanning on PK"));
418 
419  int ret= event_table->file->ha_index_init(0, 1);
420  if (ret)
421  {
422  event_table->file->print_error(ret, MYF(0));
423  DBUG_RETURN(true);
424  }
425 
426  key_info= event_table->key_info;
427 
428  if (key_info->user_defined_key_parts == 0 ||
429  key_info->key_part[0].field != event_table->field[ET_FIELD_DB])
430  {
431  /* Corrupted table: no index or index on a wrong column */
432  my_error(ER_CANNOT_LOAD_FROM_TABLE_V2, MYF(0), "mysql", "event");
433  ret= 1;
434  goto end;
435  }
436 
437  event_table->field[ET_FIELD_DB]->store(db, strlen(db), scs);
438  key_len= key_info->key_part[0].store_length;
439 
440  if (!(key_buf= (uchar *)alloc_root(thd->mem_root, key_len)))
441  {
442  /* Don't send error, it would be done by sql_alloc_error_handler() */
443  ret= 1;
444  goto end;
445  }
446 
447  key_copy(key_buf, event_table->record[0], key_info, key_len);
448  if (!(ret= event_table->file->ha_index_read_map(event_table->record[0], key_buf,
449  (key_part_map)1,
450  HA_READ_KEY_EXACT)))
451  {
452  DBUG_PRINT("info",("Found rows. Let's retrieve them. ret=%d", ret));
453  do
454  {
455  ret= copy_event_to_schema_table(thd, schema_table, event_table);
456  if (ret == 0)
457  ret= event_table->file->ha_index_next_same(event_table->record[0],
458  key_buf, key_len);
459  } while (ret == 0);
460  }
461  DBUG_PRINT("info", ("Scan finished. ret=%d", ret));
462 
463  /* ret is guaranteed to be != 0 */
464  if (ret == HA_ERR_END_OF_FILE || ret == HA_ERR_KEY_NOT_FOUND)
465  ret= 0;
466  else
467  event_table->file->print_error(ret, MYF(0));
468 
469 end:
470  event_table->file->ha_index_end();
471 
472  DBUG_RETURN(test(ret));
473 }
474 
475 
476 /*
477  Performs a table scan of event_table (mysql.event) and fills schema_table.
478 
479  SYNOPSIS
480  Events_db_repository::table_scan_all_for_i_s()
481  thd Thread
482  schema_table The I_S.EVENTS in memory table
483  event_table The event table to use for loading.
484 
485  RETURN VALUE
486  FALSE OK
487  TRUE Error
488 */
489 
490 bool
491 Event_db_repository::table_scan_all_for_i_s(THD *thd, TABLE *schema_table,
492  TABLE *event_table)
493 {
494  int ret;
495  READ_RECORD read_record_info;
496  DBUG_ENTER("Event_db_repository::table_scan_all_for_i_s");
497 
498  if (init_read_record(&read_record_info, thd, event_table, NULL, 1, 1, FALSE))
499  DBUG_RETURN(TRUE);
500 
501  /*
502  rr_sequential, in read_record(), returns 137==HA_ERR_END_OF_FILE,
503  but rr_handle_error returns -1 for that reason. Thus, read_record()
504  returns -1 eventually.
505  */
506  do
507  {
508  ret= read_record_info.read_record(&read_record_info);
509  if (ret == 0)
510  ret= copy_event_to_schema_table(thd, schema_table, event_table);
511  } while (ret == 0);
512 
513  DBUG_PRINT("info", ("Scan finished. ret=%d", ret));
514  end_read_record(&read_record_info);
515 
516  /* ret is guaranteed to be != 0 */
517  DBUG_RETURN(ret == -1 ? FALSE : TRUE);
518 }
519 
520 
535 bool
537  const char *db)
538 {
539  TABLE *schema_table= i_s_table->table;
540  Open_tables_backup open_tables_backup;
541  TABLE_LIST event_table;
542  int ret= 0;
543 
544  DBUG_ENTER("Event_db_repository::fill_schema_events");
545  DBUG_PRINT("info",("db=%s", db? db:"(null)"));
546 
547  event_table.init_one_table("mysql", 5, "event", 5, "event", TL_READ);
548 
549  if (open_system_tables_for_read(thd, &event_table, &open_tables_backup))
550  DBUG_RETURN(TRUE);
551 
552  if (!event_table.table->key_info)
553  {
554  close_system_tables(thd, &open_tables_backup);
555  my_error(ER_TABLE_CORRUPT, MYF(0), event_table.table->s->db.str,
556  event_table.table->s->table_name.str);
557  DBUG_RETURN(TRUE);
558  }
559 
560  if (table_intact.check(event_table.table, &event_table_def))
561  {
562  close_system_tables(thd, &open_tables_backup);
563  my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
564  DBUG_RETURN(TRUE);
565  }
566 
567  /*
568  1. SELECT I_S => use table scan. I_S.EVENTS does not guarantee order
569  thus we won't order it. OTOH, SHOW EVENTS will be
570  ordered.
571  2. SHOW EVENTS => PRIMARY KEY with prefix scanning on (db)
572  Reasoning: Events are per schema, therefore a scan over an index
573  will save use from doing a table scan and comparing
574  every single row's `db` with the schema which we show.
575  */
576  if (db)
577  ret= index_read_for_db_for_i_s(thd, schema_table, event_table.table, db);
578  else
579  ret= table_scan_all_for_i_s(thd, schema_table, event_table.table);
580 
581  close_system_tables(thd, &open_tables_backup);
582 
583  DBUG_PRINT("info", ("Return code=%d", ret));
584  DBUG_RETURN(ret);
585 }
586 
587 
610 bool
611 Event_db_repository::open_event_table(THD *thd, enum thr_lock_type lock_type,
612  TABLE **table)
613 {
614  TABLE_LIST tables;
615  DBUG_ENTER("Event_db_repository::open_event_table");
616 
617  tables.init_one_table("mysql", 5, "event", 5, "event", lock_type);
618 
619  if (open_and_lock_tables(thd, &tables, FALSE, MYSQL_LOCK_IGNORE_TIMEOUT))
620  DBUG_RETURN(TRUE);
621 
622  *table= tables.table;
623  tables.table->use_all_columns();
624 
625  if (table_intact.check(*table, &event_table_def))
626  {
627  close_thread_tables(thd);
628  my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
629  DBUG_RETURN(TRUE);
630  }
631 
632  DBUG_RETURN(FALSE);
633 }
634 
635 
657 bool
659  bool create_if_not,
660  bool *event_already_exists)
661 {
662  int ret= 1;
663  TABLE *table= NULL;
664  sp_head *sp= thd->lex->sphead;
665  sql_mode_t saved_mode= thd->variables.sql_mode;
666  /*
667  Take a savepoint to release only the lock on mysql.event
668  table at the end but keep the global read lock and
669  possible other locks taken by the caller.
670  */
671  MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint();
672 
673  DBUG_ENTER("Event_db_repository::create_event");
674 
675  DBUG_PRINT("info", ("open mysql.event for update"));
676  DBUG_ASSERT(sp);
677 
678  /* Reset sql_mode during data dictionary operations. */
679  thd->variables.sql_mode= 0;
680 
681  if (open_event_table(thd, TL_WRITE, &table))
682  goto end;
683 
684  DBUG_PRINT("info", ("name: %.*s", (int) parse_data->name.length,
685  parse_data->name.str));
686 
687  DBUG_PRINT("info", ("check existance of an event with the same name"));
688  if (!find_named_event(parse_data->dbname, parse_data->name, table))
689  {
690  if (create_if_not)
691  {
692  *event_already_exists= true;
693  push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
694  ER_EVENT_ALREADY_EXISTS, ER(ER_EVENT_ALREADY_EXISTS),
695  parse_data->name.str);
696  ret= 0;
697  }
698  else
699  my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), parse_data->name.str);
700 
701  goto end;
702  } else
703  *event_already_exists= false;
704 
705  DBUG_PRINT("info", ("non-existent, go forward"));
706 
707  restore_record(table, s->default_values); // Get default values for fields
708 
709  if (system_charset_info->cset->
710  numchars(system_charset_info, parse_data->dbname.str,
711  parse_data->dbname.str + parse_data->dbname.length) >
712  table->field[ET_FIELD_DB]->char_length())
713  {
714  my_error(ER_TOO_LONG_IDENT, MYF(0), parse_data->dbname.str);
715  goto end;
716  }
717 
718  if (system_charset_info->cset->
719  numchars(system_charset_info, parse_data->name.str,
720  parse_data->name.str + parse_data->name.length) >
721  table->field[ET_FIELD_NAME]->char_length())
722  {
723  my_error(ER_TOO_LONG_IDENT, MYF(0), parse_data->name.str);
724  goto end;
725  }
726 
727  if (sp->m_body.length > table->field[ET_FIELD_BODY]->field_length)
728  {
729  my_error(ER_TOO_LONG_BODY, MYF(0), parse_data->name.str);
730  goto end;
731  }
732 
733  Item_func_now_local::store_in(table->field[ET_FIELD_CREATED]);
734 
735  /*
736  mysql_event_fill_row() calls my_error() in case of error so no need to
737  handle it here
738  */
739  if (mysql_event_fill_row(thd, table, parse_data, sp, saved_mode, FALSE))
740  goto end;
741 
742  if ((ret= table->file->ha_write_row(table->record[0])))
743  {
744  table->file->print_error(ret, MYF(0));
745  goto end;
746  }
747  ret= 0;
748 
749 end:
750  close_thread_tables(thd);
751  thd->mdl_context.rollback_to_savepoint(mdl_savepoint);
752 
753  thd->variables.sql_mode= saved_mode;
754  DBUG_RETURN(test(ret));
755 }
756 
757 
776 bool
778  LEX_STRING *new_dbname,
779  LEX_STRING *new_name)
780 {
781  CHARSET_INFO *scs= system_charset_info;
782  TABLE *table= NULL;
783  sp_head *sp= thd->lex->sphead;
784  sql_mode_t saved_mode= thd->variables.sql_mode;
785  /*
786  Take a savepoint to release only the lock on mysql.event
787  table at the end but keep the global read lock and
788  possible other locks taken by the caller.
789  */
790  MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint();
791  int ret= 1;
792 
793  DBUG_ENTER("Event_db_repository::update_event");
794 
795  /* None or both must be set */
796  DBUG_ASSERT((new_dbname && new_name) || new_dbname == new_name);
797 
798  /* Reset sql_mode during data dictionary operations. */
799  thd->variables.sql_mode= 0;
800 
801  if (open_event_table(thd, TL_WRITE, &table))
802  goto end;
803 
804  DBUG_PRINT("info", ("dbname: %s", parse_data->dbname.str));
805  DBUG_PRINT("info", ("name: %s", parse_data->name.str));
806  DBUG_PRINT("info", ("user: %s", parse_data->definer.str));
807 
808  /* first look whether we overwrite */
809  if (new_name)
810  {
811  DBUG_PRINT("info", ("rename to: %s@%s", new_dbname->str, new_name->str));
812  if (!find_named_event(*new_dbname, *new_name, table))
813  {
814  my_error(ER_EVENT_ALREADY_EXISTS, MYF(0), new_name->str);
815  goto end;
816  }
817  }
818  /*
819  ...and then if there is such an event. Don't exchange the blocks
820  because you will get error 120 from table handler because new_name will
821  overwrite the key and SE will tell us that it cannot find the already found
822  row (copied into record[1] later
823  */
824  if (find_named_event(parse_data->dbname, parse_data->name, table))
825  {
826  my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), parse_data->name.str);
827  goto end;
828  }
829 
830  store_record(table,record[1]);
831 
832  /*
833  We check whether ALTER EVENT was given dates that are in the past.
834  However to know how to react, we need the ON COMPLETION type. The
835  check is deferred to this point because by now we have the previous
836  setting (from the event-table) to fall back on if nothing was specified
837  in the ALTER EVENT-statement.
838  */
839 
840  if (parse_data->check_dates(thd,
841  (int) table->field[ET_FIELD_ON_COMPLETION]->val_int()))
842  goto end;
843 
844  /*
845  mysql_event_fill_row() calls my_error() in case of error so no need to
846  handle it here
847  */
848  if (mysql_event_fill_row(thd, table, parse_data, sp, saved_mode, TRUE))
849  goto end;
850 
851  if (new_dbname)
852  {
853  table->field[ET_FIELD_DB]->store(new_dbname->str, new_dbname->length, scs);
854  table->field[ET_FIELD_NAME]->store(new_name->str, new_name->length, scs);
855  }
856 
857  if ((ret= table->file->ha_update_row(table->record[1], table->record[0])))
858  {
859  table->file->print_error(ret, MYF(0));
860  goto end;
861  }
862  ret= 0;
863 
864 end:
865  close_thread_tables(thd);
866  thd->mdl_context.rollback_to_savepoint(mdl_savepoint);
867 
868  thd->variables.sql_mode= saved_mode;
869  DBUG_RETURN(test(ret));
870 }
871 
872 
887 bool
889  bool drop_if_exists)
890 {
891  TABLE *table= NULL;
892  /*
893  Take a savepoint to release only the lock on mysql.event
894  table at the end but keep the global read lock and
895  possible other locks taken by the caller.
896  */
897  MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint();
898  int ret= 1;
899 
900  DBUG_ENTER("Event_db_repository::drop_event");
901  DBUG_PRINT("enter", ("%s@%s", db.str, name.str));
902 
903  if (open_event_table(thd, TL_WRITE, &table))
904  goto end;
905 
906  if (!find_named_event(db, name, table))
907  {
908  if ((ret= table->file->ha_delete_row(table->record[0])))
909  table->file->print_error(ret, MYF(0));
910  goto end;
911  }
912 
913  /* Event not found */
914  if (!drop_if_exists)
915  {
916  my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name.str);
917  goto end;
918  }
919 
920  push_warning_printf(thd, Sql_condition::WARN_LEVEL_NOTE,
921  ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST),
922  "Event", name.str);
923  ret= 0;
924 
925 end:
926  close_thread_tables(thd);
927  thd->mdl_context.rollback_to_savepoint(mdl_savepoint);
928 
929  DBUG_RETURN(test(ret));
930 }
931 
932 
948 bool
950  TABLE *table)
951 {
952  uchar key[MAX_KEY_LENGTH];
953  DBUG_ENTER("Event_db_repository::find_named_event");
954  DBUG_PRINT("enter", ("name: %.*s", (int) name.length, name.str));
955 
956  /*
957  Create key to find row. We have to use field->store() to be able to
958  handle VARCHAR and CHAR fields.
959  Assumption here is that the two first fields in the table are
960  'db' and 'name' and the first key is the primary key over the
961  same fields.
962  */
963  if (db.length > table->field[ET_FIELD_DB]->field_length ||
964  name.length > table->field[ET_FIELD_NAME]->field_length)
965  DBUG_RETURN(TRUE);
966 
967  if (!table->key_info)
968  {
969  my_error(ER_TABLE_CORRUPT, MYF(0), table->s->db.str,
970  table->s->table_name.str);
971  DBUG_RETURN(TRUE);
972  }
973 
974  table->field[ET_FIELD_DB]->store(db.str, db.length, &my_charset_bin);
975  table->field[ET_FIELD_NAME]->store(name.str, name.length, &my_charset_bin);
976 
977  key_copy(key, table->record[0], table->key_info, table->key_info->key_length);
978 
979  if (table->file->ha_index_read_idx_map(table->record[0], 0, key, HA_WHOLE_KEY,
980  HA_READ_KEY_EXACT))
981  {
982  DBUG_PRINT("info", ("Row not found"));
983  DBUG_RETURN(TRUE);
984  }
985 
986  DBUG_PRINT("info", ("Row found!"));
987  DBUG_RETURN(FALSE);
988 }
989 
990 
991 /*
992  Drops all events in the selected database, from mysql.event.
993 
994  SYNOPSIS
995  Event_db_repository::drop_schema_events()
996  thd Thread
997  schema The database to clean from events
998 */
999 
1000 void
1001 Event_db_repository::drop_schema_events(THD *thd, LEX_STRING schema)
1002 {
1003  int ret= 0;
1004  TABLE *table= NULL;
1005  READ_RECORD read_record_info;
1006  enum enum_events_table_field field= ET_FIELD_DB;
1007  MDL_savepoint mdl_savepoint= thd->mdl_context.mdl_savepoint();
1008  DBUG_ENTER("Event_db_repository::drop_schema_events");
1009  DBUG_PRINT("enter", ("field=%d schema=%s", field, schema.str));
1010 
1011  if (open_event_table(thd, TL_WRITE, &table))
1012  DBUG_VOID_RETURN;
1013 
1014  /* only enabled events are in memory, so we go now and delete the rest */
1015  if (init_read_record(&read_record_info, thd, table, NULL, 1, 1, FALSE))
1016  DBUG_VOID_RETURN;
1017  while (!ret && !(read_record_info.read_record(&read_record_info)) )
1018  {
1019  char *et_field= get_field(thd->mem_root, table->field[field]);
1020 
1021  /* et_field may be NULL if the table is corrupted or out of memory */
1022  if (et_field)
1023  {
1024  LEX_STRING et_field_lex= { et_field, strlen(et_field) };
1025  DBUG_PRINT("info", ("Current event %s name=%s", et_field,
1026  get_field(thd->mem_root,
1027  table->field[ET_FIELD_NAME])));
1028 
1029  if (!sortcmp_lex_string(et_field_lex, schema, system_charset_info))
1030  {
1031  DBUG_PRINT("info", ("Dropping"));
1032  if ((ret= table->file->ha_delete_row(table->record[0])))
1033  table->file->print_error(ret, MYF(0));
1034  }
1035  }
1036  }
1037  end_read_record(&read_record_info);
1038  close_thread_tables(thd);
1039  /*
1040  Make sure to only release the MDL lock on mysql.event, not other
1041  metadata locks DROP DATABASE might have acquired.
1042  */
1043  thd->mdl_context.rollback_to_savepoint(mdl_savepoint);
1044 
1045  DBUG_VOID_RETURN;
1046 }
1047 
1048 
1059 bool
1061  LEX_STRING name, Event_basic *etn)
1062 {
1063  bool ret;
1064  sql_mode_t saved_mode= thd->variables.sql_mode;
1065  Open_tables_backup open_tables_backup;
1066  TABLE_LIST event_table;
1067 
1068  DBUG_ENTER("Event_db_repository::load_named_event");
1069  DBUG_PRINT("enter",("thd: 0x%lx name: %*s", (long) thd,
1070  (int) name.length, name.str));
1071 
1072  event_table.init_one_table("mysql", 5, "event", 5, "event", TL_READ);
1073 
1074  /* Reset sql_mode during data dictionary operations. */
1075  thd->variables.sql_mode= 0;
1076 
1077  /*
1078  We don't use open_event_table() here to make sure that SHOW
1079  CREATE EVENT works properly in transactional context, and
1080  does not release transactional metadata locks when the
1081  event table is closed.
1082  */
1083  if (!(ret= open_system_tables_for_read(thd, &event_table, &open_tables_backup)))
1084  {
1085  if (table_intact.check(event_table.table, &event_table_def))
1086  {
1087  close_system_tables(thd, &open_tables_backup);
1088  my_error(ER_EVENT_OPEN_TABLE_FAILED, MYF(0));
1089  DBUG_RETURN(TRUE);
1090  }
1091 
1092  if ((ret= find_named_event(dbname, name, event_table.table)))
1093  my_error(ER_EVENT_DOES_NOT_EXIST, MYF(0), name.str);
1094  else if ((ret= etn->load_from_row(thd, event_table.table)))
1095  my_error(ER_CANNOT_LOAD_FROM_TABLE_V2, MYF(0), "mysql", "event");
1096 
1097  close_system_tables(thd, &open_tables_backup);
1098  }
1099 
1100  thd->variables.sql_mode= saved_mode;
1101  DBUG_RETURN(ret);
1102 }
1103 
1104 
1112 bool
1115  LEX_STRING event_db_name,
1116  LEX_STRING event_name,
1117  my_time_t last_executed,
1118  ulonglong status)
1119 {
1120  TABLE *table= NULL;
1121  Field **fields;
1122  int ret= 1;
1123  bool save_binlog_row_based;
1124  MYSQL_TIME time;
1125 
1126  DBUG_ENTER("Event_db_repository::update_timing_fields_for_event");
1127 
1128  /*
1129  Turn off row binlogging of event timing updates. These are not used
1130  for RBR of events replicated to the slave.
1131  */
1132  if ((save_binlog_row_based= thd->is_current_stmt_binlog_format_row()))
1133  thd->clear_current_stmt_binlog_format_row();
1134 
1135  DBUG_ASSERT(thd->security_ctx->master_access & SUPER_ACL);
1136 
1137  if (open_event_table(thd, TL_WRITE, &table))
1138  goto end;
1139 
1140  fields= table->field;
1141 
1142  if (find_named_event(event_db_name, event_name, table))
1143  goto end;
1144 
1145  store_record(table, record[1]);
1146 
1147  my_tz_OFFSET0->gmt_sec_to_TIME(&time, last_executed);
1148  fields[ET_FIELD_LAST_EXECUTED]->set_notnull();
1149  fields[ET_FIELD_LAST_EXECUTED]->store_time(&time);
1150 
1151  fields[ET_FIELD_STATUS]->set_notnull();
1152  fields[ET_FIELD_STATUS]->store(status, TRUE);
1153 
1154  if ((ret= table->file->ha_update_row(table->record[1], table->record[0])))
1155  {
1156  table->file->print_error(ret, MYF(0));
1157  goto end;
1158  }
1159 
1160  ret= 0;
1161 
1162 end:
1163  if (table)
1164  close_mysql_tables(thd);
1165 
1166  /* Restore the state of binlog format */
1167  DBUG_ASSERT(!thd->is_current_stmt_binlog_format_row());
1168  if (save_binlog_row_based)
1169  thd->set_current_stmt_binlog_format_row();
1170 
1171  DBUG_RETURN(test(ret));
1172 }
1173 
1174 
1189 bool
1191 {
1192  TABLE_LIST tables;
1193  int ret= FALSE;
1194  const unsigned int event_priv_column_position= 29;
1195 
1196  DBUG_ENTER("Event_db_repository::check_system_tables");
1197  DBUG_PRINT("enter", ("thd: 0x%lx", (long) thd));
1198 
1199  /* Check mysql.db */
1200  tables.init_one_table("mysql", 5, "db", 2, "db", TL_READ);
1201 
1202  if (open_and_lock_tables(thd, &tables, FALSE, MYSQL_LOCK_IGNORE_TIMEOUT))
1203  {
1204  ret= 1;
1205  sql_print_error("Cannot open mysql.db");
1206  }
1207  else
1208  {
1209  if (table_intact.check(tables.table, &mysql_db_table_def))
1210  ret= 1;
1211  close_acl_tables(thd);
1212  }
1213  /* Check mysql.user */
1214  tables.init_one_table("mysql", 5, "user", 4, "user", TL_READ);
1215 
1216  if (open_and_lock_tables(thd, &tables, FALSE, MYSQL_LOCK_IGNORE_TIMEOUT))
1217  {
1218  ret= 1;
1219  sql_print_error("Cannot open mysql.user");
1220  }
1221  else
1222  {
1223  if (tables.table->s->fields < event_priv_column_position ||
1224  strncmp(tables.table->field[event_priv_column_position]->field_name,
1225  STRING_WITH_LEN("Event_priv")))
1226  {
1227  sql_print_error("mysql.user has no `Event_priv` column at position %d",
1228  event_priv_column_position);
1229  ret= 1;
1230  }
1231  close_acl_tables(thd);
1232  }
1233  /* Check mysql.event */
1234  tables.init_one_table("mysql", 5, "event", 5, "event", TL_READ);
1235 
1236  if (open_and_lock_tables(thd, &tables, FALSE, MYSQL_LOCK_IGNORE_TIMEOUT))
1237  {
1238  ret= 1;
1239  sql_print_error("Cannot open mysql.event");
1240  }
1241  else
1242  {
1243  if (table_intact.check(tables.table, &event_table_def))
1244  ret= 1;
1245  close_mysql_tables(thd);
1246  }
1247 
1248  DBUG_RETURN(test(ret));
1249 }
1250