MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
event_parse_data.cc
1 /*
2  Copyright (c) 2008, 2011, 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 Foundation,
15  51 Franklin Street, Suite 500, Boston, MA 02110-1335 USA */
16 
17 #include "sql_priv.h"
18 #include "unireg.h"
19 #include "sp_head.h"
20 #include "event_parse_data.h"
21 #include "sql_time.h" // TIME_to_timestamp
22 
23 /*
24  Returns a new instance
25 
26  SYNOPSIS
27  Event_parse_data::new_instance()
28 
29  RETURN VALUE
30  Address or NULL in case of error
31 
32  NOTE
33  Created on THD's mem_root
34 */
35 
37 Event_parse_data::new_instance(THD *thd)
38 {
39  return new (thd->mem_root) Event_parse_data;
40 }
41 
42 
43 /*
44  Constructor
45 
46  SYNOPSIS
47  Event_parse_data::Event_parse_data()
48 */
49 
50 Event_parse_data::Event_parse_data()
51  :on_completion(Event_parse_data::ON_COMPLETION_DEFAULT),
52  status(Event_parse_data::ENABLED), status_changed(false),
53  do_not_create(FALSE), body_changed(FALSE),
54  item_starts(NULL), item_ends(NULL), item_execute_at(NULL),
55  starts_null(TRUE), ends_null(TRUE), execute_at_null(TRUE),
56  item_expression(NULL), expression(0)
57 {
58  DBUG_ENTER("Event_parse_data::Event_parse_data");
59 
60  /* Actually in the parser STARTS is always set */
61  starts= ends= execute_at= 0;
62 
63  comment.str= NULL;
64  comment.length= 0;
65 
66  DBUG_VOID_RETURN;
67 }
68 
69 
70 /*
71  Set a name of the event
72 
73  SYNOPSIS
74  Event_parse_data::init_name()
75  thd THD
76  spn the name extracted in the parser
77 */
78 
79 void
80 Event_parse_data::init_name(THD *thd, sp_name *spn)
81 {
82  DBUG_ENTER("Event_parse_data::init_name");
83 
84  /* We have to copy strings to get them into the right memroot */
85  dbname.length= spn->m_db.length;
86  dbname.str= thd->strmake(spn->m_db.str, spn->m_db.length);
87  name.length= spn->m_name.length;
88  name.str= thd->strmake(spn->m_name.str, spn->m_name.length);
89 
90  if (spn->m_qname.length == 0)
91  spn->init_qname(thd);
92 
93  DBUG_VOID_RETURN;
94 }
95 
96 
97 /*
98  This function is called on CREATE EVENT or ALTER EVENT. When either
99  ENDS or AT is in the past, we are trying to create an event that
100  will never be executed. If it has ON COMPLETION NOT PRESERVE
101  (default), then it would normally be dropped already, so on CREATE
102  EVENT we give a warning, and do not create anyting. On ALTER EVENT
103  we give a error, and do not change the event.
104 
105  If the event has ON COMPLETION PRESERVE, then we see if the event is
106  created or altered to the ENABLED (default) state. If so, then we
107  give a warning, and change the state to DISABLED.
108 
109  Otherwise it is a valid event in ON COMPLETION PRESERVE DISABLE
110  state.
111 */
112 
113 void
114 Event_parse_data::check_if_in_the_past(THD *thd, my_time_t ltime_utc)
115 {
116  if (ltime_utc >= (my_time_t) thd->query_start())
117  return;
118 
119  /*
120  We'll come back later when we have the real on_completion value
121  */
122  if (on_completion == Event_parse_data::ON_COMPLETION_DEFAULT)
123  return;
124 
125  if (on_completion == Event_parse_data::ON_COMPLETION_DROP)
126  {
127  switch (thd->lex->sql_command) {
128  case SQLCOM_CREATE_EVENT:
129  push_warning(thd, Sql_condition::WARN_LEVEL_NOTE,
130  ER_EVENT_CANNOT_CREATE_IN_THE_PAST,
131  ER(ER_EVENT_CANNOT_CREATE_IN_THE_PAST));
132  break;
133  case SQLCOM_ALTER_EVENT:
134  my_error(ER_EVENT_CANNOT_ALTER_IN_THE_PAST, MYF(0));
135  break;
136  default:
137  DBUG_ASSERT(0);
138  }
139 
140  do_not_create= TRUE;
141  }
142  else if (status == Event_parse_data::ENABLED)
143  {
144  status= Event_parse_data::DISABLED;
145  status_changed= true;
146  push_warning(thd, Sql_condition::WARN_LEVEL_NOTE,
147  ER_EVENT_EXEC_TIME_IN_THE_PAST,
148  ER(ER_EVENT_EXEC_TIME_IN_THE_PAST));
149  }
150 }
151 
152 
153 /*
154  Check time/dates in ALTER EVENT
155 
156  We check whether ALTER EVENT was given dates that are in the past.
157  However to know how to react, we need the ON COMPLETION type. Hence,
158  the check is deferred until we have the previous ON COMPLETION type
159  from the event-db to fall back on if nothing was specified in the
160  ALTER EVENT-statement.
161 
162  SYNOPSIS
163  Event_parse_data::check_dates()
164  thd Thread
165  on_completion ON COMPLETION value currently in event-db.
166  Will be overridden by value in ALTER EVENT if given.
167 
168  RETURN VALUE
169  TRUE an error occurred, do not ALTER
170  FALSE OK
171 */
172 
173 bool
174 Event_parse_data::check_dates(THD *thd, int previous_on_completion)
175 {
176  if (on_completion == Event_parse_data::ON_COMPLETION_DEFAULT)
177  {
178  on_completion= previous_on_completion;
179  if (!ends_null)
180  check_if_in_the_past(thd, ends);
181  if (!execute_at_null)
182  check_if_in_the_past(thd, execute_at);
183  }
184  return do_not_create;
185 }
186 
187 
188 
189 /*
190  Sets time for execution for one-time event.
191 
192  SYNOPSIS
193  Event_parse_data::init_execute_at()
194  thd Thread
195 
196  RETURN VALUE
197  0 OK
198  ER_WRONG_VALUE Wrong value for execute at (reported)
199 */
200 
201 int
202 Event_parse_data::init_execute_at(THD *thd)
203 {
204  my_bool not_used;
205  MYSQL_TIME ltime;
206  my_time_t ltime_utc;
207 
208  DBUG_ENTER("Event_parse_data::init_execute_at");
209 
210  if (!item_execute_at)
211  DBUG_RETURN(0);
212 
213  if (item_execute_at->fix_fields(thd, &item_execute_at))
214  goto wrong_value;
215 
216  /* no starts and/or ends in case of execute_at */
217  DBUG_PRINT("info", ("starts_null && ends_null should be 1 is %d",
218  (starts_null && ends_null)));
219  DBUG_ASSERT(starts_null && ends_null);
220 
221  if ((not_used= item_execute_at->get_date(&ltime, TIME_NO_ZERO_DATE)))
222  goto wrong_value;
223 
224  ltime_utc= TIME_to_timestamp(thd,&ltime,&not_used);
225  if (!ltime_utc)
226  {
227  DBUG_PRINT("error", ("Execute AT after year 2037"));
228  goto wrong_value;
229  }
230 
231  check_if_in_the_past(thd, ltime_utc);
232 
233  execute_at_null= FALSE;
234  execute_at= ltime_utc;
235  DBUG_RETURN(0);
236 
237 wrong_value:
238  report_bad_value("AT", item_execute_at);
239  DBUG_RETURN(ER_WRONG_VALUE);
240 }
241 
242 
243 /*
244  Sets time for execution of multi-time event.s
245 
246  SYNOPSIS
247  Event_parse_data::init_interval()
248  thd Thread
249 
250  RETURN VALUE
251  0 OK
252  EVEX_BAD_PARAMS Interval is not positive or MICROSECOND (reported)
253  ER_WRONG_VALUE Wrong value for interval (reported)
254 */
255 
256 int
257 Event_parse_data::init_interval(THD *thd)
258 {
259  String value;
260  INTERVAL interval_tmp;
261 
262  DBUG_ENTER("Event_parse_data::init_interval");
263  if (!item_expression)
264  DBUG_RETURN(0);
265 
266  switch (interval) {
267  case INTERVAL_MINUTE_MICROSECOND:
268  case INTERVAL_HOUR_MICROSECOND:
269  case INTERVAL_DAY_MICROSECOND:
270  case INTERVAL_SECOND_MICROSECOND:
271  case INTERVAL_MICROSECOND:
272  my_error(ER_NOT_SUPPORTED_YET, MYF(0), "MICROSECOND");
273  DBUG_RETURN(EVEX_BAD_PARAMS);
274  default:
275  break;
276  }
277 
278  if (item_expression->fix_fields(thd, &item_expression))
279  goto wrong_value;
280 
281  value.alloc(MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN);
282  if (get_interval_value(item_expression, interval, &value, &interval_tmp))
283  goto wrong_value;
284 
285  expression= 0;
286 
287  switch (interval) {
288  case INTERVAL_YEAR:
289  expression= interval_tmp.year;
290  break;
291  case INTERVAL_QUARTER:
292  case INTERVAL_MONTH:
293  expression= interval_tmp.month;
294  break;
295  case INTERVAL_WEEK:
296  case INTERVAL_DAY:
297  expression= interval_tmp.day;
298  break;
299  case INTERVAL_HOUR:
300  expression= interval_tmp.hour;
301  break;
302  case INTERVAL_MINUTE:
303  expression= interval_tmp.minute;
304  break;
305  case INTERVAL_SECOND:
306  expression= interval_tmp.second;
307  break;
308  case INTERVAL_YEAR_MONTH: // Allow YEAR-MONTH YYYYYMM
309  expression= interval_tmp.year* 12 + interval_tmp.month;
310  break;
311  case INTERVAL_DAY_HOUR:
312  expression= interval_tmp.day* 24 + interval_tmp.hour;
313  break;
314  case INTERVAL_DAY_MINUTE:
315  expression= (interval_tmp.day* 24 + interval_tmp.hour) * 60 +
316  interval_tmp.minute;
317  break;
318  case INTERVAL_HOUR_SECOND: /* day is anyway 0 */
319  case INTERVAL_DAY_SECOND:
320  /* DAY_SECOND having problems because of leap seconds? */
321  expression= ((interval_tmp.day* 24 + interval_tmp.hour) * 60 +
322  interval_tmp.minute)*60
323  + interval_tmp.second;
324  break;
325  case INTERVAL_HOUR_MINUTE:
326  expression= interval_tmp.hour * 60 + interval_tmp.minute;
327  break;
328  case INTERVAL_MINUTE_SECOND:
329  expression= interval_tmp.minute * 60 + interval_tmp.second;
330  break;
331  case INTERVAL_LAST:
332  DBUG_ASSERT(0);
333  default:
334  ;/* these are the microsec stuff */
335  }
336  if (interval_tmp.neg || expression == 0 ||
337  expression > EVEX_MAX_INTERVAL_VALUE)
338  {
339  my_error(ER_EVENT_INTERVAL_NOT_POSITIVE_OR_TOO_BIG, MYF(0));
340  DBUG_RETURN(EVEX_BAD_PARAMS);
341  }
342 
343  DBUG_RETURN(0);
344 
345 wrong_value:
346  report_bad_value("INTERVAL", item_expression);
347  DBUG_RETURN(ER_WRONG_VALUE);
348 }
349 
350 
351 /*
352  Sets STARTS.
353 
354  SYNOPSIS
355  Event_parse_data::init_starts()
356  expr how much?
357 
358  NOTES
359  Note that activation time is not execution time.
360  EVERY 5 MINUTE STARTS "2004-12-12 10:00:00" means that
361  the event will be executed every 5 minutes but this will
362  start at the date shown above. Expressions are possible :
363  DATE_ADD(NOW(), INTERVAL 1 DAY) -- start tommorow at
364  same time.
365 
366  RETURN VALUE
367  0 OK
368  ER_WRONG_VALUE Starts before now
369 */
370 
371 int
372 Event_parse_data::init_starts(THD *thd)
373 {
374  my_bool not_used;
375  MYSQL_TIME ltime;
376  my_time_t ltime_utc;
377 
378  DBUG_ENTER("Event_parse_data::init_starts");
379  if (!item_starts)
380  DBUG_RETURN(0);
381 
382  if (item_starts->fix_fields(thd, &item_starts))
383  goto wrong_value;
384 
385  if ((not_used= item_starts->get_date(&ltime, TIME_NO_ZERO_DATE)))
386  goto wrong_value;
387 
388  ltime_utc= TIME_to_timestamp(thd, &ltime, &not_used);
389  if (!ltime_utc)
390  goto wrong_value;
391 
392  DBUG_PRINT("info",("now: %ld starts: %ld",
393  (long) thd->query_start(), (long) ltime_utc));
394 
395  starts_null= FALSE;
396  starts= ltime_utc;
397  DBUG_RETURN(0);
398 
399 wrong_value:
400  report_bad_value("STARTS", item_starts);
401  DBUG_RETURN(ER_WRONG_VALUE);
402 }
403 
404 
405 /*
406  Sets ENDS (deactivation time).
407 
408  SYNOPSIS
409  Event_parse_data::init_ends()
410  thd THD
411 
412  NOTES
413  Note that activation time is not execution time.
414  EVERY 5 MINUTE ENDS "2004-12-12 10:00:00" means that
415  the event will be executed every 5 minutes but this will
416  end at the date shown above. Expressions are possible :
417  DATE_ADD(NOW(), INTERVAL 1 DAY) -- end tommorow at
418  same time.
419 
420  RETURN VALUE
421  0 OK
422  EVEX_BAD_PARAMS Error (reported)
423 */
424 
425 int
426 Event_parse_data::init_ends(THD *thd)
427 {
428  my_bool not_used;
429  MYSQL_TIME ltime;
430  my_time_t ltime_utc;
431 
432  DBUG_ENTER("Event_parse_data::init_ends");
433  if (!item_ends)
434  DBUG_RETURN(0);
435 
436  if (item_ends->fix_fields(thd, &item_ends))
437  goto error_bad_params;
438 
439  DBUG_PRINT("info", ("convert to TIME"));
440  if ((not_used= item_ends->get_date(&ltime, TIME_NO_ZERO_DATE)))
441  goto error_bad_params;
442 
443  ltime_utc= TIME_to_timestamp(thd, &ltime, &not_used);
444  if (!ltime_utc)
445  goto error_bad_params;
446 
447  /* Check whether ends is after starts */
448  DBUG_PRINT("info", ("ENDS after STARTS?"));
449  if (!starts_null && starts >= ltime_utc)
450  goto error_bad_params;
451 
452  check_if_in_the_past(thd, ltime_utc);
453 
454  ends_null= FALSE;
455  ends= ltime_utc;
456  DBUG_RETURN(0);
457 
458 error_bad_params:
459  my_error(ER_EVENT_ENDS_BEFORE_STARTS, MYF(0));
460  DBUG_RETURN(EVEX_BAD_PARAMS);
461 }
462 
463 
464 /*
465  Prints an error message about invalid value. Internally used
466  during input data verification
467 
468  SYNOPSIS
469  Event_parse_data::report_bad_value()
470  item_name The name of the parameter
471  bad_item The parameter
472 */
473 
474 void
475 Event_parse_data::report_bad_value(const char *item_name, Item *bad_item)
476 {
477  char buff[120];
478  String str(buff,(uint32) sizeof(buff), system_charset_info);
479  String *str2= bad_item->fixed? bad_item->val_str(&str):NULL;
480  my_error(ER_WRONG_VALUE, MYF(0), item_name, str2? str2->c_ptr_safe():"NULL");
481 }
482 
483 
484 /*
485  Checks for validity the data gathered during the parsing phase.
486 
487  SYNOPSIS
488  Event_parse_data::check_parse_data()
489  thd Thread
490 
491  RETURN VALUE
492  FALSE OK
493  TRUE Error (reported)
494 */
495 
496 bool
497 Event_parse_data::check_parse_data(THD *thd)
498 {
499  bool ret;
500  DBUG_ENTER("Event_parse_data::check_parse_data");
501  DBUG_PRINT("info", ("execute_at: 0x%lx expr=0x%lx starts=0x%lx ends=0x%lx",
502  (long) item_execute_at, (long) item_expression,
503  (long) item_starts, (long) item_ends));
504 
505  init_name(thd, identifier);
506 
507  init_definer(thd);
508 
509  ret= init_execute_at(thd) || init_interval(thd) || init_starts(thd) ||
510  init_ends(thd);
511  check_originator_id(thd);
512  DBUG_RETURN(ret);
513 }
514 
515 
516 /*
517  Inits definer (definer_user and definer_host) during parsing.
518 
519  SYNOPSIS
520  Event_parse_data::init_definer()
521  thd Thread
522 */
523 
524 void
525 Event_parse_data::init_definer(THD *thd)
526 {
527  DBUG_ENTER("Event_parse_data::init_definer");
528 
529  DBUG_ASSERT(thd->lex->definer);
530 
531  const char *definer_user= thd->lex->definer->user.str;
532  const char *definer_host= thd->lex->definer->host.str;
533  size_t definer_user_len= thd->lex->definer->user.length;
534  size_t definer_host_len= thd->lex->definer->host.length;
535 
536  DBUG_PRINT("info",("init definer_user thd->mem_root: 0x%lx "
537  "definer_user: 0x%lx", (long) thd->mem_root,
538  (long) definer_user));
539 
540  /* + 1 for @ */
541  DBUG_PRINT("info",("init definer as whole"));
542  definer.length= definer_user_len + definer_host_len + 1;
543  definer.str= (char*) thd->alloc(definer.length + 1);
544 
545  DBUG_PRINT("info",("copy the user"));
546  memcpy(definer.str, definer_user, definer_user_len);
547  definer.str[definer_user_len]= '@';
548 
549  DBUG_PRINT("info",("copy the host"));
550  memcpy(definer.str + definer_user_len + 1, definer_host, definer_host_len);
551  definer.str[definer.length]= '\0';
552  DBUG_PRINT("info",("definer [%s] initted", definer.str));
553 
554  DBUG_VOID_RETURN;
555 }
556 
557 
566 void Event_parse_data::check_originator_id(THD *thd)
567 {
568  /* Disable replicated events on slave. */
569  if ((thd->system_thread == SYSTEM_THREAD_SLAVE_SQL) ||
570  (thd->system_thread == SYSTEM_THREAD_SLAVE_WORKER) ||
571  (thd->system_thread == SYSTEM_THREAD_SLAVE_IO))
572  {
573  DBUG_PRINT("info", ("Invoked object status set to SLAVESIDE_DISABLED."));
574  if ((status == Event_parse_data::ENABLED) ||
575  (status == Event_parse_data::DISABLED))
576  {
577  status= Event_parse_data::SLAVESIDE_DISABLED;
578  status_changed= true;
579  }
580  originator = thd->server_id;
581  }
582  else
583  originator = server_id;
584 }