WL #3337 (Events new architecture)
Final stroke, events should be loaded from disk on server startup. Also check the validity of their bodies if possible during loading. sql/event_data_objects.cc: Remove Event_job_data::free_sp(), move the code to the destructor Change the way we change the security context Steal some code from sql_parse.cc sql/event_data_objects.h: Remove free_sp() Make compile() public, to be used when booting for verifying the integrity of mysql.event sql/event_queue.cc: Make the queue load events from disk on server boot. Compile and thus check for integrity the events. sql/event_queue.h: shift methods around. add queue_loaded boolean. sql/event_scheduler.cc: Rename init_event_thread() to pre_init_event_thread() and make it more generic. Add post_init_event_thread() Export these two as well as deinit_event_thread(). Now it is quite easy to write code to spawn a new event thread whenever needed. sql/event_scheduler.h: export pre_init_event_thread(), post_init_event_thread() and deinit_event_thread() to simplify writing of thread functions. sql/events.cc: Events::init() returns only one error code, then make it bool sql/events.h: Events::init() returns only one error code, then make it bool sql/mysqld.cc: Check the return code of Events::init() sql/sp_head.cc: Add trace info sql/sql_class.cc: Reorganize thd::change_security_context() to load main_security_ctx sql/sql_class.h: Reorganize thd::change_security_context() to load main_security_ctx sql/sql_lex.cc: Initialize lex->spname sql/sql_yacc.yy: Add a comment
This commit is contained in:
parent
628be8a716
commit
31caa8c433
10
mysql-test/r/events_restart_phase1.result
Normal file
10
mysql-test/r/events_restart_phase1.result
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
create database if not exists mysqltest_events_test;
|
||||||
|
use mysqltest_events_test;
|
||||||
|
set global event_scheduler=2;
|
||||||
|
create table execution_log(name char(10));
|
||||||
|
create event abc1 on schedule every 1 second do insert into execution_log value('abc1');
|
||||||
|
create event abc2 on schedule every 1 second do insert into execution_log value('abc2');
|
||||||
|
create event abc3 on schedule every 1 second do insert into execution_log value('abc3');
|
||||||
|
insert into mysql.event values ('db1','bad','select 42','root@localhost',NULL,1000,'MICROSECOND','2006-05-05 17:39:11','2006-05-05 17:39:20','2016-05-05 15:39:24','2016-05-05 15:39:11',NULL,'ENABLED','DROP','','comment1');
|
||||||
|
insert into mysql.event values ('db1','bad2','sect','root@localhost',NULL,1000,'SECOND','2006-05-05 17:39:11','2006-05-05 17:39:20','2016-05-05 15:39:24','2016-05-05 15:39:11',NULL,'ENABLED','DROP','','comment2');
|
||||||
|
"Now we restart the server"
|
6
mysql-test/r/events_restart_phase2.result
Normal file
6
mysql-test/r/events_restart_phase2.result
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
use mysqltest_events_test;
|
||||||
|
"Should get 0 rows because the queue aborted run
|
||||||
|
select distinct name from execution_log order by name;
|
||||||
|
name
|
||||||
|
delete from mysql.event where name like 'bad%';
|
||||||
|
"Now restart the server again"
|
9
mysql-test/r/events_restart_phase3.result
Normal file
9
mysql-test/r/events_restart_phase3.result
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
use mysqltest_events_test;
|
||||||
|
"Should get 3 rows : abc1, abc2, abc3
|
||||||
|
select distinct name from execution_log order by name;
|
||||||
|
name
|
||||||
|
drop event abc1;
|
||||||
|
drop event abc2;
|
||||||
|
drop event abc3;
|
||||||
|
drop table execution_log;
|
||||||
|
drop database mysqltest_events_test;
|
17
mysql-test/t/events_restart_phase1.test
Normal file
17
mysql-test/t/events_restart_phase1.test
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# Can't test with embedded server that doesn't support grants
|
||||||
|
-- source include/not_embedded.inc
|
||||||
|
|
||||||
|
--disable_warnings
|
||||||
|
create database if not exists mysqltest_events_test;
|
||||||
|
--enable_warnings
|
||||||
|
|
||||||
|
use mysqltest_events_test;
|
||||||
|
set global event_scheduler=2;
|
||||||
|
create table execution_log(name char(10));
|
||||||
|
create event abc1 on schedule every 1 second do insert into execution_log value('abc1');
|
||||||
|
create event abc2 on schedule every 1 second do insert into execution_log value('abc2');
|
||||||
|
create event abc3 on schedule every 1 second do insert into execution_log value('abc3');
|
||||||
|
|
||||||
|
insert into mysql.event values ('db1','bad','select 42','root@localhost',NULL,1000,'MICROSECOND','2006-05-05 17:39:11','2006-05-05 17:39:20','2016-05-05 15:39:24','2016-05-05 15:39:11',NULL,'ENABLED','DROP','','comment1');
|
||||||
|
insert into mysql.event values ('db1','bad2','sect','root@localhost',NULL,1000,'SECOND','2006-05-05 17:39:11','2006-05-05 17:39:20','2016-05-05 15:39:24','2016-05-05 15:39:11',NULL,'ENABLED','DROP','','comment2');
|
||||||
|
--echo "Now we restart the server"
|
1
mysql-test/t/events_restart_phase2-master.opt
Normal file
1
mysql-test/t/events_restart_phase2-master.opt
Normal file
@ -0,0 +1 @@
|
|||||||
|
--event-scheduler=1
|
9
mysql-test/t/events_restart_phase2.test
Normal file
9
mysql-test/t/events_restart_phase2.test
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
# Can't test with embedded server that doesn't support grants
|
||||||
|
-- source include/not_embedded.inc
|
||||||
|
|
||||||
|
use mysqltest_events_test;
|
||||||
|
--sleep 1.5
|
||||||
|
--echo "Should get 0 rows because the queue aborted run
|
||||||
|
select distinct name from execution_log order by name;
|
||||||
|
delete from mysql.event where name like 'bad%';
|
||||||
|
--echo "Now restart the server again"
|
1
mysql-test/t/events_restart_phase3-master.opt
Normal file
1
mysql-test/t/events_restart_phase3-master.opt
Normal file
@ -0,0 +1 @@
|
|||||||
|
--event-scheduler=1
|
14
mysql-test/t/events_restart_phase3.test
Normal file
14
mysql-test/t/events_restart_phase3.test
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
# Can't test with embedded server that doesn't support grants
|
||||||
|
-- source include/not_embedded.inc
|
||||||
|
|
||||||
|
use mysqltest_events_test;
|
||||||
|
--sleep 2
|
||||||
|
--echo "Should get 3 rows : abc1, abc2, abc3
|
||||||
|
select distinct name from execution_log order by name;
|
||||||
|
|
||||||
|
drop event abc1;
|
||||||
|
drop event abc2;
|
||||||
|
drop event abc3;
|
||||||
|
drop table execution_log;
|
||||||
|
|
||||||
|
drop database mysqltest_events_test;
|
@ -731,7 +731,7 @@ Event_timed::~Event_timed()
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
Event_job_data::Event_job_data():
|
Event_job_data::Event_job_data():
|
||||||
thd(NULL), sphead(0), sql_mode(0)
|
thd(NULL), sphead(NULL), sql_mode(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -745,7 +745,10 @@ Event_job_data::Event_job_data():
|
|||||||
|
|
||||||
Event_job_data::~Event_job_data()
|
Event_job_data::~Event_job_data()
|
||||||
{
|
{
|
||||||
free_sp();
|
DBUG_ENTER("Event_job_data::~Event_job_data");
|
||||||
|
delete sphead;
|
||||||
|
sphead= NULL;
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -1605,20 +1608,6 @@ Event_job_data::get_fake_create_event(THD *thd, String *buf)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
|
||||||
Frees the memory of the sp_head object we hold
|
|
||||||
SYNOPSIS
|
|
||||||
Event_job_data::free_sp()
|
|
||||||
*/
|
|
||||||
|
|
||||||
void
|
|
||||||
Event_job_data::free_sp()
|
|
||||||
{
|
|
||||||
delete sphead;
|
|
||||||
sphead= NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Compiles an event before it's execution. Compiles the anonymous
|
Compiles an event before it's execution. Compiles the anonymous
|
||||||
sp_head object held by the event
|
sp_head object held by the event
|
||||||
@ -1651,9 +1640,7 @@ Event_job_data::compile(THD *thd, MEM_ROOT *mem_root)
|
|||||||
CHARSET_INFO *old_character_set_client,
|
CHARSET_INFO *old_character_set_client,
|
||||||
*old_collation_connection,
|
*old_collation_connection,
|
||||||
*old_character_set_results;
|
*old_character_set_results;
|
||||||
Security_context *save_ctx;
|
Security_context save_ctx;
|
||||||
/* this one is local and not needed after exec */
|
|
||||||
Security_context security_ctx;
|
|
||||||
|
|
||||||
DBUG_ENTER("Event_job_data::compile");
|
DBUG_ENTER("Event_job_data::compile");
|
||||||
|
|
||||||
@ -1699,10 +1686,9 @@ Event_job_data::compile(THD *thd, MEM_ROOT *mem_root)
|
|||||||
thd->query_length= show_create.length();
|
thd->query_length= show_create.length();
|
||||||
DBUG_PRINT("info", ("query:%s",thd->query));
|
DBUG_PRINT("info", ("query:%s",thd->query));
|
||||||
|
|
||||||
thd->change_security_context(definer_user, definer_host, dbname,
|
thd->change_security_context(definer_user, definer_host, dbname, &save_ctx);
|
||||||
&security_ctx, &save_ctx);
|
|
||||||
thd->lex= &lex;
|
thd->lex= &lex;
|
||||||
lex_start(thd, (uchar*)thd->query, thd->query_length);
|
mysql_init_query(thd, (uchar*) thd->query, thd->query_length);
|
||||||
if (MYSQLparse((void *)thd) || thd->is_fatal_error)
|
if (MYSQLparse((void *)thd) || thd->is_fatal_error)
|
||||||
{
|
{
|
||||||
DBUG_PRINT("error", ("error during compile or thd->is_fatal_error=%d",
|
DBUG_PRINT("error", ("error during compile or thd->is_fatal_error=%d",
|
||||||
@ -1713,13 +1699,10 @@ Event_job_data::compile(THD *thd, MEM_ROOT *mem_root)
|
|||||||
*/
|
*/
|
||||||
sql_print_error("error during compile of %s.%s or thd->is_fatal_error=%d",
|
sql_print_error("error during compile of %s.%s or thd->is_fatal_error=%d",
|
||||||
dbname.str, name.str, thd->is_fatal_error);
|
dbname.str, name.str, thd->is_fatal_error);
|
||||||
if (lex.sphead)
|
|
||||||
{
|
lex.unit.cleanup();
|
||||||
if (&lex != thd->lex)
|
|
||||||
thd->lex->sphead->restore_lex(thd);
|
|
||||||
delete lex.sphead;
|
delete lex.sphead;
|
||||||
lex.sphead= 0;
|
sphead= lex.sphead= NULL;
|
||||||
}
|
|
||||||
ret= EVEX_COMPILE_ERROR;
|
ret= EVEX_COMPILE_ERROR;
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@ -1734,7 +1717,7 @@ Event_job_data::compile(THD *thd, MEM_ROOT *mem_root)
|
|||||||
done:
|
done:
|
||||||
|
|
||||||
lex_end(&lex);
|
lex_end(&lex);
|
||||||
thd->restore_security_context(save_ctx);
|
thd->restore_security_context(&save_ctx);
|
||||||
DBUG_PRINT("note", ("return old data on its place. set back NAMES"));
|
DBUG_PRINT("note", ("return old data on its place. set back NAMES"));
|
||||||
|
|
||||||
thd->lex= old_lex;
|
thd->lex= old_lex;
|
||||||
@ -1772,20 +1755,17 @@ done:
|
|||||||
int
|
int
|
||||||
Event_job_data::execute(THD *thd)
|
Event_job_data::execute(THD *thd)
|
||||||
{
|
{
|
||||||
Security_context *save_ctx;
|
Security_context save_ctx;
|
||||||
/* this one is local and not needed after exec */
|
/* this one is local and not needed after exec */
|
||||||
Security_context security_ctx;
|
|
||||||
int ret= 0;
|
int ret= 0;
|
||||||
|
|
||||||
DBUG_ENTER("Event_job_data::execute");
|
DBUG_ENTER("Event_job_data::execute");
|
||||||
DBUG_PRINT("info", ("EXECUTING %s.%s", dbname.str, name.str));
|
DBUG_PRINT("info", ("EXECUTING %s.%s", dbname.str, name.str));
|
||||||
|
|
||||||
|
|
||||||
if ((ret= compile(thd, NULL)))
|
if ((ret= compile(thd, NULL)))
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
thd->change_security_context(definer_user, definer_host, dbname,
|
thd->change_security_context(definer_user, definer_host, dbname, &save_ctx);
|
||||||
&security_ctx, &save_ctx);
|
|
||||||
/*
|
/*
|
||||||
THD::~THD will clean this or if there is DROP DATABASE in the SP then
|
THD::~THD will clean this or if there is DROP DATABASE in the SP then
|
||||||
it will be free there. It should not point to our buffer which is allocated
|
it will be free there. It should not point to our buffer which is allocated
|
||||||
@ -1810,9 +1790,10 @@ Event_job_data::execute(THD *thd)
|
|||||||
ret= -99;
|
ret= -99;
|
||||||
}
|
}
|
||||||
|
|
||||||
thd->restore_security_context(save_ctx);
|
thd->restore_security_context(&save_ctx);
|
||||||
done:
|
done:
|
||||||
free_sp();
|
thd->end_statement();
|
||||||
|
thd->cleanup_after_query();
|
||||||
|
|
||||||
DBUG_PRINT("info", ("EXECUTED %s.%s ret=%d", dbname.str, name.str, ret));
|
DBUG_PRINT("info", ("EXECUTED %s.%s ret=%d", dbname.str, name.str, ret));
|
||||||
|
|
||||||
|
@ -178,15 +178,12 @@ public:
|
|||||||
|
|
||||||
int
|
int
|
||||||
execute(THD *thd);
|
execute(THD *thd);
|
||||||
private:
|
|
||||||
int
|
|
||||||
get_fake_create_event(THD *thd, String *buf);
|
|
||||||
|
|
||||||
int
|
int
|
||||||
compile(THD *thd, MEM_ROOT *mem_root);
|
compile(THD *thd, MEM_ROOT *mem_root);
|
||||||
|
private:
|
||||||
void
|
int
|
||||||
free_sp();
|
get_fake_create_event(THD *thd, String *buf);
|
||||||
|
|
||||||
Event_job_data(const Event_job_data &); /* Prevent use of these */
|
Event_job_data(const Event_job_data &); /* Prevent use of these */
|
||||||
void operator=(Event_job_data &);
|
void operator=(Event_job_data &);
|
||||||
|
@ -35,6 +35,14 @@
|
|||||||
#define LOCK_QUEUE_DATA() lock_data(SCHED_FUNC, __LINE__)
|
#define LOCK_QUEUE_DATA() lock_data(SCHED_FUNC, __LINE__)
|
||||||
#define UNLOCK_QUEUE_DATA() unlock_data(SCHED_FUNC, __LINE__)
|
#define UNLOCK_QUEUE_DATA() unlock_data(SCHED_FUNC, __LINE__)
|
||||||
|
|
||||||
|
struct event_queue_param
|
||||||
|
{
|
||||||
|
THD *thd;
|
||||||
|
Event_queue *queue;
|
||||||
|
pthread_mutex_t LOCK_loaded;
|
||||||
|
pthread_cond_t COND_loaded;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Compares the execute_at members of two Event_queue_element instances.
|
Compares the execute_at members of two Event_queue_element instances.
|
||||||
@ -64,6 +72,31 @@ event_queue_element_compare_q(void *vptr, byte* a, byte *b)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pthread_handler_t
|
||||||
|
event_queue_loader_thread(void *arg)
|
||||||
|
{
|
||||||
|
/* needs to be first for thread_stack */
|
||||||
|
THD *thd= (THD *)((struct event_queue_param *) arg)->thd;
|
||||||
|
struct event_queue_param *param= (struct event_queue_param *) arg;
|
||||||
|
thd->thread_stack= (char *) &thd;
|
||||||
|
|
||||||
|
if (post_init_event_thread(thd))
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
DBUG_ENTER("event_queue_loader_thread");
|
||||||
|
|
||||||
|
pthread_mutex_lock(¶m->LOCK_loaded);
|
||||||
|
param->queue->load_events_from_db(thd);
|
||||||
|
pthread_cond_signal(¶m->COND_loaded);
|
||||||
|
pthread_mutex_unlock(¶m->LOCK_loaded);
|
||||||
|
|
||||||
|
end:
|
||||||
|
deinit_event_thread(thd);
|
||||||
|
|
||||||
|
DBUG_RETURN(0); // Against gcc warnings
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Constructor of class Event_queue.
|
Constructor of class Event_queue.
|
||||||
|
|
||||||
@ -80,6 +113,8 @@ Event_queue::Event_queue()
|
|||||||
mutex_last_attempted_lock_in_func= "";
|
mutex_last_attempted_lock_in_func= "";
|
||||||
|
|
||||||
mutex_queue_data_locked= mutex_queue_data_attempting_lock= FALSE;
|
mutex_queue_data_locked= mutex_queue_data_attempting_lock= FALSE;
|
||||||
|
|
||||||
|
queue_loaded= FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -125,8 +160,11 @@ Event_queue::deinit_mutexes()
|
|||||||
bool
|
bool
|
||||||
Event_queue::init_queue(Event_db_repository *db_repo, Event_scheduler *sched)
|
Event_queue::init_queue(Event_db_repository *db_repo, Event_scheduler *sched)
|
||||||
{
|
{
|
||||||
int i= 0;
|
THD *new_thd;
|
||||||
bool ret= FALSE;
|
pthread_t th;
|
||||||
|
bool res;
|
||||||
|
struct event_queue_param *event_queue_param_value= NULL;
|
||||||
|
|
||||||
DBUG_ENTER("Event_queue::init_queue");
|
DBUG_ENTER("Event_queue::init_queue");
|
||||||
DBUG_PRINT("enter", ("this=0x%lx", this));
|
DBUG_PRINT("enter", ("this=0x%lx", this));
|
||||||
|
|
||||||
@ -139,8 +177,7 @@ Event_queue::init_queue(Event_db_repository *db_repo, Event_scheduler *sched)
|
|||||||
NULL, EVENT_QUEUE_EXTENT))
|
NULL, EVENT_QUEUE_EXTENT))
|
||||||
{
|
{
|
||||||
sql_print_error("SCHEDULER: Can't initialize the execution queue");
|
sql_print_error("SCHEDULER: Can't initialize the execution queue");
|
||||||
ret= TRUE;
|
goto err;
|
||||||
goto end;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sizeof(my_time_t) != sizeof(time_t))
|
if (sizeof(my_time_t) != sizeof(time_t))
|
||||||
@ -148,13 +185,43 @@ Event_queue::init_queue(Event_db_repository *db_repo, Event_scheduler *sched)
|
|||||||
sql_print_error("SCHEDULER: sizeof(my_time_t) != sizeof(time_t) ."
|
sql_print_error("SCHEDULER: sizeof(my_time_t) != sizeof(time_t) ."
|
||||||
"The scheduler may not work correctly. Stopping.");
|
"The scheduler may not work correctly. Stopping.");
|
||||||
DBUG_ASSERT(0);
|
DBUG_ASSERT(0);
|
||||||
ret= TRUE;
|
goto err;
|
||||||
goto end;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
if (!(new_thd= new THD))
|
||||||
|
goto err;
|
||||||
|
|
||||||
|
pre_init_event_thread(new_thd);
|
||||||
|
|
||||||
|
event_queue_param_value= (struct event_queue_param *)
|
||||||
|
my_malloc(sizeof(struct event_queue_param), MYF(0));
|
||||||
|
event_queue_param_value->thd= new_thd;
|
||||||
|
event_queue_param_value->queue= this;
|
||||||
|
pthread_mutex_init(&event_queue_param_value->LOCK_loaded, MY_MUTEX_INIT_FAST);
|
||||||
|
pthread_cond_init(&event_queue_param_value->COND_loaded, NULL);
|
||||||
|
|
||||||
|
pthread_mutex_lock(&event_queue_param_value->LOCK_loaded);
|
||||||
|
DBUG_PRINT("info", ("Forking new thread for scheduduler. THD=0x%lx", new_thd));
|
||||||
|
if (!(res= pthread_create(&th, &connection_attrib, event_queue_loader_thread,
|
||||||
|
(void*)event_queue_param_value)))
|
||||||
|
{
|
||||||
|
do {
|
||||||
|
pthread_cond_wait(&event_queue_param_value->COND_loaded,
|
||||||
|
&event_queue_param_value->LOCK_loaded);
|
||||||
|
} while (queue_loaded == FALSE);
|
||||||
|
}
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&event_queue_param_value->LOCK_loaded);
|
||||||
|
pthread_mutex_destroy(&event_queue_param_value->LOCK_loaded);
|
||||||
|
pthread_cond_destroy(&event_queue_param_value->COND_loaded);
|
||||||
|
my_free((char *)event_queue_param_value, MYF(0));
|
||||||
|
|
||||||
UNLOCK_QUEUE_DATA();
|
UNLOCK_QUEUE_DATA();
|
||||||
DBUG_RETURN(ret);
|
DBUG_RETURN(res);
|
||||||
|
|
||||||
|
err:
|
||||||
|
UNLOCK_QUEUE_DATA();
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -498,7 +565,7 @@ Event_queue::load_events_from_db(THD *thd)
|
|||||||
READ_RECORD read_record_info;
|
READ_RECORD read_record_info;
|
||||||
int ret= -1;
|
int ret= -1;
|
||||||
uint count= 0;
|
uint count= 0;
|
||||||
bool clean_the_queue= FALSE;
|
bool clean_the_queue= TRUE;
|
||||||
/* Compile the events on this root but only for syntax check, then discard */
|
/* Compile the events on this root but only for syntax check, then discard */
|
||||||
MEM_ROOT boot_root;
|
MEM_ROOT boot_root;
|
||||||
|
|
||||||
@ -518,14 +585,12 @@ Event_queue::load_events_from_db(THD *thd)
|
|||||||
if (!(et= new Event_queue_element))
|
if (!(et= new Event_queue_element))
|
||||||
{
|
{
|
||||||
DBUG_PRINT("info", ("Out of memory"));
|
DBUG_PRINT("info", ("Out of memory"));
|
||||||
clean_the_queue= TRUE;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
DBUG_PRINT("info", ("Loading event from row."));
|
DBUG_PRINT("info", ("Loading event from row."));
|
||||||
|
|
||||||
if ((ret= et->load_from_row(table)))
|
if ((ret= et->load_from_row(table)))
|
||||||
{
|
{
|
||||||
clean_the_queue= TRUE;
|
|
||||||
sql_print_error("SCHEDULER: Error while loading from mysql.event. "
|
sql_print_error("SCHEDULER: Error while loading from mysql.event. "
|
||||||
"Table probably corrupted");
|
"Table probably corrupted");
|
||||||
break;
|
break;
|
||||||
@ -536,27 +601,6 @@ Event_queue::load_events_from_db(THD *thd)
|
|||||||
delete et;
|
delete et;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#if 0
|
|
||||||
init_alloc_root(&boot_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
|
|
||||||
DBUG_PRINT("info", ("Event %s loaded from row. ", et->name.str));
|
|
||||||
|
|
||||||
/* We load only on scheduler root just to check whether the body compiles */
|
|
||||||
switch (ret= et->compile(thd, &boot_root)) {
|
|
||||||
case EVEX_MICROSECOND_UNSUP:
|
|
||||||
et->free_sp();
|
|
||||||
sql_print_error("SCHEDULER: mysql.event is tampered. MICROSECOND is not "
|
|
||||||
"supported but found in mysql.event");
|
|
||||||
goto end;
|
|
||||||
case EVEX_COMPILE_ERROR:
|
|
||||||
sql_print_error("SCHEDULER: Error while compiling %s.%s. Aborting load.",
|
|
||||||
et->dbname.str, et->name.str);
|
|
||||||
goto end;
|
|
||||||
default:
|
|
||||||
/* Free it, it will be compiled again on the worker thread */
|
|
||||||
et->free_sp();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
free_root(&boot_root, MYF(0));
|
|
||||||
|
|
||||||
/* let's find when to be executed */
|
/* let's find when to be executed */
|
||||||
if (et->compute_next_execution_time())
|
if (et->compute_next_execution_time())
|
||||||
@ -565,11 +609,40 @@ Event_queue::load_events_from_db(THD *thd)
|
|||||||
" Skipping", et->dbname.str, et->name.str);
|
" Skipping", et->dbname.str, et->name.str);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
|
{
|
||||||
|
Event_job_data temp_job_data;
|
||||||
|
DBUG_PRINT("info", ("Event %s loaded from row. ", et->name.str));
|
||||||
|
|
||||||
|
temp_job_data.load_from_row(table);
|
||||||
|
|
||||||
|
/* We load only on scheduler root just to check whether the body compiles */
|
||||||
|
switch (ret= temp_job_data.compile(thd, thd->mem_root)) {
|
||||||
|
case EVEX_MICROSECOND_UNSUP:
|
||||||
|
sql_print_error("SCHEDULER: mysql.event is tampered. MICROSECOND is not "
|
||||||
|
"supported but found in mysql.event");
|
||||||
|
break;
|
||||||
|
case EVEX_COMPILE_ERROR:
|
||||||
|
sql_print_error("SCHEDULER: Error while compiling %s.%s. Aborting load.",
|
||||||
|
et->dbname.str, et->name.str);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
thd->end_statement();
|
||||||
|
thd->cleanup_after_query();
|
||||||
|
}
|
||||||
|
if (ret)
|
||||||
|
{
|
||||||
|
delete et;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
DBUG_PRINT("load_events_from_db", ("Adding 0x%lx to the exec list."));
|
DBUG_PRINT("load_events_from_db", ("Adding 0x%lx to the exec list."));
|
||||||
queue_insert_safe(&queue, (byte *) et);
|
queue_insert_safe(&queue, (byte *) et);
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
clean_the_queue= FALSE;
|
||||||
end:
|
end:
|
||||||
end_read_record(&read_record_info);
|
end_read_record(&read_record_info);
|
||||||
|
|
||||||
@ -589,6 +662,8 @@ end:
|
|||||||
|
|
||||||
close_thread_tables(thd);
|
close_thread_tables(thd);
|
||||||
|
|
||||||
|
queue_loaded= TRUE;
|
||||||
|
|
||||||
DBUG_PRINT("info", ("Status code %d. Loaded %d event(s)", ret, count));
|
DBUG_PRINT("info", ("Status code %d. Loaded %d event(s)", ret, count));
|
||||||
DBUG_RETURN(ret);
|
DBUG_RETURN(ret);
|
||||||
}
|
}
|
||||||
@ -713,6 +788,7 @@ Event_queue::empty_queue()
|
|||||||
uint i;
|
uint i;
|
||||||
DBUG_ENTER("Event_queue::empty_queue");
|
DBUG_ENTER("Event_queue::empty_queue");
|
||||||
DBUG_PRINT("enter", ("Purging the queue. %d element(s)", queue.elements));
|
DBUG_PRINT("enter", ("Purging the queue. %d element(s)", queue.elements));
|
||||||
|
sql_print_information("SCHEDULER: Purging queue. %u events", queue.elements);
|
||||||
/* empty the queue */
|
/* empty the queue */
|
||||||
for (i= 0; i < queue.elements; ++i)
|
for (i= 0; i < queue.elements; ++i)
|
||||||
{
|
{
|
||||||
|
@ -68,12 +68,13 @@ public:
|
|||||||
bool
|
bool
|
||||||
dump_internal_status(THD *thd);
|
dump_internal_status(THD *thd);
|
||||||
|
|
||||||
|
int
|
||||||
|
load_events_from_db(THD *thd);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Event_queue_element *
|
Event_queue_element *
|
||||||
find_n_remove_event(LEX_STRING db, LEX_STRING name);
|
find_n_remove_event(LEX_STRING db, LEX_STRING name);
|
||||||
|
|
||||||
int
|
|
||||||
load_events_from_db(THD *thd);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
drop_matching_events(THD *thd, LEX_STRING pattern,
|
drop_matching_events(THD *thd, LEX_STRING pattern,
|
||||||
@ -82,11 +83,24 @@ protected:
|
|||||||
void
|
void
|
||||||
empty_queue();
|
empty_queue();
|
||||||
|
|
||||||
|
void
|
||||||
|
notify_observers();
|
||||||
|
|
||||||
|
void
|
||||||
|
dbug_dump_queue(time_t now);
|
||||||
|
|
||||||
/* LOCK_event_queue is the mutex which protects the access to the queue. */
|
/* LOCK_event_queue is the mutex which protects the access to the queue. */
|
||||||
pthread_mutex_t LOCK_event_queue;
|
pthread_mutex_t LOCK_event_queue;
|
||||||
|
|
||||||
Event_db_repository *db_repository;
|
Event_db_repository *db_repository;
|
||||||
|
|
||||||
|
Event_scheduler *scheduler;
|
||||||
|
|
||||||
|
/* The sorted queue with the Event_job_data objects */
|
||||||
|
QUEUE queue;
|
||||||
|
|
||||||
|
bool queue_loaded;
|
||||||
|
|
||||||
uint mutex_last_locked_at_line;
|
uint mutex_last_locked_at_line;
|
||||||
uint mutex_last_unlocked_at_line;
|
uint mutex_last_unlocked_at_line;
|
||||||
uint mutex_last_attempted_lock_at_line;
|
uint mutex_last_attempted_lock_at_line;
|
||||||
@ -102,17 +116,6 @@ protected:
|
|||||||
|
|
||||||
void
|
void
|
||||||
unlock_data(const char *func, uint line);
|
unlock_data(const char *func, uint line);
|
||||||
|
|
||||||
void
|
|
||||||
notify_observers();
|
|
||||||
|
|
||||||
void
|
|
||||||
dbug_dump_queue(time_t now);
|
|
||||||
|
|
||||||
Event_scheduler *scheduler;
|
|
||||||
|
|
||||||
/* The sorted queue with the Event_job_data objects */
|
|
||||||
QUEUE queue;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif /* _EVENT_QUEUE_H_ */
|
#endif /* _EVENT_QUEUE_H_ */
|
||||||
|
@ -40,9 +40,6 @@ struct scheduler_param
|
|||||||
Event_scheduler *scheduler;
|
Event_scheduler *scheduler;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct scheduler_param scheduler_param_value;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
static
|
static
|
||||||
LEX_STRING scheduler_states_names[] =
|
LEX_STRING scheduler_states_names[] =
|
||||||
@ -103,25 +100,23 @@ evex_print_warnings(THD *thd, Event_job_data *et)
|
|||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Inits an scheduler thread handler, both the main and a worker
|
Performs pre- pthread_create() initialisation of THD. Do this
|
||||||
|
in the thread that will pass THD to the child thread. In the
|
||||||
|
child thread call post_init_event_thread().
|
||||||
|
|
||||||
SYNOPSIS
|
SYNOPSIS
|
||||||
init_event_thread()
|
pre_init_event_thread()
|
||||||
thd - the THD of the thread. Has to be allocated by the caller.
|
thd The THD of the thread. Has to be allocated by the caller.
|
||||||
|
|
||||||
NOTES
|
NOTES
|
||||||
1. The host of the thead is my_localhost
|
1. The host of the thead is my_localhost
|
||||||
2. thd->net is initted with NULL - no communication.
|
2. thd->net is initted with NULL - no communication.
|
||||||
|
|
||||||
RETURN VALUE
|
|
||||||
0 OK
|
|
||||||
-1 Error
|
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static int
|
void
|
||||||
init_scheduler_thread(THD* thd)
|
pre_init_event_thread(THD* thd)
|
||||||
{
|
{
|
||||||
DBUG_ENTER("init_event_thread");
|
DBUG_ENTER("pre_init_event_thread");
|
||||||
thd->client_capabilities= 0;
|
thd->client_capabilities= 0;
|
||||||
thd->security_ctx->master_access= 0;
|
thd->security_ctx->master_access= 0;
|
||||||
thd->security_ctx->db_access= 0;
|
thd->security_ctx->db_access= 0;
|
||||||
@ -148,7 +143,36 @@ init_scheduler_thread(THD* thd)
|
|||||||
thd->version= refresh_version;
|
thd->version= refresh_version;
|
||||||
thd->set_time();
|
thd->set_time();
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
DBUG_VOID_RETURN;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
Performs post initialization of structures in a new thread.
|
||||||
|
|
||||||
|
SYNOPSIS
|
||||||
|
post_init_event_thread()
|
||||||
|
thd Thread
|
||||||
|
*/
|
||||||
|
|
||||||
|
bool
|
||||||
|
post_init_event_thread(THD *thd)
|
||||||
|
{
|
||||||
|
my_thread_init();
|
||||||
|
pthread_detach_this_thread();
|
||||||
|
thd->real_id= pthread_self();
|
||||||
|
if (init_thr_lock() || thd->store_globals())
|
||||||
|
{
|
||||||
|
thd->cleanup();
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
|
||||||
|
sigset_t set;
|
||||||
|
VOID(sigemptyset(&set)); // Get mask in use
|
||||||
|
VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals));
|
||||||
|
#endif
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -160,7 +184,7 @@ init_scheduler_thread(THD* thd)
|
|||||||
thd Thread
|
thd Thread
|
||||||
*/
|
*/
|
||||||
|
|
||||||
static void
|
void
|
||||||
deinit_event_thread(THD *thd)
|
deinit_event_thread(THD *thd)
|
||||||
{
|
{
|
||||||
thd->proc_info= "Clearing";
|
thd->proc_info= "Clearing";
|
||||||
@ -192,29 +216,18 @@ pthread_handler_t
|
|||||||
event_scheduler_thread(void *arg)
|
event_scheduler_thread(void *arg)
|
||||||
{
|
{
|
||||||
/* needs to be first for thread_stack */
|
/* needs to be first for thread_stack */
|
||||||
THD *thd= (THD *)(*(struct scheduler_param *) arg).thd;
|
THD *thd= (THD *)((struct scheduler_param *) arg)->thd;
|
||||||
|
Event_scheduler *scheduler= ((struct scheduler_param *) arg)->scheduler;
|
||||||
|
|
||||||
|
my_free((char*)arg, MYF(0));
|
||||||
|
|
||||||
thd->thread_stack= (char *)&thd; // remember where our stack is
|
thd->thread_stack= (char *)&thd; // remember where our stack is
|
||||||
|
|
||||||
DBUG_ENTER("event_scheduler_thread");
|
DBUG_ENTER("event_scheduler_thread");
|
||||||
|
|
||||||
my_thread_init();
|
if (!post_init_event_thread(thd))
|
||||||
pthread_detach_this_thread();
|
scheduler->run(thd);
|
||||||
thd->real_id=pthread_self();
|
|
||||||
if (init_thr_lock() || thd->store_globals())
|
|
||||||
{
|
|
||||||
thd->cleanup();
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
|
|
||||||
sigset_t set;
|
|
||||||
VOID(sigemptyset(&set)); // Get mask in use
|
|
||||||
VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals));
|
|
||||||
#endif
|
|
||||||
|
|
||||||
((struct scheduler_param *) arg)->scheduler->run(thd);
|
|
||||||
|
|
||||||
end:
|
|
||||||
deinit_event_thread(thd);
|
deinit_event_thread(thd);
|
||||||
|
|
||||||
DBUG_RETURN(0); // Against gcc warnings
|
DBUG_RETURN(0); // Against gcc warnings
|
||||||
@ -242,27 +255,13 @@ event_worker_thread(void *arg)
|
|||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
thd= event->thd;
|
thd= event->thd;
|
||||||
thd->thread_stack= (char *) &thd;
|
|
||||||
|
|
||||||
|
|
||||||
my_thread_init();
|
|
||||||
pthread_detach_this_thread();
|
|
||||||
thd->real_id=pthread_self();
|
|
||||||
if (init_thr_lock() || thd->store_globals())
|
|
||||||
{
|
|
||||||
thd->cleanup();
|
|
||||||
goto end;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
#if !defined(__WIN__) && !defined(OS2) && !defined(__NETWARE__)
|
|
||||||
sigset_t set;
|
|
||||||
VOID(sigemptyset(&set)); // Get mask in use
|
|
||||||
VOID(pthread_sigmask(SIG_UNBLOCK, &set, &thd->block_signals));
|
|
||||||
#endif
|
|
||||||
thd->init_for_queries();
|
|
||||||
|
|
||||||
|
thd->thread_stack= (char *) &thd; // remember where our stack is
|
||||||
DBUG_ENTER("event_worker_thread");
|
DBUG_ENTER("event_worker_thread");
|
||||||
|
|
||||||
|
if (post_init_event_thread(thd))
|
||||||
|
goto end;
|
||||||
|
|
||||||
DBUG_PRINT("info", ("Baikonur, time is %d, BURAN reporting and operational."
|
DBUG_PRINT("info", ("Baikonur, time is %d, BURAN reporting and operational."
|
||||||
"THD=0x%lx", time(NULL), thd));
|
"THD=0x%lx", time(NULL), thd));
|
||||||
|
|
||||||
@ -375,6 +374,7 @@ Event_scheduler::start()
|
|||||||
THD *new_thd= NULL;
|
THD *new_thd= NULL;
|
||||||
bool ret= FALSE;
|
bool ret= FALSE;
|
||||||
pthread_t th;
|
pthread_t th;
|
||||||
|
struct scheduler_param *scheduler_param_value;
|
||||||
DBUG_ENTER("Event_scheduler::start");
|
DBUG_ENTER("Event_scheduler::start");
|
||||||
|
|
||||||
LOCK_SCHEDULER_DATA();
|
LOCK_SCHEDULER_DATA();
|
||||||
@ -382,21 +382,24 @@ Event_scheduler::start()
|
|||||||
if (state > INITIALIZED)
|
if (state > INITIALIZED)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
if (!(new_thd= new THD) || init_scheduler_thread(new_thd))
|
if (!(new_thd= new THD))
|
||||||
{
|
{
|
||||||
sql_print_error("SCHEDULER: Cannot init manager event thread.");
|
sql_print_error("SCHEDULER: Cannot init manager event thread.");
|
||||||
ret= TRUE;
|
ret= TRUE;
|
||||||
goto end;
|
goto end;
|
||||||
}
|
}
|
||||||
|
pre_init_event_thread(new_thd);
|
||||||
new_thd->system_thread= SYSTEM_THREAD_EVENT_SCHEDULER;
|
new_thd->system_thread= SYSTEM_THREAD_EVENT_SCHEDULER;
|
||||||
new_thd->command= COM_DAEMON;
|
new_thd->command= COM_DAEMON;
|
||||||
|
|
||||||
scheduler_param_value.thd= new_thd;
|
scheduler_param_value=
|
||||||
scheduler_param_value.scheduler= this;
|
(struct scheduler_param *)my_malloc(sizeof(struct scheduler_param), MYF(0));
|
||||||
|
scheduler_param_value->thd= new_thd;
|
||||||
|
scheduler_param_value->scheduler= this;
|
||||||
|
|
||||||
DBUG_PRINT("info", ("Forking new thread for scheduduler. THD=0x%lx", new_thd));
|
DBUG_PRINT("info", ("Forking new thread for scheduduler. THD=0x%lx", new_thd));
|
||||||
if (pthread_create(&th, &connection_attrib, event_scheduler_thread,
|
if (pthread_create(&th, &connection_attrib, event_scheduler_thread,
|
||||||
(void*)&scheduler_param_value))
|
(void*)scheduler_param_value))
|
||||||
{
|
{
|
||||||
DBUG_PRINT("error", ("cannot create a new thread"));
|
DBUG_PRINT("error", ("cannot create a new thread"));
|
||||||
state= INITIALIZED;
|
state= INITIALIZED;
|
||||||
@ -588,9 +591,10 @@ Event_scheduler::execute_top(THD *thd, Event_job_data *job_data)
|
|||||||
pthread_t th;
|
pthread_t th;
|
||||||
int res= 0;
|
int res= 0;
|
||||||
DBUG_ENTER("Event_scheduler::execute_top");
|
DBUG_ENTER("Event_scheduler::execute_top");
|
||||||
if (!(new_thd= new THD) || init_scheduler_thread(new_thd))
|
if (!(new_thd= new THD))
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
pre_init_event_thread(new_thd);
|
||||||
new_thd->system_thread= SYSTEM_THREAD_EVENT_WORKER;
|
new_thd->system_thread= SYSTEM_THREAD_EVENT_WORKER;
|
||||||
job_data->thd= new_thd;
|
job_data->thd= new_thd;
|
||||||
DBUG_PRINT("info", ("BURAN %s@%s ready for start t-3..2..1..0..ignition",
|
DBUG_PRINT("info", ("BURAN %s@%s ready for start t-3..2..1..0..ignition",
|
||||||
|
@ -19,6 +19,15 @@
|
|||||||
class Event_queue;
|
class Event_queue;
|
||||||
class Event_job_data;
|
class Event_job_data;
|
||||||
|
|
||||||
|
void
|
||||||
|
pre_init_event_thread(THD* thd);
|
||||||
|
|
||||||
|
bool
|
||||||
|
post_init_event_thread(THD* thd);
|
||||||
|
|
||||||
|
void
|
||||||
|
deinit_event_thread(THD *thd);
|
||||||
|
|
||||||
class Event_scheduler
|
class Event_scheduler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
@ -556,11 +556,16 @@ Events::fill_schema_events(THD *thd, TABLE_LIST *tables, COND * /* cond */)
|
|||||||
1 Error in case the scheduler can't start
|
1 Error in case the scheduler can't start
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int
|
bool
|
||||||
Events::init()
|
Events::init()
|
||||||
{
|
{
|
||||||
|
int res;
|
||||||
DBUG_ENTER("Events::init");
|
DBUG_ENTER("Events::init");
|
||||||
event_queue->init_queue(db_repository, scheduler);
|
if (event_queue->init_queue(db_repository, scheduler))
|
||||||
|
{
|
||||||
|
sql_print_information("SCHEDULER: Error while loading from disk.");
|
||||||
|
DBUG_RETURN(TRUE);
|
||||||
|
}
|
||||||
scheduler->init_scheduler(event_queue);
|
scheduler->init_scheduler(event_queue);
|
||||||
|
|
||||||
/* it should be an assignment! */
|
/* it should be an assignment! */
|
||||||
@ -571,7 +576,7 @@ Events::init()
|
|||||||
DBUG_RETURN(scheduler->start());
|
DBUG_RETURN(scheduler->start());
|
||||||
}
|
}
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ public:
|
|||||||
static ulong opt_event_scheduler;
|
static ulong opt_event_scheduler;
|
||||||
static TYPELIB opt_typelib;
|
static TYPELIB opt_typelib;
|
||||||
|
|
||||||
int
|
bool
|
||||||
init();
|
init();
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -3675,7 +3675,8 @@ we force server id to 2, but this MySQL server will not act as a slave.");
|
|||||||
|
|
||||||
if (!opt_noacl)
|
if (!opt_noacl)
|
||||||
{
|
{
|
||||||
Events::get_instance()->init();
|
if (Events::get_instance()->init())
|
||||||
|
unireg_abort(1);
|
||||||
}
|
}
|
||||||
#if defined(__NT__) || defined(HAVE_SMEM)
|
#if defined(__NT__) || defined(HAVE_SMEM)
|
||||||
handle_connections_methods();
|
handle_connections_methods();
|
||||||
|
@ -640,10 +640,12 @@ sp_head::create(THD *thd)
|
|||||||
|
|
||||||
sp_head::~sp_head()
|
sp_head::~sp_head()
|
||||||
{
|
{
|
||||||
|
DBUG_ENTER("sp_head::~sp_head");
|
||||||
destroy();
|
destroy();
|
||||||
delete m_next_cached_sp;
|
delete m_next_cached_sp;
|
||||||
if (m_thd)
|
if (m_thd)
|
||||||
restore_thd_mem_root(m_thd);
|
restore_thd_mem_root(m_thd);
|
||||||
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -2085,21 +2085,20 @@ bool Security_context::set_user(char *user_arg)
|
|||||||
|
|
||||||
bool
|
bool
|
||||||
THD::change_security_context(LEX_STRING user, LEX_STRING host,
|
THD::change_security_context(LEX_STRING user, LEX_STRING host,
|
||||||
LEX_STRING db, Security_context *s_ctx,
|
LEX_STRING db, Security_context *backup)
|
||||||
Security_context **backup)
|
|
||||||
{
|
{
|
||||||
DBUG_ENTER("change_security_context");
|
DBUG_ENTER("change_security_context");
|
||||||
DBUG_PRINT("info",("%s@%s@%s", user.str, host.str, db.str));
|
DBUG_PRINT("info",("%s@%s@%s", user.str, host.str, db.str));
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
s_ctx->init();
|
|
||||||
*backup= 0;
|
*backup= main_security_ctx;
|
||||||
if (acl_getroot_no_password(s_ctx, user.str, host.str, host.str, db.str))
|
if (acl_getroot_no_password(&main_security_ctx, user.str, host.str, host.str,
|
||||||
|
db.str))
|
||||||
{
|
{
|
||||||
my_error(ER_NO_SUCH_USER, MYF(0), user.str, host.str);
|
my_error(ER_NO_SUCH_USER, MYF(0), user.str, host.str);
|
||||||
DBUG_RETURN(TRUE);
|
DBUG_RETURN(TRUE);
|
||||||
}
|
}
|
||||||
*backup= security_ctx;
|
security_ctx= &main_security_ctx;
|
||||||
security_ctx= s_ctx;
|
|
||||||
#endif
|
#endif
|
||||||
DBUG_RETURN(FALSE);
|
DBUG_RETURN(FALSE);
|
||||||
}
|
}
|
||||||
@ -2119,7 +2118,10 @@ THD::restore_security_context(Security_context *backup)
|
|||||||
DBUG_ENTER("restore_security_context");
|
DBUG_ENTER("restore_security_context");
|
||||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||||
if (backup)
|
if (backup)
|
||||||
security_ctx= backup;
|
{
|
||||||
|
main_security_ctx= *backup;
|
||||||
|
security_ctx= &main_security_ctx;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
}
|
}
|
||||||
|
@ -871,8 +871,7 @@ public:
|
|||||||
|
|
||||||
bool
|
bool
|
||||||
change_security_context(LEX_STRING user, LEX_STRING host,
|
change_security_context(LEX_STRING user, LEX_STRING host,
|
||||||
LEX_STRING db, Security_context *s_ctx,
|
LEX_STRING db, Security_context *backup);
|
||||||
Security_context **backup);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
restore_security_context(Security_context *backup);
|
restore_security_context(Security_context *backup);
|
||||||
|
@ -171,6 +171,7 @@ void lex_start(THD *thd, const uchar *buf, uint length)
|
|||||||
lex->sql_command= SQLCOM_END;
|
lex->sql_command= SQLCOM_END;
|
||||||
lex->duplicates= DUP_ERROR;
|
lex->duplicates= DUP_ERROR;
|
||||||
lex->ignore= 0;
|
lex->ignore= 0;
|
||||||
|
lex->spname= NULL;
|
||||||
lex->sphead= NULL;
|
lex->sphead= NULL;
|
||||||
lex->spcont= NULL;
|
lex->spcont= NULL;
|
||||||
lex->proc_list.first= 0;
|
lex->proc_list.first= 0;
|
||||||
|
@ -4652,6 +4652,13 @@ alter:
|
|||||||
YYTHD->client_capabilities is set back to original value
|
YYTHD->client_capabilities is set back to original value
|
||||||
*/
|
*/
|
||||||
{
|
{
|
||||||
|
/*
|
||||||
|
It is safe to use Lex->spname because
|
||||||
|
ALTER EVENT xxx RENATE TO yyy DO ALTER EVENT RENAME TO
|
||||||
|
is not allowed. Lex->spname is used in the case of RENAME TO
|
||||||
|
If it had to be supported spname had to be added to
|
||||||
|
Event_parse_data.
|
||||||
|
*/
|
||||||
Lex->spname= NULL;
|
Lex->spname= NULL;
|
||||||
|
|
||||||
if (!(Lex->event_parse_data= Event_parse_data::new_instance(YYTHD)))
|
if (!(Lex->event_parse_data= Event_parse_data::new_instance(YYTHD)))
|
||||||
|
Loading…
x
Reference in New Issue
Block a user