Commit 533180d7 authored by andrey@lmy004's avatar andrey@lmy004

WL#1034 update

- fix EVENT_ACL problem that GRANT ALL on some_db.* to someone@somewhere did not get to mysql.db
- fix crash when the following is executed :
  CREATE EVENT P() CREATE EVENT E ON SCHEDULER 1 SECOND DO ROLLBACK;
  (creation works as well as calling P() which creates the event).
parent fd0613f5
......@@ -22,6 +22,7 @@ CREATE TABLE db (
Create_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
Alter_routine_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
Execute_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL,
PRIMARY KEY Host (Host,Db,User),
KEY User (User)
) engine=MyISAM
......@@ -29,8 +30,8 @@ CHARACTER SET utf8 COLLATE utf8_bin
comment='Database privileges';
INSERT INTO db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N');
INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N');
INSERT INTO db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y');
INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y','Y','Y','Y','N','N','Y');
CREATE TABLE host (
......@@ -570,26 +571,26 @@ CREATE TABLE proc (
CREATE TABLE event (
'db' VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
'name' VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
'body' longblob NOT NULL,
'definer' VARCHAR(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
'execute_at' DATETIME default NULL,
'transient_expression' int(11) default NULL,
'interval_type' ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK',
db VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
name VARCHAR(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
body longblob NOT NULL,
definer VARCHAR(77) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
execute_at DATETIME default NULL,
transient_expression int(11) default NULL,
interval_type ENUM('YEAR','QUARTER','MONTH','DAY','HOUR','MINUTE','WEEK',
'SECOND','MICROSECOND', 'YEAR_MONTH','DAY_HOUR',
'DAY_MINUTE','DAY_SECOND',
'HOUR_MINUTE','HOUR_SECOND',
'MINUTE_SECOND','DAY_MICROSECOND',
'HOUR_MICROSECOND','MINUTE_MICROSECOND',
'SECOND_MICROSECOND') default NULL,
'created' TIMESTAMP NOT NULL default '0000-00-00 00:00:00',
'modified' TIMESTAMP NOT NULL default '0000-00-00 00:00:00',
'last_executed' DATETIME default NULL,
'starts' DATETIME default NULL,
'ends' DATETIME default NULL,
'status' ENUM('ENABLED','DISABLED') NOT NULL default 'ENABLED',
'on_completion' ENUM('DROP','PRESERVE') NOT NULL default 'DROP',
'comment' varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
PRIMARY KEY ('db','name')
created TIMESTAMP NOT NULL,
modified TIMESTAMP NOT NULL,
last_executed DATETIME default NULL,
starts DATETIME default NULL,
ends DATETIME default NULL,
status ENUM('ENABLED','DISABLED') NOT NULL default 'ENABLED',
on_completion ENUM('DROP','PRESERVE') NOT NULL default 'DROP',
comment varchar(64) CHARACTER SET utf8 COLLATE utf8_bin NOT NULL default '',
PRIMARY KEY (db, name)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT 'Events';
use test;
drop event if exists event1;
Warnings:
Note 1305 Event event1 does not exist
create event event1 on schedule every 15 minute starts now() ends date_add(now(), interval 5 hour) DO begin end;
alter event event1 rename to event2;
alter event event2 disable;
drop event event2;
create event event2 on schedule every 2 second starts now() ends date_add(now(), interval 5 hour) comment "some" DO begin end;
drop event event2;
create table t_event3 (a int, b float);
drop event if exists event3;
Warnings:
Note 1305 Event event3 does not exist
create event event3 on schedule every 50 + 10 minute starts date_add("20010101", interval 5 minute) ends date_add("20151010", interval 5 day) comment "portokala_comment" DO insert into t_event3 values (unix_timestamp(), rand());
set max_allowed_packet=128000000;
select count(*) from t_event3;
count(*)
0
drop event event3;
drop table t_event3;
create database events_test;
use events_test;
use test;
drop event if exists event1;
create event event1 on schedule every 15 minute starts now() ends date_add(now(), interval 5 hour) DO begin end;
alter event event1 rename to event2;
......@@ -13,7 +12,6 @@ create table t_event3 (a int, b float);
drop event if exists event3;
create event event3 on schedule every 50 + 10 minute starts date_add("20010101", interval 5 minute) ends date_add("20151010", interval 5 day) comment "portokala_comment" DO insert into t_event3 values (unix_timestamp(), rand());
set max_allowed_packet=128000000;
select sha1(space(9999999));
select count(*) from t_event3;
drop event event3;
drop database events_test;
drop table t_event3;
......@@ -562,5 +562,6 @@ CREATE TABLE event (
# EVENT privilege
#
ALTER TABLE mysql.user add Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL AFTER Create_user_priv;
ALTER TABLE mysql.db add Event_priv enum('N','Y') COLLATE utf8_general_ci DEFAULT 'N' NOT NULL;
ALTER TABLE mysql.user add Event_priv enum('N','Y') character set utf8 DEFAULT 'N' NOT NULL AFTER Create_user_priv;
ALTER TABLE mysql.db add Event_priv enum('N','Y') character set utf8 DEFAULT 'N' NOT NULL;
......@@ -652,6 +652,7 @@ evex_load_and_compile_event(THD * thd, sp_name *spn, bool use_lock)
int ret= 0;
MEM_ROOT *tmp_mem_root;
event_timed *ett;
Open_tables_state backup;
DBUG_ENTER("db_load_and_compile_event");
DBUG_PRINT("enter", ("name: %*s", spn->m_name.length, spn->m_name.str));
......@@ -659,10 +660,12 @@ evex_load_and_compile_event(THD * thd, sp_name *spn, bool use_lock)
tmp_mem_root= thd->mem_root;
thd->mem_root= &evex_mem_root;
thd->reset_n_backup_open_tables_state(&backup);
// no need to use my_error() here because db_find_event() has done it
if ((ret= db_find_event(thd, spn, &ett, NULL)))
goto done;
thd->restore_backup_open_tables_state(&backup);
/*
allocate on evex_mem_root. if you call without evex_mem_root
then sphead will not be cleared!
......
......@@ -30,7 +30,7 @@
#define DBUG_FAULTY_THR2
extern ulong thread_created;
extern const char *my_localhost;
pthread_mutex_t LOCK_event_arrays,
LOCK_workers_count,
......@@ -125,6 +125,7 @@ init_event_thread(THD* thd)
DBUG_ENTER("init_event_thread");
thd->client_capabilities= 0;
thd->security_ctx->skip_grants();
thd->security_ctx->host= (char*)my_localhost;
my_net_init(&thd->net, 0);
thd->net.read_timeout = slave_net_timeout;
thd->slave_thread= 0;
......@@ -211,6 +212,7 @@ event_executor_main(void *arg)
if (evex_load_events_from_db(thd))
goto err;
thd->security_ctx->user= my_strdup("event_scheduler", MYF(0));
THD_CHECK_SENTRY(thd);
/* Read queries from the IO/THREAD until this thread is killed */
evex_main_thread_id= thd->thread_id;
......@@ -254,8 +256,8 @@ event_executor_main(void *arg)
VOID(pthread_mutex_unlock(&LOCK_event_arrays));
if (t2sleep > 0)
{
sql_print_information("Sleeping for %d seconds.", t2sleep);
printf("\nWHEN=%llu NOW=%llu\n", TIME_to_ulonglong_datetime(&et->execute_at), TIME_to_ulonglong_datetime(&time_now));
// sql_print_information("Sleeping for %d seconds.", t2sleep);
// printf("\nWHEN=%llu NOW=%llu\n", TIME_to_ulonglong_datetime(&et->execute_at), TIME_to_ulonglong_datetime(&time_now));
/*
We sleep t2sleep seconds but we check every second whether this thread
has been killed, or there is new candidate
......@@ -264,7 +266,7 @@ event_executor_main(void *arg)
evex_queue_num_elements(EVEX_EQ_NAME) &&
(evex_queue_first_element(&EVEX_EQ_NAME, event_timed*) == et))
my_sleep(1000000);
sql_print_information("Finished sleeping");
// sql_print_information("Finished sleeping");
}
if (!event_executor_running_global_var)
continue;
......@@ -297,9 +299,9 @@ event_executor_main(void *arg)
pthread_t th;
DBUG_PRINT("info", (" Spawning a thread %d", ++iter_num));
sql_print_information(" Spawning a thread %d", ++iter_num);
// sql_print_information(" Spawning a thread %d", ++iter_num);
#ifndef DBUG_FAULTY_THR
sql_print_information(" Thread is not debuggable!");
// sql_print_information(" Thread is not debuggable!");
if (pthread_create(&th, NULL, event_executor_worker, (void*)et))
{
sql_print_error("Problem while trying to create a thread");
......@@ -442,20 +444,18 @@ event_executor_worker(void *event_void)
strxnmov(thd->security_ctx->priv_host, sizeof(thd->security_ctx->priv_host),
event->definer_host.str, NullS);
thd->security_ctx->priv_user= event->definer_user.str;
thd->security_ctx->user= thd->security_ctx->priv_user= my_strdup(event->definer_user.str, MYF(0));
thd->db= event->dbname.str;
if (!check_access(thd, EVENT_ACL, event->dbname.str, 0, 0, 0,
is_schema_db(event->dbname.str)))
{
char exec_time[200];
int ret;
my_TIME_to_str(&event->execute_at, exec_time);
DBUG_PRINT("info", (" EVEX EXECUTING event for event %s.%s [EXPR:%d][EXECUTE_AT:%s]", event->dbname.str, event->name.str,(int) event->expression, exec_time));
sql_print_information(" EVEX EXECUTING event for event %s.%s [EXPR:%d][EXECUTE_AT:%s]", event->dbname.str, event->name.str,(int) event->expression, exec_time);
DBUG_PRINT("info", (" EVEX EXECUTING event for event %s.%s [EXPR:%d]", event->dbname.str, event->name.str,(int) event->expression));
sql_print_information(" EVEX EXECUTING event for event %s.%s [EXPR:%d]", event->dbname.str, event->name.str,(int) event->expression);
ret= event->execute(thd, &worker_mem_root);
sql_print_information(" EVEX EXECUTED event for event %s.%s [EXPR:%d][EXECUTE_AT:%s]. RetCode=%d", event->dbname.str, event->name.str,(int) event->expression, exec_time, ret);
DBUG_PRINT("info", (" EVEX EXECUTED event for event %s.%s [EXPR:%d][EXECUTE_AT:%s]", event->dbname.str, event->name.str,(int) event->expression, exec_time));
sql_print_information(" EVEX EXECUTED event for event %s.%s [EXPR:%d]. RetCode=%d", event->dbname.str, event->name.str,(int) event->expression, ret);
DBUG_PRINT("info", (" EVEX EXECUTED event for event %s.%s [EXPR:%d]. RetCode=%d", event->dbname.str, event->name.str,(int) event->expression, ret));
}
thd->db= 0;
......@@ -505,6 +505,7 @@ evex_load_events_from_db(THD *thd)
READ_RECORD read_record_info;
MYSQL_LOCK *lock;
int ret= -1;
uint count= 0;
DBUG_ENTER("evex_load_events_from_db");
......@@ -555,6 +556,7 @@ evex_load_events_from_db(THD *thd)
evex_queue_insert(&EVEX_EQ_NAME, (EVEX_PTOQEL) et);
DBUG_PRINT("evex_load_events_from_db", ("%p %*s",
et, et->name.length,et->name.str));
count++;
}
ret= 0;
......@@ -566,8 +568,8 @@ end:
thd->version--; // Force close to free memory
close_thread_tables(thd);
DBUG_PRINT("info", ("Finishing with status code %d", ret));
sql_print_information("Scheduler loaded %d events", count);
DBUG_PRINT("info", ("Finishing with status code %d. Loaded %d events", ret, count));
DBUG_RETURN(ret);
}
......
......@@ -807,7 +807,6 @@ event_timed::get_show_create_event(THD *thd, uint *length)
*length= len;
sql_print_information("%d %d[%s]", len, dst-ret, ret);
return ret;
}
......@@ -938,7 +937,7 @@ event_timed::compile(THD *thd, MEM_ROOT *mem_root)
goto done;
}
sphead= lex.sphead;
sphead= lex.et->sphead;
sphead->m_db= dbname;
//copy also chistics since they will vanish otherwise we get 0x0 pointer
// Todo : Handle sql_mode !!
......@@ -947,6 +946,7 @@ event_timed::compile(THD *thd, MEM_ROOT *mem_root)
sphead->optimize();
ret= 0;
done:
lex.et->free_sphead_on_delete= false;
delete lex.et;
lex_end(&lex);
thd->lex= old_lex;
......
......@@ -960,8 +960,12 @@ int sp_head::execute(THD *thd)
m_first_instance->m_first_free_instance= m_next_cached_sp;
DBUG_PRINT("info", ("first free for 0x%lx ++: 0x%lx->0x%lx, level: %lu, flags %x",
(ulong)m_first_instance, this, m_next_cached_sp,
m_next_cached_sp->m_recursion_level,
m_next_cached_sp->m_flags));
(m_next_cached_sp ?
m_next_cached_sp->m_recursion_level :
0),
(m_next_cached_sp ?
m_next_cached_sp->m_flags :
0)));
/*
Check that if there are not any instances after this one then
pointer to the last instance points on this instance or if there are
......
......@@ -97,17 +97,20 @@
#define DB_CHUNK3 (CREATE_VIEW_ACL | SHOW_VIEW_ACL | \
CREATE_PROC_ACL | ALTER_PROC_ACL )
#define DB_CHUNK4 (EXECUTE_ACL)
#define DB_CHUNK5 (EVENT_ACL)
#define fix_rights_for_db(A) (((A) & DB_CHUNK0) | \
(((A) << 4) & DB_CHUNK1) | \
(((A) << 6) & DB_CHUNK2) | \
(((A) << 9) & DB_CHUNK3) | \
(((A) << 2) & DB_CHUNK4))
(((A) << 2) & DB_CHUNK4))| \
(((A) << 9) & DB_CHUNK5)
#define get_rights_for_db(A) (((A) & DB_CHUNK0) | \
(((A) & DB_CHUNK1) >> 4) | \
(((A) & DB_CHUNK2) >> 6) | \
(((A) & DB_CHUNK3) >> 9) | \
(((A) & DB_CHUNK4) >> 2))
(((A) & DB_CHUNK4) >> 2))| \
(((A) & DB_CHUNK5) >> 9)
#define TBL_CHUNK0 DB_CHUNK0
#define TBL_CHUNK1 DB_CHUNK1
#define TBL_CHUNK2 (CREATE_VIEW_ACL | SHOW_VIEW_ACL)
......
......@@ -3704,10 +3704,9 @@ end_with_restore_list:
/* lex->unit.cleanup() is called outside, no need to call it here */
} while (0);
lex->et->free_sphead_on_delete= true;
delete lex->et;
delete lex->sphead;
lex->et= 0;
lex->sphead= 0;
break;
}
case SQLCOM_SHOW_CREATE_EVENT:
......@@ -5658,6 +5657,7 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
}
if (thd->lex->et)
{
thd->lex->et->free_sphead_on_delete= true;
delete thd->lex->et;
thd->lex->et= NULL;
}
......@@ -5698,6 +5698,7 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
}
if (thd->lex->et)
{
thd->lex->et->free_sphead_on_delete= true;
delete thd->lex->et;
thd->lex->et= NULL;
}
......
......@@ -109,6 +109,7 @@ inline Item *is_truth_value(Item *A, bool v1, bool v2)
struct { int vars, conds, hndlrs, curs; } spblock;
sp_name *spname;
struct st_lex *lex;
sp_head *sphead;
}
%{
......@@ -1345,8 +1346,6 @@ create:
if (!lex->et_compile_phase)
lex->et->init_name(YYTHD, $4);
lex->sphead= 0;//defensive programming
}
ON SCHEDULE_SYM ev_schedule_time
ev_on_completion
......@@ -1482,33 +1481,46 @@ ev_sql_stmt:
{
LEX *lex= Lex;
sp_head *sp;
if (!(sp= new sp_head()))
YYABORT;
$<sphead>$= lex->sphead;
if (!lex->sphead)
{
if (!(sp= new sp_head()))
YYABORT;
sp->reset_thd_mem_root(YYTHD);
sp->init(lex);
sp->reset_thd_mem_root(YYTHD);
sp->init(lex);
sp->m_type= TYPE_ENUM_PROCEDURE;
lex->sphead= sp;
sp->m_type= TYPE_ENUM_PROCEDURE;
lex->sphead= sp;
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
lex->sphead->m_chistics= &lex->sp_chistics;
bzero((char *)&lex->sp_chistics, sizeof(st_sp_chistics));
lex->sphead->m_chistics= &lex->sp_chistics;
lex->sphead->m_body_begin= lex->ptr;
lex->sphead->m_body_begin= lex->ptr;
}
if (!lex->et_compile_phase)
lex->et->body_begin= lex->ptr;
}
ev_sql_stmt_inner
{
LEX *lex=Lex;
sp_head *sp= lex->sphead;
// return back to the original memory root ASAP
sp->init_strings(YYTHD, lex, NULL);
sp->restore_thd_mem_root(YYTHD);
if (!$<sphead>1)
{
sp_head *sp= lex->sphead;
// return back to the original memory root ASAP
sp->init_strings(YYTHD, lex, NULL);
sp->restore_thd_mem_root(YYTHD);
lex->sp_chistics.suid= SP_IS_SUID;//always the definer!
lex->sp_chistics.suid= SP_IS_SUID;//always the definer!
lex->et->sphead= lex->sphead;
lex->sphead= NULL;
}
if (!lex->et_compile_phase)
{
lex->et->init_body(YYTHD);
......@@ -4223,7 +4235,8 @@ alter:
}
lex->spname= 0;//defensive programming
et= new event_timed();// implicitly calls event_timed::init()
if (!(et= new event_timed()))// implicitly calls event_timed::init()
YYABORT;
lex->et = et;
et->init_name(YYTHD, $3);
......@@ -4235,11 +4248,6 @@ alter:
$<ulong_num>$= YYTHD->client_capabilities & CLIENT_MULTI_QUERIES;
YYTHD->client_capabilities &= ~CLIENT_MULTI_QUERIES;
/*
defensive. in sql_parse.cc it is checked whether is not null
and then deleted
*/
lex->sphead= 0;
}
ev_on_schedule
ev_rename_to
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment