#include <event_timed.h>
Collaboration diagram for Event_timed:

Definition at line 45 of file event_timed.h.
Definition at line 66 of file event_timed.h.
00067 { 00068 ON_COMPLETION_DROP = 1, 00069 ON_COMPLETION_PRESERVE 00070 };
| Event_timed::Event_timed | ( | const Event_timed & | ) | [private] |
| Event_timed::Event_timed | ( | ) |
Definition at line 32 of file event_timed.cc.
References init(), MY_MUTEX_INIT_FAST, NULL, and pthread_mutex_init.
00032 :in_spawned_thread(0),locked_by_thread_id(0), 00033 running(0), thread_id(0), status_changed(false), 00034 last_executed_changed(false), expression(0), 00035 created(0), modified(0), 00036 on_completion(Event_timed::ON_COMPLETION_DROP), 00037 status(Event_timed::ENABLED), sphead(0), 00038 sql_mode(0), body_begin(0), dropped(false), 00039 free_sphead_on_delete(true), flags(0) 00040 00041 { 00042 pthread_mutex_init(&this->LOCK_running, MY_MUTEX_INIT_FAST); 00043 pthread_cond_init(&this->COND_finished, NULL); 00044 init(); 00045 }
Here is the call graph for this function:

| Event_timed::~Event_timed | ( | ) |
Definition at line 55 of file event_timed.cc.
References deinit_mutexes(), free_sp(), and free_sphead_on_delete.
00056 { 00057 deinit_mutexes(); 00058 00059 if (free_sphead_on_delete) 00060 free_sp(); 00061 }
Here is the call graph for this function:

