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