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