| int Event_timed::compile | ( | THD * | thd, | |
| MEM_ROOT * | mem_root | |||
| ) |
Definition at line 1470 of file event_timed.cc.
References String::c_ptr(), change_security_context(), dbname, DBUG_ASSERT, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, definer, definer_host, definer_user, EVEX_COMPILE_ERROR, EVEX_MICROSECOND_UNSUP, get_charset_by_csname(), get_create_event(), LEX_STRING::length, String::length(), lex_end(), lex_start(), sp_head::m_db, MY_CS_PRIMARY, MY_WME, MYF, name, sp_head::optimize(), restore_security_context(), sp_head::set_definer(), sp_head::set_info(), sphead, sql_mode, sql_print_error(), LEX_STRING::str, system_charset_info, and TRUE.
Referenced by execute(), and Event_scheduler::load_events_from_db().
01471 { 01472 int ret= 0; 01473 MEM_ROOT *tmp_mem_root= 0; 01474 LEX *old_lex= thd->lex, lex; 01475 char *old_db; 01476 int old_db_length; 01477 char *old_query; 01478 uint old_query_len; 01479 ulong old_sql_mode= thd->variables.sql_mode; 01480 char create_buf[2048]; 01481 String show_create(create_buf, sizeof(create_buf), system_charset_info); 01482 CHARSET_INFO *old_character_set_client, 01483 *old_collation_connection, 01484 *old_character_set_results; 01485 Security_context *save_ctx; 01486 /* this one is local and not needed after exec */ 01487 Security_context security_ctx; 01488 01489 DBUG_ENTER("Event_timed::compile"); 01490 01491 show_create.length(0); 01492 01493 switch (get_create_event(thd, &show_create)) { 01494 case EVEX_MICROSECOND_UNSUP: 01495 sql_print_error("Scheduler"); 01496 DBUG_RETURN(EVEX_MICROSECOND_UNSUP); 01497 case 0: 01498 break; 01499 default: 01500 DBUG_ASSERT(0); 01501 } 01502 01503 old_character_set_client= thd->variables.character_set_client; 01504 old_character_set_results= thd->variables.character_set_results; 01505 old_collation_connection= thd->variables.collation_connection; 01506 01507 thd->variables.character_set_client= 01508 thd->variables.character_set_results= 01509 thd->variables.collation_connection= 01510 get_charset_by_csname("utf8", MY_CS_PRIMARY, MYF(MY_WME)); 01511 01512 thd->update_charset(); 01513 01514 DBUG_PRINT("info",("old_sql_mode=%d new_sql_mode=%d",old_sql_mode, sql_mode)); 01515 thd->variables.sql_mode= this->sql_mode; 01516 /* Change the memory root for the execution time */ 01517 if (mem_root) 01518 { 01519 tmp_mem_root= thd->mem_root; 01520 thd->mem_root= mem_root; 01521 } 01522 old_query_len= thd->query_length; 01523 old_query= thd->query; 01524 old_db= thd->db; 01525 old_db_length= thd->db_length; 01526 thd->db= dbname.str; 01527 thd->db_length= dbname.length; 01528 01529 thd->query= show_create.c_ptr(); 01530 thd->query_length= show_create.length(); 01531 DBUG_PRINT("info", ("query:%s",thd->query)); 01532 01533 change_security_context(thd, definer_user, definer_host, dbname, 01534 &security_ctx, &save_ctx); 01535 thd->lex= &lex; 01536 lex_start(thd, (uchar*)thd->query, thd->query_length); 01537 lex.et_compile_phase= TRUE; 01538 if (MYSQLparse((void *)thd) || thd->is_fatal_error) 01539 { 01540 DBUG_PRINT("error", ("error during compile or thd->is_fatal_error=%d", 01541 thd->is_fatal_error)); 01542 /* 01543 Free lex associated resources 01544 QQ: Do we really need all this stuff here? 01545 */ 01546 sql_print_error("error during compile of %s.%s or thd->is_fatal_error=%d", 01547 dbname.str, name.str, thd->is_fatal_error); 01548 if (lex.sphead) 01549 { 01550 if (&lex != thd->lex) 01551 thd->lex->sphead->restore_lex(thd); 01552 delete lex.sphead; 01553 lex.sphead= 0; 01554 } 01555 ret= EVEX_COMPILE_ERROR; 01556 goto done; 01557 } 01558 DBUG_PRINT("note", ("success compiling %s.%s", dbname.str, name.str)); 01559 01560 sphead= lex.et->sphead; 01561 sphead->m_db= dbname; 01562 01563 sphead->set_definer(definer.str, definer.length); 01564 sphead->set_info(0, 0, &lex.sp_chistics, sql_mode); 01565 sphead->optimize(); 01566 ret= 0; 01567 done: 01568 lex.et->free_sphead_on_delete= false; 01569 lex.et->deinit_mutexes(); 01570 01571 lex_end(&lex); 01572 restore_security_context(thd, save_ctx); 01573 DBUG_PRINT("note", ("return old data on its place. set back NAMES")); 01574 01575 thd->lex= old_lex; 01576 thd->query= old_query; 01577 thd->query_length= old_query_len; 01578 thd->db= old_db; 01579 01580 thd->variables.sql_mode= old_sql_mode; 01581 thd->variables.character_set_client= old_character_set_client; 01582 thd->variables.character_set_results= old_character_set_results; 01583 thd->variables.collation_connection= old_collation_connection; 01584 thd->update_charset(); 01585 01586 /* Change the memory root for the execution time. */ 01587 if (mem_root) 01588 thd->mem_root= tmp_mem_root; 01589 01590 DBUG_RETURN(ret); 01591 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool Event_timed::compute_next_execution_time | ( | ) |
Definition at line 929 of file event_timed.cc.
References current_thd, dbname, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, definer, DISABLED, dropped, ends, ends_null, err, execute_at, execute_at_null, expression, FALSE, get_next_time(), Time_zone::gmt_sec_to_TIME(), interval, last_executed, my_time_compare(), my_tz_UTC, MYSQL_TIMESTAMP_DATETIME, name, on_completion, ON_COMPLETION_DROP, set_zero_time(), starts, starts_null, status, status_changed, LEX_STRING::str, TIME_to_ulonglong_datetime(), TRUE, and st_mysql_time::year.
Referenced by Event_scheduler::load_events_from_db(), Event_scheduler::load_named_event(), and spawn_now().
00930 { 00931 TIME time_now; 00932 int tmp; 00933 00934 DBUG_ENTER("Event_timed::compute_next_execution_time"); 00935 DBUG_PRINT("enter", ("starts=%llu ends=%llu last_executed=%llu", 00936 TIME_to_ulonglong_datetime(&starts), 00937 TIME_to_ulonglong_datetime(&ends), 00938 TIME_to_ulonglong_datetime(&last_executed))); 00939 00940 if (status == Event_timed::DISABLED) 00941 { 00942 DBUG_PRINT("compute_next_execution_time", 00943 ("Event %s is DISABLED", name.str)); 00944 goto ret; 00945 } 00946 /* If one-time, no need to do computation */ 00947 if (!expression) 00948 { 00949 /* Let's check whether it was executed */ 00950 if (last_executed.year) 00951 { 00952 DBUG_PRINT("info",("One-time event %s.%s of was already executed", 00953 dbname.str, name.str, definer.str)); 00954 dropped= (on_completion == Event_timed::ON_COMPLETION_DROP); 00955 DBUG_PRINT("info",("One-time event will be dropped=%d.", dropped)); 00956 00957 status= Event_timed::DISABLED; 00958 status_changed= true; 00959 } 00960 goto ret; 00961 } 00962 00963 my_tz_UTC->gmt_sec_to_TIME(&time_now, current_thd->query_start()); 00964 00965 DBUG_PRINT("info",("NOW=[%llu]", TIME_to_ulonglong_datetime(&time_now))); 00966 00967 /* if time_now is after ends don't execute anymore */ 00968 if (!ends_null && (tmp= my_time_compare(&ends, &time_now)) == -1) 00969 { 00970 DBUG_PRINT("info", ("NOW after ENDS, don't execute anymore")); 00971 /* time_now is after ends. don't execute anymore */ 00972 set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME); 00973 execute_at_null= TRUE; 00974 if (on_completion == Event_timed::ON_COMPLETION_DROP) 00975 dropped= true; 00976 DBUG_PRINT("info", ("Dropped=%d", dropped)); 00977 status= Event_timed::DISABLED; 00978 status_changed= true; 00979 00980 goto ret; 00981 } 00982 00983 /* 00984 Here time_now is before or equals ends if the latter is set. 00985 Let's check whether time_now is before starts. 00986 If so schedule for starts. 00987 */ 00988 if (!starts_null && (tmp= my_time_compare(&time_now, &starts)) < 1) 00989 { 00990 if (tmp == 0 && my_time_compare(&starts, &last_executed) == 0) 00991 { 00992 /* 00993 time_now = starts = last_executed 00994 do nothing or we will schedule for second time execution at starts. 00995 */ 00996 } 00997 else 00998 { 00999 DBUG_PRINT("info", ("STARTS is future, NOW <= STARTS,sched for STARTS")); 01000 /* 01001 starts is in the future 01002 time_now before starts. Scheduling for starts 01003 */ 01004 execute_at= starts; 01005 execute_at_null= FALSE; 01006 goto ret; 01007 } 01008 } 01009 01010 if (!starts_null && !ends_null) 01011 { 01012 /* 01013 Both starts and m_ends are set and time_now is between them (incl.) 01014 If last_executed is set then increase with m_expression. The new TIME is 01015 after m_ends set execute_at to 0. And check for on_completion 01016 If not set then schedule for now. 01017 */ 01018 DBUG_PRINT("info", ("Both STARTS & ENDS are set")); 01019 if (!last_executed.year) 01020 { 01021 DBUG_PRINT("info", ("Not executed so far.")); 01022 } 01023 01024 { 01025 TIME next_exec; 01026 01027 if (get_next_time(&next_exec, &starts, &time_now, 01028 last_executed.year? &last_executed:&starts, 01029 expression, interval)) 01030 goto err; 01031 01032 /* There was previous execution */ 01033 if (my_time_compare(&ends, &next_exec) == -1) 01034 { 01035 DBUG_PRINT("info", ("Next execution of %s after ENDS. Stop executing.", 01036 name.str)); 01037 /* Next execution after ends. No more executions */ 01038 set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME); 01039 execute_at_null= TRUE; 01040 if (on_completion == Event_timed::ON_COMPLETION_DROP) 01041 dropped= true; 01042 status= Event_timed::DISABLED; 01043 status_changed= true; 01044 } 01045 else 01046 { 01047 DBUG_PRINT("info",("Next[%llu]",TIME_to_ulonglong_datetime(&next_exec))); 01048 execute_at= next_exec; 01049 execute_at_null= FALSE; 01050 } 01051 } 01052 goto ret; 01053 } 01054 else if (starts_null && ends_null) 01055 { 01056 /* starts is always set, so this is a dead branch !! */ 01057 DBUG_PRINT("info", ("Neither STARTS nor ENDS are set")); 01058 /* 01059 Both starts and m_ends are not set, so we schedule for the next 01060 based on last_executed. 01061 */ 01062 if (last_executed.year) 01063 { 01064 TIME next_exec; 01065 if (get_next_time(&next_exec, &starts, &time_now, &last_executed, 01066 expression, interval)) 01067 goto err; 01068 execute_at= next_exec; 01069 DBUG_PRINT("info",("Next[%llu]",TIME_to_ulonglong_datetime(&next_exec))); 01070 } 01071 else 01072 { 01073 /* last_executed not set. Schedule the event for now */ 01074 DBUG_PRINT("info", ("Execute NOW")); 01075 execute_at= time_now; 01076 } 01077 execute_at_null= FALSE; 01078 } 01079 else 01080 { 01081 /* either starts or m_ends is set */ 01082 if (!starts_null) 01083 { 01084 DBUG_PRINT("info", ("STARTS is set")); 01085 /* 01086 - starts is set. 01087 - starts is not in the future according to check made before 01088 Hence schedule for starts + m_expression in case last_executed 01089 is not set, otherwise to last_executed + m_expression 01090 */ 01091 if (!last_executed.year) 01092 { 01093 DBUG_PRINT("info", ("Not executed so far.")); 01094 } 01095 01096 { 01097 TIME next_exec; 01098 if (get_next_time(&next_exec, &starts, &time_now, 01099 last_executed.year? &last_executed:&starts, 01100 expression, interval)) 01101 goto err; 01102 execute_at= next_exec; 01103 DBUG_PRINT("info",("Next[%llu]",TIME_to_ulonglong_datetime(&next_exec))); 01104 } 01105 execute_at_null= FALSE; 01106 } 01107 else 01108 { 01109 /* this is a dead branch, because starts is always set !!! */ 01110 DBUG_PRINT("info", ("STARTS is not set. ENDS is set")); 01111 /* 01112 - m_ends is set 01113 - m_ends is after time_now or is equal 01114 Hence check for m_last_execute and increment with m_expression. 01115 If last_executed is not set then schedule for now 01116 */ 01117 01118 if (!last_executed.year) 01119 execute_at= time_now; 01120 else 01121 { 01122 TIME next_exec; 01123 01124 if (get_next_time(&next_exec, &starts, &time_now, &last_executed, 01125 expression, interval)) 01126 goto err; 01127 01128 if (my_time_compare(&ends, &next_exec) == -1) 01129 { 01130 DBUG_PRINT("info", ("Next execution after ENDS. Stop executing.")); 01131 set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME); 01132 execute_at_null= TRUE; 01133 status= Event_timed::DISABLED; 01134 status_changed= true; 01135 if (on_completion == Event_timed::ON_COMPLETION_DROP) 01136 dropped= true; 01137 } 01138 else 01139 { 01140 DBUG_PRINT("info", ("Next[%llu]", 01141 TIME_to_ulonglong_datetime(&next_exec))); 01142 execute_at= next_exec; 01143 execute_at_null= FALSE; 01144 } 01145 } 01146 } 01147 goto ret; 01148 } 01149 ret: 01150 DBUG_PRINT("info", ("ret=0")); 01151 DBUG_RETURN(false); 01152 err: 01153 DBUG_PRINT("info", ("ret=1")); 01154 DBUG_RETURN(true); 01155 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void Event_timed::deinit_mutexes | ( | ) |
Definition at line 72 of file event_timed.cc.
References pthread_mutex_destroy.
Referenced by ~Event_timed().
00073 { 00074 pthread_mutex_destroy(&this->LOCK_running); 00075 pthread_cond_destroy(&this->COND_finished); 00076 }
Here is the caller graph for this function:

| int Event_timed::drop | ( | THD * | thd | ) |
Definition at line 1197 of file event_timed.cc.
References db_drop_event(), DBUG_ENTER, and DBUG_RETURN.
Referenced by Event_scheduler::run(), and spawn_thread_finish().
01198 { 01199 uint tmp= 0; 01200 DBUG_ENTER("Event_timed::drop"); 01201 01202 DBUG_RETURN(db_drop_event(thd, this, false, &tmp)); 01203 }
Here is the call graph for this function:

Here is the caller graph for this function:

| int Event_timed::execute | ( | THD * | thd, | |
| MEM_ROOT * | mem_root | |||
| ) |
Definition at line 1370 of file event_timed.cc.
References check_access(), compile(), dbname, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, definer_host, definer_user, base_list::empty(), EVENT_ACL, sp_head::execute_procedure(), expression, free_sp(), LEX_STRING::length, sp_head::LOG_GENERAL_LOG, sp_head::LOG_SLOW_STATEMENTS, sp_head::m_flags, my_strdup(), MYF, name, pthread_mutex_lock, pthread_mutex_unlock, running, sphead, LEX_STRING::str, and VOID.
Referenced by event_worker_thread().
01371 { 01372 /* this one is local and not needed after exec */ 01373 Security_context security_ctx; 01374 int ret= 0; 01375 01376 DBUG_ENTER("Event_timed::execute"); 01377 DBUG_PRINT("info", (" EVEX EXECUTING event %s.%s [EXPR:%d]", 01378 dbname.str, name.str, (int) expression)); 01379 01380 VOID(pthread_mutex_lock(&this->LOCK_running)); 01381 if (running) 01382 { 01383 VOID(pthread_mutex_unlock(&this->LOCK_running)); 01384 DBUG_RETURN(-100); 01385 } 01386 running= true; 01387 VOID(pthread_mutex_unlock(&this->LOCK_running)); 01388 01389 if (!sphead && (ret= compile(thd, mem_root))) 01390 goto done; 01391 /* 01392 THD::~THD will clean this or if there is DROP DATABASE in the SP then 01393 it will be free there. It should not point to our buffer which is allocated 01394 on a mem_root. 01395 */ 01396 thd->db= my_strdup(dbname.str, MYF(0)); 01397 thd->db_length= dbname.length; 01398 if (!check_access(thd, EVENT_ACL,dbname.str, 0, 0, 0,is_schema_db(dbname.str))) 01399 { 01400 List<Item> empty_item_list; 01401 empty_item_list.empty(); 01402 if (thd->enable_slow_log) 01403 sphead->m_flags|= sp_head::LOG_SLOW_STATEMENTS; 01404 sphead->m_flags|= sp_head::LOG_GENERAL_LOG; 01405 01406 ret= sphead->execute_procedure(thd, &empty_item_list); 01407 } 01408 else 01409 { 01410 DBUG_PRINT("error", ("%s@%s has no rights on %s", definer_user.str, 01411 definer_host.str, dbname.str)); 01412 ret= -99; 01413 } 01414 01415 VOID(pthread_mutex_lock(&this->LOCK_running)); 01416 running= false; 01417 /* Will compile every time a new sp_head on different root */ 01418 free_sp(); 01419 VOID(pthread_mutex_unlock(&this->LOCK_running)); 01420 01421 done: 01422 /* 01423 1. Don't cache sphead if allocated on another mem_root 01424 2. Don't call security_ctx.destroy() because this will free our dbname.str 01425 name.str and definer.str 01426 */ 01427 if (mem_root && sphead) 01428 { 01429 delete sphead; 01430 sphead= 0; 01431 } 01432 DBUG_PRINT("info", (" EVEX EXECUTED event %s.%s [EXPR:%d]. RetCode=%d", 01433 dbname.str, name.str, (int) expression, ret)); 01434 01435 DBUG_RETURN(ret); 01436 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void Event_timed::free_sp | ( | ) |
Definition at line 1446 of file event_timed.cc.
References sphead.
Referenced by execute(), Event_scheduler::load_events_from_db(), and ~Event_timed().
Here is the caller graph for this function:

| int Event_timed::get_create_event | ( | THD * | thd, | |
| String * | buf | |||
| ) |
Definition at line 1294 of file event_timed.cc.
References append_identifier(), append_unescaped(), body, buf, comment, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, ENABLED, EVEX_MICROSECOND_UNSUP, execute_at, expression, interval, interval_type_to_name, LEX_STRING::length, String::length(), my_datetime_to_str(), name, on_completion, ON_COMPLETION_DROP, Events::reconstruct_interval_expression(), status, LEX_STRING::str, STRING_WITH_LEN, and system_charset_info.
Referenced by compile(), and Events::show_create_event().
01295 { 01296 int multipl= 0; 01297 char tmp_buff[128]; 01298 String expr_buf(tmp_buff, sizeof(tmp_buff), system_charset_info); 01299 expr_buf.length(0); 01300 01301 DBUG_ENTER("get_create_event"); 01302 DBUG_PRINT("ret_info",("body_len=[%d]body=[%s]", body.length, body.str)); 01303 01304 if (expression && Events::reconstruct_interval_expression(&expr_buf, interval, 01305 expression)) 01306 DBUG_RETURN(EVEX_MICROSECOND_UNSUP); 01307 01308 buf->append(STRING_WITH_LEN("CREATE EVENT ")); 01309 append_identifier(thd, buf, name.str, name.length); 01310 01311 buf->append(STRING_WITH_LEN(" ON SCHEDULE ")); 01312 if (expression) 01313 { 01314 buf->append(STRING_WITH_LEN("EVERY ")); 01315 buf->append(expr_buf); 01316 buf->append(' '); 01317 LEX_STRING *ival= &interval_type_to_name[interval]; 01318 buf->append(ival->str, ival->length); 01319 } 01320 else 01321 { 01322 char dtime_buff[20*2+32];/* +32 to make my_snprintf_{8bit|ucs2} happy */ 01323 buf->append(STRING_WITH_LEN("AT '")); 01324 /* 01325 Pass the buffer and the second param tells fills the buffer and 01326 returns the number of chars to copy. 01327 */ 01328 buf->append(dtime_buff, my_datetime_to_str(&execute_at, dtime_buff)); 01329 buf->append(STRING_WITH_LEN("'")); 01330 } 01331 01332 if (on_completion == Event_timed::ON_COMPLETION_DROP) 01333 buf->append(STRING_WITH_LEN(" ON COMPLETION NOT PRESERVE ")); 01334 else 01335 buf->append(STRING_WITH_LEN(" ON COMPLETION PRESERVE ")); 01336 01337 if (status == Event_timed::ENABLED) 01338 buf->append(STRING_WITH_LEN("ENABLE")); 01339 else 01340 buf->append(STRING_WITH_LEN("DISABLE")); 01341 01342 if (comment.length) 01343 { 01344 buf->append(STRING_WITH_LEN(" COMMENT ")); 01345 append_unescaped(buf, comment.str, comment.length); 01346 } 01347 buf->append(STRING_WITH_LEN(" DO ")); 01348 buf->append(body.str, body.length); 01349 01350 DBUG_RETURN(0); 01351 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool Event_timed::has_equal_db | ( | Event_timed * | etn | ) |
| void Event_timed::init | ( | ) |
Definition at line 107 of file event_timed.cc.
References body, comment, dbname, DBUG_ENTER, DBUG_VOID_RETURN, definer_host, definer_user, ends, ends_null, execute_at, execute_at_null, last_executed, LEX_STRING::length, MYSQL_TIMESTAMP_DATETIME, name, set_zero_time(), sql_mode, starts, starts_null, LEX_STRING::str, and TRUE.
Referenced by Event_timed().
00108 { 00109 DBUG_ENTER("Event_timed::init"); 00110 00111 dbname.str= name.str= body.str= comment.str= 0; 00112 dbname.length= name.length= body.length= comment.length= 0; 00113 00114 set_zero_time(&starts, MYSQL_TIMESTAMP_DATETIME); 00115 set_zero_time(&ends, MYSQL_TIMESTAMP_DATETIME); 00116 set_zero_time(&execute_at, MYSQL_TIMESTAMP_DATETIME); 00117 set_zero_time(&last_executed, MYSQL_TIMESTAMP_DATETIME); 00118 starts_null= ends_null= execute_at_null= TRUE; 00119 00120 definer_user.str= definer_host.str= 0; 00121 definer_user.length= definer_host.length= 0; 00122 00123 sql_mode= 0; 00124 00125 DBUG_VOID_RETURN; 00126 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void Event_timed::init_body | ( | THD * | thd | ) |
Definition at line 177 of file event_timed.cc.
References body, body_begin, DBUG_ENTER, DBUG_PRINT, DBUG_VOID_RETURN, LEX_STRING::length, my_isspace, LEX_STRING::str, and strmake_root().
00178 { 00179 DBUG_ENTER("Event_timed::init_body"); 00180 DBUG_PRINT("info", ("body=[%s] body_begin=0x%ld end=0x%ld", body_begin, 00181 body_begin, thd->lex->ptr)); 00182 00183 body.length= thd->lex->ptr - body_begin; 00184 const uchar *body_end= body_begin + body.length - 1; 00185 00186 /* Trim nuls or close-comments ('*'+'/') or spaces at the end */ 00187 while (body_begin < body_end) 00188 { 00189 00190 if ((*body_end == '\0') || 00191 (my_isspace(thd->variables.character_set_client, *body_end))) 00192 { /* consume NULs and meaningless whitespace */ 00193 --body.length; 00194 --body_end; 00195 continue; 00196 } 00197 00198 /* 00199 consume closing comments 00200 00201 This is arguably wrong, but it's the best we have until the parser is 00202 changed to be smarter. FIXME PARSER 00203 00204 See also the sp_head code, where something like this is done also. 00205 00206 One idea is to keep in the lexer structure the count of the number of 00207 open-comments we've entered, and scan left-to-right looking for a 00208 closing comment IFF the count is greater than zero. 00209 00210 Another idea is to remove the closing comment-characters wholly in the 00211 parser, since that's where it "removes" the opening characters. 00212 */ 00213 if ((*(body_end - 1) == '*') && (*body_end == '/')) 00214 { 00215 DBUG_PRINT("info", ("consumend one '*" "/' comment in the query '%s'", 00216 body_begin)); 00217 body.length-= 2; 00218 body_end-= 2; 00219 continue; 00220 } 00221 00222 break; /* none were found, so we have excised all we can. */ 00223 } 00224 00225 /* the first is always whitespace which I cannot skip in the parser */ 00226 while (my_isspace(thd->variables.character_set_client, *body_begin)) 00227 { 00228 ++body_begin; 00229 --body.length; 00230 } 00231 body.str= strmake_root(thd->mem_root, (char *)body_begin, body.length); 00232 00233 DBUG_VOID_RETURN; 00234 }
Here is the call graph for this function:

| void Event_timed::init_comment | ( | THD * | thd, | |
| LEX_STRING * | set_comment | |||
| ) |
Definition at line 550 of file event_timed.cc.
References comment, DBUG_ENTER, DBUG_VOID_RETURN, LEX_STRING::length, LEX_STRING::str, and strmake_root().
00551 { 00552 DBUG_ENTER("Event_timed::init_comment"); 00553 00554 comment.str= strmake_root(thd->mem_root, set_comment->str, 00555 comment.length= set_comment->length); 00556 00557 DBUG_VOID_RETURN; 00558 }
Here is the call graph for this function:

| int Event_timed::init_definer | ( | THD * | thd | ) |
Definition at line 572 of file event_timed.cc.
References alloc_root(), DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, definer, definer_host, definer_user, LEX_STRING::length, memcpy, LEX_STRING::str, strdup_root(), and strlen().
00573 { 00574 DBUG_ENTER("Event_timed::init_definer"); 00575 00576 DBUG_PRINT("info",("init definer_user thd->mem_root=0x%lx " 00577 "thd->sec_ctx->priv_user=0x%lx", thd->mem_root, 00578 thd->security_ctx->priv_user)); 00579 definer_user.str= strdup_root(thd->mem_root, thd->security_ctx->priv_user); 00580 definer_user.length= strlen(thd->security_ctx->priv_user); 00581 00582 DBUG_PRINT("info",("init definer_host thd->s_c->priv_host=0x%lx", 00583 thd->security_ctx->priv_host)); 00584 definer_host.str= strdup_root(thd->mem_root, thd->security_ctx->priv_host); 00585 definer_host.length= strlen(thd->security_ctx->priv_host); 00586 00587 DBUG_PRINT("info",("init definer as whole")); 00588 definer.length= definer_user.length + definer_host.length + 1; 00589 definer.str= alloc_root(thd->mem_root, definer.length + 1); 00590 00591 DBUG_PRINT("info",("copy the user")); 00592 memcpy(definer.str, definer_user.str, definer_user.length); 00593 definer.str[definer_user.length]= '@'; 00594 00595 DBUG_PRINT("info",("copy the host")); 00596 memcpy(definer.str + definer_user.length + 1, definer_host.str, 00597 definer_host.length); 00598 definer.str[definer.length]= '\0'; 00599 DBUG_PRINT("info",("definer initted")); 00600 00601 DBUG_RETURN(0); 00602 }
Here is the call graph for this function:

| int Event_timed::init_ends | ( | THD * | thd, | |
| Item * | ends | |||
| ) |
Definition at line 490 of file event_timed.cc.
References DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, ends, ends_null, EVEX_BAD_PARAMS, EVEX_PARSE_ERROR, FALSE, Item::fix_fields(), Item::get_date(), Time_zone::gmt_sec_to_TIME(), my_time_compare(), my_tz_UTC, starts, starts_null, TIME_NO_ZERO_DATE, and TIME_to_timestamp().
00491 { 00492 TIME ltime, ltime_now; 00493 my_bool not_used; 00494 my_time_t t; 00495 00496 DBUG_ENTER("Event_timed::init_ends"); 00497 00498 if (new_ends->fix_fields(thd, &new_ends)) 00499 DBUG_RETURN(EVEX_PARSE_ERROR); 00500 00501 DBUG_PRINT("info", ("convert to TIME")); 00502 if ((not_used= new_ends->get_date(<ime, TIME_NO_ZERO_DATE))) 00503 DBUG_RETURN(EVEX_BAD_PARAMS); 00504 00505 /* 00506 This may result in a 1970-01-01 date if ltime is > 2037-xx-xx. 00507 CONVERT_TZ has similar problem. 00508 mysql_priv.h currently lists 00509 #define TIMESTAMP_MAX_YEAR 2038 (see TIME_to_timestamp()) 00510 */ 00511 DBUG_PRINT("info", ("get the UTC time")); 00512 my_tz_UTC->gmt_sec_to_TIME(<ime,t=TIME_to_timestamp(thd, <ime, ¬_used)); 00513 if (!t) 00514 { 00515 DBUG_PRINT("error", ("ENDS after year 2037")); 00516 DBUG_RETURN(EVEX_BAD_PARAMS); 00517 } 00518 00519 /* Check whether ends is after starts */ 00520 DBUG_PRINT("info", ("ENDS after STARTS?")); 00521 if (!starts_null && my_time_compare(&starts, <ime) != -1) 00522 DBUG_RETURN(EVEX_BAD_PARAMS); 00523 00524 /* 00525 The parser forces starts to be provided but one day STARTS could be 00526 set before NOW() and in this case the following check should be done. 00527 Check whether ENDS is not in the past. 00528 */ 00529 DBUG_PRINT("info", ("ENDS after NOW?")); 00530 my_tz_UTC->gmt_sec_to_TIME(<ime_now, thd->query_start()); 00531 if (my_time_compare(<ime_now, <ime) == 1) 00532 DBUG_RETURN(EVEX_BAD_PARAMS); 00533 00534 ends= ltime; 00535 ends_null= FALSE; 00536 DBUG_RETURN(0); 00537 }
Here is the call graph for this function:

| int Event_timed::init_execute_at | ( | THD * | thd, | |
| Item * | expr | |||
| ) |
Definition at line 252 of file event_timed.cc.
References DBUG_ASSERT, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, ends_null, ER_WRONG_VALUE, EVEX_BAD_PARAMS, EVEX_PARSE_ERROR, execute_at, execute_at_null, FALSE, Item::fix_fields(), Item::get_date(), Time_zone::gmt_sec_to_TIME(), my_tz_UTC, starts_null, TIME_NO_ZERO_DATE, TIME_to_timestamp(), and TIME_to_ulonglong_datetime().
00253 { 00254 my_bool not_used; 00255 TIME ltime; 00256 my_time_t t; 00257 00258 TIME time_tmp; 00259 DBUG_ENTER("Event_timed::init_execute_at"); 00260 00261 if (expr->fix_fields(thd, &expr)) 00262 DBUG_RETURN(EVEX_PARSE_ERROR); 00263 00264 /* no starts and/or ends in case of execute_at */ 00265 DBUG_PRINT("info", ("starts_null && ends_null should be 1 is %d", 00266 (starts_null && ends_null))); 00267 DBUG_ASSERT(starts_null && ends_null); 00268 00269 /* let's check whether time is in the past */ 00270 thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp, 00271 (my_time_t) thd->query_start()); 00272 00273 if ((not_used= expr->get_date(<ime, TIME_NO_ZERO_DATE))) 00274 DBUG_RETURN(ER_WRONG_VALUE); 00275 00276 if (TIME_to_ulonglong_datetime(<ime) < 00277 TIME_to_ulonglong_datetime(&time_tmp)) 00278 DBUG_RETURN(EVEX_BAD_PARAMS); 00279 00280 /* 00281 This may result in a 1970-01-01 date if ltime is > 2037-xx-xx. 00282 CONVERT_TZ has similar problem. 00283 mysql_priv.h currently lists 00284 #define TIMESTAMP_MAX_YEAR 2038 (see TIME_to_timestamp()) 00285 */ 00286 my_tz_UTC->gmt_sec_to_TIME(<ime,t=TIME_to_timestamp(thd,<ime,¬_used)); 00287 if (!t) 00288 { 00289 DBUG_PRINT("error", ("Execute AT after year 2037")); 00290 DBUG_RETURN(ER_WRONG_VALUE); 00291 } 00292 00293 execute_at_null= FALSE; 00294 execute_at= ltime; 00295 DBUG_RETURN(0); 00296 }
Here is the call graph for this function:

| int Event_timed::init_interval | ( | THD * | thd, | |
| Item * | expr, | |||
| interval_type | new_interval | |||
| ) |
Definition at line 315 of file event_timed.cc.
References INTERVAL::day, DBUG_ASSERT, DBUG_ENTER, DBUG_RETURN, EVEX_BAD_PARAMS, EVEX_MAX_INTERVAL_VALUE, EVEX_MICROSECOND_UNSUP, EVEX_PARSE_ERROR, expression, Item::fix_fields(), get_interval_value(), INTERVAL::hour, interval, INTERVAL_DAY, INTERVAL_DAY_HOUR, INTERVAL_DAY_MICROSECOND, INTERVAL_DAY_MINUTE, INTERVAL_DAY_SECOND, INTERVAL_HOUR, INTERVAL_HOUR_MICROSECOND, INTERVAL_HOUR_MINUTE, INTERVAL_HOUR_SECOND, INTERVAL_LAST, INTERVAL_MICROSECOND, INTERVAL_MINUTE, INTERVAL_MINUTE_MICROSECOND, INTERVAL_MINUTE_SECOND, INTERVAL_MONTH, INTERVAL_QUARTER, INTERVAL_SECOND, INTERVAL_SECOND_MICROSECOND, INTERVAL_WEEK, INTERVAL_YEAR, INTERVAL_YEAR_MONTH, MAX_DATETIME_FULL_WIDTH, INTERVAL::minute, INTERVAL::month, MY_CHARSET_BIN_MB_MAXLEN, INTERVAL::neg, INTERVAL::second, INTERVAL::second_part, value, and INTERVAL::year.
00316 { 00317 String value; 00318 INTERVAL interval_tmp; 00319 00320 DBUG_ENTER("Event_timed::init_interval"); 00321 00322 if (expr->fix_fields(thd, &expr)) 00323 DBUG_RETURN(EVEX_PARSE_ERROR); 00324 00325 value.alloc(MAX_DATETIME_FULL_WIDTH*MY_CHARSET_BIN_MB_MAXLEN); 00326 if (get_interval_value(expr, new_interval, &value, &interval_tmp)) 00327 DBUG_RETURN(EVEX_PARSE_ERROR); 00328 00329 expression= 0; 00330 00331 switch (new_interval) { 00332 case INTERVAL_YEAR: 00333 expression= interval_tmp.year; 00334 break; 00335 case INTERVAL_QUARTER: 00336 case INTERVAL_MONTH: 00337 expression= interval_tmp.month; 00338 break; 00339 case INTERVAL_WEEK: 00340 case INTERVAL_DAY: 00341 expression= interval_tmp.day; 00342 break; 00343 case INTERVAL_HOUR: 00344 expression= interval_tmp.hour; 00345 break; 00346 case INTERVAL_MINUTE: 00347 expression= interval_tmp.minute; 00348 break; 00349 case INTERVAL_SECOND: 00350 expression= interval_tmp.second; 00351 break; 00352 case INTERVAL_YEAR_MONTH: // Allow YEAR-MONTH YYYYYMM 00353 expression= interval_tmp.year* 12 + interval_tmp.month; 00354 break; 00355 case INTERVAL_DAY_HOUR: 00356 expression= interval_tmp.day* 24 + interval_tmp.hour; 00357 break; 00358 case INTERVAL_DAY_MINUTE: 00359 expression= (interval_tmp.day* 24 + interval_tmp.hour) * 60 + 00360 interval_tmp.minute; 00361 break; 00362 case INTERVAL_HOUR_SECOND: /* day is anyway 0 */ 00363 case INTERVAL_DAY_SECOND: 00364 /* DAY_SECOND having problems because of leap seconds? */ 00365 expression= ((interval_tmp.day* 24 + interval_tmp.hour) * 60 + 00366 interval_tmp.minute)*60 00367 + interval_tmp.second; 00368 break; 00369 case INTERVAL_MINUTE_MICROSECOND: /* day and hour are 0 */ 00370 case INTERVAL_HOUR_MICROSECOND: /* day is anyway 0 */ 00371 case INTERVAL_DAY_MICROSECOND: 00372 DBUG_RETURN(EVEX_MICROSECOND_UNSUP); 00373 expression= ((((interval_tmp.day*24) + interval_tmp.hour)*60+ 00374 interval_tmp.minute)*60 + 00375 interval_tmp.second) * 1000000L + interval_tmp.second_part; 00376 break; 00377 case INTERVAL_HOUR_MINUTE: 00378 expression= interval_tmp.hour * 60 + interval_tmp.minute; 00379 break; 00380 case INTERVAL_MINUTE_SECOND: 00381 expression= interval_tmp.minute * 60 + interval_tmp.second; 00382 break; 00383 case INTERVAL_SECOND_MICROSECOND: 00384 DBUG_RETURN(EVEX_MICROSECOND_UNSUP); 00385 expression= interval_tmp.second * 1000000L + interval_tmp.second_part; 00386 break; 00387 case INTERVAL_MICROSECOND: 00388 DBUG_RETURN(EVEX_MICROSECOND_UNSUP); 00389 case INTERVAL_LAST: 00390 DBUG_ASSERT(0); 00391 } 00392 if (interval_tmp.neg || expression > EVEX_MAX_INTERVAL_VALUE) 00393 DBUG_RETURN(EVEX_BAD_PARAMS); 00394 00395 interval= new_interval; 00396 DBUG_RETURN(0); 00397 }
Here is the call graph for this function:

| void Event_timed::init_name | ( | THD * | thd, | |
| sp_name * | spn | |||
| ) |
Definition at line 139 of file event_timed.cc.
References dbname, DBUG_ENTER, DBUG_PRINT, DBUG_VOID_RETURN, sp_name::init_qname(), LEX_STRING::length, sp_name::m_db, sp_name::m_name, sp_name::m_qname, name, LEX_STRING::str, and strmake_root().
00140 { 00141 DBUG_ENTER("Event_timed::init_name"); 00142 /* During parsing, we must use thd->mem_root */ 00143 MEM_ROOT *root= thd->mem_root; 00144 00145 /* We have to copy strings to get them into the right memroot */ 00146 dbname.length= spn->m_db.length; 00147 dbname.str= strmake_root(root, spn->m_db.str, spn->m_db.length); 00148 name.length= spn->m_name.length; 00149 name.str= strmake_root(root, spn->m_name.str, spn->m_name.length); 00150 00151 if (spn->m_qname.length == 0) 00152 spn->init_qname(thd); 00153 00154 DBUG_PRINT("dbname", ("len=%d db=%s",dbname.length, dbname.str)); 00155 DBUG_PRINT("name", ("len=%d name=%s",name.length, name.str)); 00156 00157 DBUG_VOID_RETURN; 00158 }
Here is the call graph for this function:

| int Event_timed::init_starts | ( | THD * | thd, | |
| Item * | starts | |||
| ) |
Definition at line 423 of file event_timed.cc.
References DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, EVEX_BAD_PARAMS, EVEX_PARSE_ERROR, FALSE, Item::fix_fields(), Item::get_date(), Time_zone::gmt_sec_to_TIME(), my_tz_UTC, starts, starts_null, TIME_NO_ZERO_DATE, TIME_to_timestamp(), and TIME_to_ulonglong_datetime().
00424 { 00425 my_bool not_used; 00426 TIME ltime, time_tmp; 00427 my_time_t t; 00428 00429 DBUG_ENTER("Event_timed::init_starts"); 00430 00431 if (new_starts->fix_fields(thd, &new_starts)) 00432 DBUG_RETURN(EVEX_PARSE_ERROR); 00433 00434 if ((not_used= new_starts->get_date(<ime, TIME_NO_ZERO_DATE))) 00435 DBUG_RETURN(EVEX_BAD_PARAMS); 00436 00437 /* Let's check whether time is in the past */ 00438 thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp, 00439 (my_time_t) thd->query_start()); 00440 00441 DBUG_PRINT("info",("now =%lld", TIME_to_ulonglong_datetime(&time_tmp))); 00442 DBUG_PRINT("info",("starts=%lld", TIME_to_ulonglong_datetime(<ime))); 00443 if (TIME_to_ulonglong_datetime(<ime) < 00444 TIME_to_ulonglong_datetime(&time_tmp)) 00445 DBUG_RETURN(EVEX_BAD_PARAMS); 00446 00447 /* 00448 This may result in a 1970-01-01 date if ltime is > 2037-xx-xx. 00449 CONVERT_TZ has similar problem. 00450 mysql_priv.h currently lists 00451 #define TIMESTAMP_MAX_YEAR 2038 (see TIME_to_timestamp()) 00452 */ 00453 my_tz_UTC->gmt_sec_to_TIME(<ime,t=TIME_to_timestamp(thd, <ime, ¬_used)); 00454 if (!t) 00455 { 00456 DBUG_PRINT("error", ("STARTS after year 2037")); 00457 DBUG_RETURN(EVEX_BAD_PARAMS); 00458 } 00459 00460 starts= ltime; 00461 starts_null= FALSE; 00462 DBUG_RETURN(0); 00463 }
Here is the call graph for this function:

| bool Event_timed::is_running | ( | ) |
Definition at line 87 of file event_timed.cc.
References pthread_mutex_lock, pthread_mutex_unlock, running, and VOID.
00088 { 00089 bool ret; 00090 00091 VOID(pthread_mutex_lock(&this->LOCK_running)); 00092 ret= running; 00093 VOID(pthread_mutex_unlock(&this->LOCK_running)); 00094 00095 return ret; 00096 }
| int Event_timed::kill_thread | ( | THD * | thd | ) |
Definition at line 1693 of file event_timed.cc.
References COND_finished, DBUG_ASSERT, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, EVEX_CANT_KILL, in_spawned_thread, kill_one_thread(), LOCK_running, pthread_mutex_lock, pthread_mutex_unlock, and thread_id.
Referenced by Event_scheduler::drop_event(), Event_scheduler::drop_matching_events(), and Event_scheduler::update_event().
01694 { 01695 int ret= 0; 01696 DBUG_ENTER("Event_timed::kill_thread"); 01697 pthread_mutex_lock(&LOCK_running); 01698 DBUG_PRINT("info", ("thread_id=%lu", thread_id)); 01699 01700 if (thread_id == thd->thread_id) 01701 { 01702 /* 01703 We don't kill ourselves in cases like : 01704 alter event e_43 do alter event e_43 do set @a = 4 because 01705 we will never receive COND_finished. 01706 */ 01707 DBUG_PRINT("info", ("It's not safe to kill ourselves in self altering queries")); 01708 ret= EVEX_CANT_KILL; 01709 } 01710 else if (thread_id && !(ret= kill_one_thread(thd, thread_id, false))) 01711 { 01712 thd->enter_cond(&COND_finished, &LOCK_running, "Waiting for finished"); 01713 DBUG_PRINT("info", ("Waiting for COND_finished from thread %d", thread_id)); 01714 while (thread_id) 01715 pthread_cond_wait(&COND_finished, &LOCK_running); 01716 01717 DBUG_PRINT("info", ("Got COND_finished")); 01718 /* This will implicitly unlock LOCK_running. Hence we return before that */ 01719 thd->exit_cond(""); 01720 01721 DBUG_RETURN(0); 01722 } 01723 else if (!thread_id && in_spawned_thread) 01724 { 01725 /* 01726 Because the manager thread waits for the forked thread to update thread_id 01727 this situation is impossible. 01728 */ 01729 DBUG_ASSERT(0); 01730 } 01731 pthread_mutex_unlock(&LOCK_running); 01732 DBUG_PRINT("exit", ("%d", ret)); 01733 DBUG_RETURN(ret); 01734 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 622 of file event_timed.cc.
References body, comment, created, dbname, DBUG_ASSERT, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, definer, definer_host, definer_user, DISABLED, ENABLED, ends, ends_null, error, EVEX_GET_FIELD_FAILED, execute_at, execute_at_null, expression, st_table::field, Events::FIELD_BODY, Events::FIELD_COMMENT, Events::FIELD_COUNT, Events::FIELD_CREATED, Events::FIELD_DB, Events::FIELD_DEFINER, Events::FIELD_ENDS, Events::FIELD_EXECUTE_AT, Events::FIELD_INTERVAL_EXPR, Events::FIELD_LAST_EXECUTED, Events::FIELD_MODIFIED, Events::FIELD_NAME, Events::FIELD_ON_COMPLETION, Events::FIELD_SQL_MODE, Events::FIELD_STARTS, Events::FIELD_STATUS, Events::FIELD_TRANSIENT_INTERVAL, st_table_share::fields, Field::get_date(), get_date(), get_field(), interval, Field::is_null(), last_executed, last_executed_changed, LEX_STRING::length, modified, name, NULL, NullS, on_completion, ON_COMPLETION_DROP, ON_COMPLETION_PRESERVE, st_table::s, sql_mode, starts, starts_null, status, LEX_STRING::str, strchr(), strlen(), strmake_root(), TIME_NO_ZERO_DATE, and Field::val_int().
Referenced by copy_event_to_schema_table(), db_find_event(), and Event_scheduler::load_events_from_db().
00623 { 00624 char *ptr; 00625 Event_timed *et; 00626 uint len; 00627 bool res1, res2; 00628 00629 DBUG_ENTER("Event_timed::load_from_row"); 00630 00631 if (!table) 00632 goto error; 00633 00634 et= this; 00635 00636 if (table->s->fields != Events::FIELD_COUNT) 00637 goto error; 00638 00639 if ((et->dbname.str= get_field(mem_root, 00640 table->field[Events::FIELD_DB])) == NULL) 00641 goto error; 00642 00643 et->dbname.length= strlen(et->dbname.str); 00644 00645 if ((et->name.str= get_field(mem_root, 00646 table->field[Events::FIELD_NAME])) == NULL) 00647 goto error; 00648 00649 et->name.length= strlen(et->name.str); 00650 00651 if ((et->body.str= get_field(mem_root, 00652 table->field[Events::FIELD_BODY])) == NULL) 00653 goto error; 00654 00655 et->body.length= strlen(et->body.str); 00656 00657 if ((et->definer.str= get_field(mem_root, 00658 table->field[Events::FIELD_DEFINER])) == NullS) 00659 goto error; 00660 et->definer.length= strlen(et->definer.str); 00661 00662 ptr= strchr(et->definer.str, '@'); 00663 00664 if (! ptr) 00665 ptr= et->definer.str; 00666 00667 len= ptr - et->definer.str; 00668 00669 et->definer_user.str= strmake_root(mem_root, et->definer.str, len); 00670 et->definer_user.length= len; 00671 len= et->definer.length - len - 1; //1 is because of @ 00672 et->definer_host.str= strmake_root(mem_root, ptr + 1, len);/* 1:because of @*/ 00673 et->definer_host.length= len; 00674 00675 et->starts_null= table->field[Events::FIELD_STARTS]->is_null(); 00676 res1= table->field[Events::FIELD_STARTS]-> 00677 get_date(&et->starts,TIME_NO_ZERO_DATE); 00678 00679 et->ends_null= table->field[Events::FIELD_ENDS]->is_null(); 00680 res2= table->field[Events::FIELD_ENDS]->get_date(&et->ends, TIME_NO_ZERO_DATE); 00681 00682 if (!table->field[Events::FIELD_INTERVAL_EXPR]->is_null()) 00683 et->expression= table->field[Events::FIELD_INTERVAL_EXPR]->val_int(); 00684 else 00685 et->expression= 0; 00686 /* 00687 If res1 and res2 are true then both fields are empty. 00688 Hence if Events::FIELD_EXECUTE_AT is empty there is an error. 00689 */ 00690 et->execute_at_null= 00691 table->field[Events::FIELD_EXECUTE_AT]->is_null(); 00692 DBUG_ASSERT(!(et->starts_null && et->ends_null && !et->expression && 00693 et->execute_at_null)); 00694 if (!et->expression && 00695 table->field[Events::FIELD_EXECUTE_AT]-> get_date(&et->execute_at, 00696 TIME_NO_ZERO_DATE)) 00697 goto error; 00698 00699 /* 00700 In DB the values start from 1 but enum interval_type starts 00701 from 0 00702 */ 00703 if (!table->field[Events::FIELD_TRANSIENT_INTERVAL]->is_null()) 00704 et->interval= (interval_type) ((ulonglong) 00705 table->field[Events::FIELD_TRANSIENT_INTERVAL]->val_int() - 1); 00706 else 00707 et->interval= (interval_type) 0; 00708 00709 et->created= table->field[Events::FIELD_CREATED]->val_int(); 00710 et->modified= table->field[Events::FIELD_MODIFIED]->val_int(); 00711 00712 table->field[Events::FIELD_LAST_EXECUTED]-> 00713 get_date(&et->last_executed, TIME_NO_ZERO_DATE); 00714 00715 last_executed_changed= false; 00716 00717 /* ToDo : Andrey . Find a way not to allocate ptr on event_mem_root */ 00718 if ((ptr= get_field(mem_root, table->field[Events::FIELD_STATUS])) == NullS) 00719 goto error; 00720 00721 DBUG_PRINT("load_from_row", ("Event [%s] is [%s]", et->name.str, ptr)); 00722 et->status= (ptr[0]=='E'? Event_timed::ENABLED:Event_timed::DISABLED); 00723 00724 /* ToDo : Andrey . Find a way not to allocate ptr on event_mem_root */ 00725 if ((ptr= get_field(mem_root, 00726 table->field[Events::FIELD_ON_COMPLETION])) == NullS) 00727 goto error; 00728 00729 et->on_completion= (ptr[0]=='D'? Event_timed::ON_COMPLETION_DROP: 00730 Event_timed::ON_COMPLETION_PRESERVE); 00731 00732 et->comment.str= get_field(mem_root, table->field[Events::FIELD_COMMENT]); 00733 if (et->comment.str != NullS) 00734 et->comment.length= strlen(et->comment.str); 00735 else 00736 et->comment.length= 0; 00737 00738 00739 et->sql_mode= (ulong) table->field[Events::FIELD_SQL_MODE]->val_int(); 00740 00741 DBUG_RETURN(0); 00742 error: 00743 DBUG_RETURN(EVEX_GET_FIELD_FAILED); 00744 }
Here is the call graph for this function:

Here is the caller graph for this function:

| void Event_timed::mark_last_executed | ( | THD * | thd | ) |
Definition at line 1168 of file event_timed.cc.
References Time_zone::gmt_sec_to_TIME(), last_executed, last_executed_changed, and my_tz_UTC.
Referenced by spawn_now().
01169 { 01170 TIME time_now; 01171 01172 thd->end_time(); 01173 my_tz_UTC->gmt_sec_to_TIME(&time_now, (my_time_t) thd->query_start()); 01174 01175 last_executed= time_now; /* was execute_at */ 01176 last_executed_changed= true; 01177 }
Here is the call graph for this function:

Here is the caller graph for this function:

| static void Event_timed::operator delete | ( | void * | ptr, | |
| MEM_ROOT * | mem_root | |||
| ) | [inline, static] |
Definition at line 126 of file event_timed.h.
References DBUG_ASSERT.
00127 { 00128 /* 00129 Don't free the memory it will be done by the mem_root but 00130 we need to call the destructor because we free other resources 00131 which are not allocated on the root but on the heap, or we 00132 deinit mutexes. 00133 */ 00134 DBUG_ASSERT(0); 00135 }
| static void Event_timed::operator delete | ( | void * | ptr, | |
| size_t | size | |||
| ) | [inline, static] |
Definition at line 117 of file event_timed.h.
References DBUG_ENTER, DBUG_PRINT, DBUG_VOID_RETURN, my_free, MYF, and TRASH.
00118 { 00119 DBUG_ENTER("Event_timed::delete(ptr,size)"); 00120 DBUG_PRINT("enter", ("free_ptr=0x%lx", ptr)); 00121 TRASH(ptr, size); 00122 my_free((gptr) ptr, MYF(0)); 00123 DBUG_VOID_RETURN; 00124 }
Definition at line 114 of file event_timed.h.
References alloc_root().
00115 { return (void*) alloc_root(mem_root, (uint) size); }
Here is the call graph for this function:

| static void* Event_timed::operator new | ( | size_t | size | ) | [inline, static] |
Definition at line 105 of file event_timed.h.
References DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, my_malloc(), MYF, and p.
00106 { 00107 void *p; 00108 DBUG_ENTER("Event_timed::new(size)"); 00109 p= my_malloc(size, MYF(0)); 00110 DBUG_PRINT("info", ("alloc_ptr=0x%lx", p)); 00111 DBUG_RETURN(p); 00112 }
Here is the call graph for this function:

| void Event_timed::operator= | ( | Event_timed & | ) | [private] |
| void Event_timed::set_thread_id | ( | ulong | tid | ) | [inline] |
Definition at line 214 of file event_timed.h.
References thread_id.
Referenced by event_worker_thread().
00214 { thread_id= tid; }
Here is the caller graph for this function:

| int Event_timed::spawn_now | ( | void *(*)(void *) | thread_func, | |
| void * | arg | |||
| ) |
Definition at line 1606 of file event_timed.cc.
References compute_next_execution_time(), connection_attrib, current_thd, dbname, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, definer, DISABLED, EVENT_EXEC_ALREADY_EXEC, EVENT_EXEC_CANT_FORK, EVENT_EXEC_NO_MORE, EVENT_EXEC_STARTED, EVENT_FREE_WHEN_FINISHED, execute_at, execute_at_null, expression, flags, in_spawned_thread, mark_last_executed(), name, pthread_mutex_lock, pthread_mutex_unlock, sql_print_error(), sql_print_information(), status, LEX_STRING::str, TIME_to_ulonglong_datetime(), update_fields(), VOID, and st_mysql_time::year.
Referenced by Event_scheduler::execute_top().
01607 { 01608 THD *thd= current_thd; 01609 int ret= EVENT_EXEC_STARTED; 01610 DBUG_ENTER("Event_timed::spawn_now"); 01611 DBUG_PRINT("info", ("[%s.%s]", dbname.str, name.str)); 01612 01613 VOID(pthread_mutex_lock(&this->LOCK_running)); 01614 01615 DBUG_PRINT("info", ("SCHEDULER: execute_at of %s is %lld", name.str, 01616 TIME_to_ulonglong_datetime(&execute_at))); 01617 mark_last_executed(thd); 01618 if (compute_next_execution_time()) 01619 { 01620 sql_print_error("SCHEDULER: Error while computing time of %s.%s . " 01621 "Disabling after execution.", dbname.str, name.str); 01622 status= DISABLED; 01623 } 01624 DBUG_PRINT("evex manager", ("[%10s] next exec at [%llu]", name.str, 01625 TIME_to_ulonglong_datetime(&execute_at))); 01626 /* 01627 1. For one-time event : year is > 0 and expression is 0 01628 2. For recurring, expression is != -=> check execute_at_null in this case 01629 */ 01630 if ((execute_at.year && !expression) || execute_at_null) 01631 { 01632 sql_print_information("SCHEDULER: [%s.%s of %s] no more executions " 01633 "after this one", dbname.str, name.str, 01634 definer.str); 01635 flags |= EVENT_EXEC_NO_MORE | EVENT_FREE_WHEN_FINISHED; 01636 } 01637 01638 update_fields(thd); 01639 01640 if (!in_spawned_thread) 01641 { 01642 pthread_t th; 01643 in_spawned_thread= true; 01644 01645 if (pthread_create(&th, &connection_attrib, thread_func, arg)) 01646 { 01647 DBUG_PRINT("info", ("problem while spawning thread")); 01648 ret= EVENT_EXEC_CANT_FORK; 01649 in_spawned_thread= false; 01650 } 01651 } 01652 else 01653 { 01654 DBUG_PRINT("info", ("already in spawned thread. skipping")); 01655 ret= EVENT_EXEC_ALREADY_EXEC; 01656 } 01657 VOID(pthread_mutex_unlock(&this->LOCK_running)); 01658 01659 DBUG_RETURN(ret); 01660 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool Event_timed::spawn_thread_finish | ( | THD * | thd | ) |
Definition at line 1664 of file event_timed.cc.
References COND_finished, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, drop(), dropped, EVENT_FREE_WHEN_FINISHED, flags, in_spawned_thread, LOCK_running, pthread_mutex_lock, pthread_mutex_unlock, thread_id, and VOID.
Referenced by event_worker_thread().
01665 { 01666 bool should_free; 01667 DBUG_ENTER("Event_timed::spawn_thread_finish"); 01668 VOID(pthread_mutex_lock(&LOCK_running)); 01669 in_spawned_thread= false; 01670 DBUG_PRINT("info", ("Sending COND_finished for thread %d", thread_id)); 01671 thread_id= 0; 01672 if (dropped) 01673 drop(thd); 01674 pthread_cond_broadcast(&COND_finished); 01675 should_free= flags & EVENT_FREE_WHEN_FINISHED; 01676 VOID(pthread_mutex_unlock(&LOCK_running)); 01677 DBUG_RETURN(should_free); 01678 }
Here is the call graph for this function:

Here is the caller graph for this function:

| bool Event_timed::update_fields | ( | THD * | thd | ) |
Definition at line 1223 of file event_timed.cc.
References backup, close_thread_tables(), dbname, DBUG_ENTER, DBUG_PRINT, DBUG_RETURN, evex_db_find_event_by_name(), EVEX_OPEN_TABLE_FAILED, EVEX_WRITE_ROW_FAILED, st_table::field, Events::FIELD_LAST_EXECUTED, Events::FIELD_STATUS, st_table::file, handler::ha_update_row(), last_executed, last_executed_changed, LEX_STRING::length, MYSQL_TIMESTAMP_DATETIME, name, Events::open_event_table(), st_table::record, Field::set_notnull(), status, status_changed, Field::store(), store_record, Field::store_time(), LEX_STRING::str, st_table::timestamp_field_type, TIMESTAMP_NO_AUTO_SET, and TL_WRITE.
Referenced by spawn_now().
01224 { 01225 TABLE *table; 01226 Open_tables_state backup; 01227 int ret; 01228 01229 DBUG_ENTER("Event_timed::update_time_fields"); 01230 01231 DBUG_PRINT("enter", ("name: %*s", name.length, name.str)); 01232 01233 /* No need to update if nothing has changed */ 01234 if (!(status_changed || last_executed_changed)) 01235 DBUG_RETURN(0); 01236 01237 thd->reset_n_backup_open_tables_state(&backup); 01238 01239 if (Events::open_event_table(thd, TL_WRITE, &table)) 01240 { 01241 ret= EVEX_OPEN_TABLE_FAILED; 01242 goto done; 01243 } 01244 01245 01246 if ((ret= evex_db_find_event_by_name(thd, dbname, name, table))) 01247 goto done; 01248 01249 store_record(table,record[1]); 01250 /* Don't update create on row update. */ 01251 table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET; 01252 01253 if (last_executed_changed) 01254 { 01255 table->field[Events::FIELD_LAST_EXECUTED]->set_notnull(); 01256 table->field[Events::FIELD_LAST_EXECUTED]->store_time(&last_executed, 01257 MYSQL_TIMESTAMP_DATETIME); 01258 last_executed_changed= false; 01259 } 01260 if (status_changed) 01261 { 01262 table->field[Events::FIELD_STATUS]->set_notnull(); 01263 table->field[Events::FIELD_STATUS]->store((longlong)status, true); 01264 status_changed= false; 01265 } 01266 01267 if ((table->file->ha_update_row(table->record[1],table->record[0]))) 01268 ret= EVEX_WRITE_ROW_FAILED; 01269 01270 done: 01271 close_thread_tables(thd); 01272 thd->restore_backup_open_tables_state(&backup); 01273 01274 DBUG_RETURN(ret); 01275 }
Here is the call graph for this function:

Here is the caller graph for this function:

Definition at line 76 of file event_timed.h.
Referenced by copy_event_to_schema_table(), db_create_event(), evex_fill_row(), get_create_event(), init(), init_body(), and load_from_row().
| const uchar* Event_timed::body_begin |
Definition at line 82 of file event_timed.h.
Referenced by copy_event_to_schema_table(), evex_fill_row(), get_create_event(), init(), init_comment(), and load_from_row().
pthread_cond_t Event_timed::COND_finished [private] |
Definition at line 54 of file event_timed.h.
Referenced by kill_thread(), and spawn_thread_finish().
Definition at line 93 of file event_timed.h.
Referenced by copy_event_to_schema_table(), and load_from_row().
Definition at line 74 of file event_timed.h.
Referenced by compile(), compute_next_execution_time(), copy_event_to_schema_table(), db_create_event(), db_update_event(), Event_scheduler::drop_matching_events(), event_timed_db_equal(), event_timed_identifier_equal(), event_worker_thread(), evex_db_find_event_aux(), evex_fill_row(), evex_print_warnings(), execute(), Event_scheduler::execute_top(), Event_scheduler::find_event(), init(), init_name(), Event_scheduler::load_events_from_db(), load_from_row(), Event_scheduler::load_named_event(), Event_scheduler::run(), spawn_now(), Event_scheduler::update_event(), and update_fields().
Definition at line 80 of file event_timed.h.
Referenced by compile(), compute_next_execution_time(), copy_event_to_schema_table(), db_update_event(), event_timed_definer_equal(), event_timed_identifier_equal(), event_worker_thread(), evex_fill_row(), init_definer(), load_from_row(), and spawn_now().
Definition at line 79 of file event_timed.h.
Referenced by compile(), event_worker_thread(), evex_print_warnings(), execute(), init(), init_definer(), and load_from_row().
Definition at line 78 of file event_timed.h.
Referenced by compile(), event_worker_thread(), evex_print_warnings(), execute(), init(), init_definer(), and load_from_row().
Definition at line 101 of file event_timed.h.
Referenced by compute_next_execution_time(), Event_scheduler::run(), and spawn_thread_finish().
Definition at line 84 of file event_timed.h.
Referenced by compute_next_execution_time(), copy_event_to_schema_table(), evex_fill_row(), init(), init_ends(), and load_from_row().
Definition at line 87 of file event_timed.h.
Referenced by compute_next_execution_time(), copy_event_to_schema_table(), evex_fill_row(), init(), init_ends(), init_execute_at(), and load_from_row().
Definition at line 85 of file event_timed.h.
Referenced by compute_next_execution_time(), copy_event_to_schema_table(), db_create_event(), evex_fill_row(), get_create_event(), init(), init_execute_at(), load_from_row(), Event_scheduler::run(), and spawn_now().
Definition at line 88 of file event_timed.h.
Referenced by compute_next_execution_time(), init(), init_execute_at(), load_from_row(), and spawn_now().
Definition at line 90 of file event_timed.h.
Referenced by compute_next_execution_time(), copy_event_to_schema_table(), db_create_event(), evex_fill_row(), execute(), get_create_event(), init_interval(), load_from_row(), and spawn_now().
Definition at line 103 of file event_timed.h.
Referenced by Event_scheduler::drop_event(), Event_scheduler::drop_matching_events(), Event_scheduler::execute_top(), spawn_now(), spawn_thread_finish(), and Event_scheduler::update_event().
my_bool Event_timed::in_spawned_thread [private] |
Definition at line 49 of file event_timed.h.
Referenced by kill_thread(), spawn_now(), and spawn_thread_finish().
Definition at line 91 of file event_timed.h.
Referenced by compute_next_execution_time(), copy_event_to_schema_table(), evex_fill_row(), get_create_event(), init_interval(), and load_from_row().
Definition at line 72 of file event_timed.h.
Referenced by compute_next_execution_time(), copy_event_to_schema_table(), init(), load_from_row(), mark_last_executed(), and update_fields().
bool Event_timed::last_executed_changed [private] |
Definition at line 57 of file event_timed.h.
Referenced by load_from_row(), mark_last_executed(), and update_fields().
pthread_mutex_t Event_timed::LOCK_running [private] |
Definition at line 53 of file event_timed.h.
Referenced by kill_thread(), and spawn_thread_finish().
ulong Event_timed::locked_by_thread_id [private] |
Definition at line 50 of file event_timed.h.
Definition at line 94 of file event_timed.h.
Referenced by copy_event_to_schema_table(), and load_from_row().
Definition at line 75 of file event_timed.h.
Referenced by compile(), compute_next_execution_time(), copy_event_to_schema_table(), Events::create_event(), db_create_event(), db_drop_event(), db_update_event(), Event_scheduler::drop_matching_events(), event_timed_identifier_equal(), event_timed_name_equal(), event_worker_thread(), evex_db_find_event_aux(), evex_fill_row(), evex_print_warnings(), execute(), Event_scheduler::execute_top(), Event_scheduler::find_event(), get_create_event(), init(), init_name(), Event_scheduler::load_events_from_db(), load_from_row(), Event_scheduler::load_named_event(), Event_scheduler::run(), Events::show_create_event(), spawn_now(), Events::update_event(), Event_scheduler::update_event(), and update_fields().
Definition at line 95 of file event_timed.h.
Referenced by compute_next_execution_time(), copy_event_to_schema_table(), evex_fill_row(), get_create_event(), and load_from_row().
my_bool Event_timed::running [private] |
Definition at line 98 of file event_timed.h.
Referenced by compile(), copy_event_to_schema_table(), init(), load_from_row(), and Events::show_create_event().
Definition at line 83 of file event_timed.h.
Referenced by compute_next_execution_time(), copy_event_to_schema_table(), evex_fill_row(), init(), init_ends(), init_starts(), and load_from_row().
Definition at line 86 of file event_timed.h.
Referenced by compute_next_execution_time(), evex_fill_row(), init(), init_ends(), init_execute_at(), init_starts(), and load_from_row().
Definition at line 96 of file event_timed.h.
Referenced by compute_next_execution_time(), copy_event_to_schema_table(), evex_fill_row(), Event_scheduler::execute_top(), get_create_event(), Event_scheduler::load_events_from_db(), load_from_row(), Event_scheduler::load_named_event(), Event_scheduler::run(), spawn_now(), and update_fields().
bool Event_timed::status_changed [private] |
Definition at line 56 of file event_timed.h.
Referenced by compute_next_execution_time(), and update_fields().
ulong Event_timed::thread_id [private] |
Definition at line 52 of file event_timed.h.
Referenced by kill_thread(), set_thread_id(), and spawn_thread_finish().
1.4.7

