Commit 1161b521 authored by unknown's avatar unknown

Merge ahristov@bk-internal.mysql.com:/home/bk/mysql-5.1-new

into lmy004.:/work/mysql-5.1-bug17289


mysql-test/r/events.result:
  Auto merged
mysql-test/t/events.test:
  Auto merged
sql/event.h:
  Auto merged
sql/event_executor.cc:
  Auto merged
sql/event_timed.cc:
  Auto merged
parents 7b9223fc b0739269
create database if not exists events_test;
use events_test;
CREATE USER pauline@localhost;
CREATE DATABASE db_x;
GRANT EVENT ON db_x.* TO pauline@localhost;
USE db_x;
CREATE TABLE x_table(a int);
CREATE EVENT e_x1 ON SCHEDULE EVERY 1 SECOND DO DROP DATABASE db_x;
CREATE EVENT e_x2 ON SCHEDULE EVERY 1 SECOND DO DROP TABLE x_table;
SHOW DATABASES LIKE 'db_x';
Database (db_x)
db_x
SET GLOBAL event_scheduler=1;
SHOW DATABASES LIKE 'db_x';
Database (db_x)
db_x
SHOW TABLES FROM db_x;
Tables_in_db_x
x_table
SET GLOBAL event_scheduler=0;
DROP EVENT e_x1;
DROP EVENT e_x2;
DROP DATABASE db_x;
DROP USER pauline@localhost;
USE events_test;
drop event if exists event1;
Warnings:
Note 1305 Event event1 does not exist
......@@ -331,7 +354,7 @@ show processlist;
Id User Host db Command Time State Info
# root localhost events_test Query # NULL show processlist
# event_scheduler NULL Connect # Sleeping NULL
# root events_test Connect # User lock select get_lock("test_lock2", 20)
# root localhost events_test Connect # User lock select get_lock("test_lock2", 20)
"Release the mutex, the event worker should finish."
select release_lock("test_lock2");
release_lock("test_lock2")
......@@ -349,6 +372,8 @@ set global event_scheduler=0;
show processlist;
Id User Host db Command Time State Info
# root localhost events_test Query # NULL show processlist
# event_scheduler NULL Connect # Sleeping NULL
# root localhost events_test Connect # User lock select get_lock("test_lock2_1", 20)
"Release the lock so the child process should finish. Hence the scheduler also"
select release_lock("test_lock2_1");
release_lock("test_lock2_1")
......
create database if not exists events_test;
use events_test;
#
# START: BUG #17289 Events: missing privilege check for drop database
#
CREATE USER pauline@localhost;
CREATE DATABASE db_x;
GRANT EVENT ON db_x.* TO pauline@localhost;
USE db_x;
CREATE TABLE x_table(a int);
connect (priv_conn,localhost,pauline,,db_x);
CREATE EVENT e_x1 ON SCHEDULE EVERY 1 SECOND DO DROP DATABASE db_x;
CREATE EVENT e_x2 ON SCHEDULE EVERY 1 SECOND DO DROP TABLE x_table;
connection default;
SHOW DATABASES LIKE 'db_x';
SET GLOBAL event_scheduler=1;
--sleep 2
SHOW DATABASES LIKE 'db_x';
SHOW TABLES FROM db_x;
SET GLOBAL event_scheduler=0;
--sleep 1
connection priv_conn;
DROP EVENT e_x1;
DROP EVENT e_x2;
disconnect priv_conn;
connection default;
DROP DATABASE db_x;
DROP USER pauline@localhost;
USE events_test;
--sleep 1
#
# END: BUG #17289 Events: missing privilege check for drop database
#
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 enable;
......
......@@ -205,6 +205,12 @@ class event_timed
delete sphead;
sphead= 0;
}
protected:
bool
change_security_context(THD *thd, Security_context **backup);
void
restore_security_context(THD *thd, Security_context *backup);
};
......
......@@ -49,7 +49,8 @@ static uint workers_count;
static int
evex_load_events_from_db(THD *thd);
bool
evex_print_warnings(THD *thd, event_timed *et);
/*
TODO Andrey: Check for command line option whether to start
......@@ -258,7 +259,8 @@ init_event_thread(THD* thd)
{
DBUG_ENTER("init_event_thread");
thd->client_capabilities= 0;
thd->security_ctx->skip_grants();
thd->security_ctx->master_access= 0;
thd->security_ctx->db_access= 0;
thd->security_ctx->host= (char*)my_localhost;
my_net_init(&thd->net, 0);
thd->net.read_timeout = slave_net_timeout;
......@@ -343,8 +345,11 @@ event_executor_main(void *arg)
if (init_event_thread(thd))
goto err;
// make this thread invisible it has no vio -> show processlist won't see
/*
make this thread visible it has no vio -> show processlist won't see it
unless it's marked as system thread
*/
thd->system_thread= 1;
VOID(pthread_mutex_lock(&LOCK_thread_count));
......@@ -629,21 +634,8 @@ event_executor_worker(void *event_void)
thd= current_thd;
#endif
// thd->security_ctx->priv_host is char[MAX_HOSTNAME]
strxnmov(thd->security_ctx->priv_host, sizeof(thd->security_ctx->priv_host),
event->definer_host.str, NullS);
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)))
{
int ret;
DBUG_PRINT("info", (" EVEX EXECUTING event %s.%s [EXPR:%d]",
event->dbname.str, event->name.str,(int) event->expression));
sql_print_information(" EVEX EXECUTING event %s.%s [EXPR:%d]",
event->dbname.str, event->name.str,(int) event->expression);
......@@ -655,10 +647,7 @@ event_executor_worker(void *event_void)
if (ret == EVEX_COMPILE_ERROR)
sql_print_information(" EVEX COMPILE ERROR for event %s.%s",
event->dbname.str, event->name.str);
DBUG_PRINT("info", (" EVEX EXECUTED event %s.%s [EXPR:%d]. RetCode=%d",
event->dbname.str, event->name.str,
(int) event->expression, ret));
evex_print_warnings(thd, event);
}
if ((event->flags & EVENT_EXEC_NO_MORE) || event->status==MYSQL_EVENT_DISABLED)
{
......@@ -669,7 +658,6 @@ event_executor_worker(void *event_void)
delete event;
}
thd->db= 0;
err:
VOID(pthread_mutex_lock(&LOCK_thread_count));
......@@ -847,3 +835,72 @@ sys_var_event_executor::update(THD *thd, set_var *var)
DBUG_RETURN(0);
}
extern LEX_STRING warning_level_names[];
typedef void (*sql_print_xxx_func)(const char *format, ...);
static sql_print_xxx_func sql_print_xxx_handlers[3] =
{
sql_print_information,
sql_print_warning,
sql_print_error
};
/*
Prints the stack of infos, warnings, errors from thd to
the console so it can be fetched by the logs-into-tables and
checked later.
Synopsis
evex_print_warnings
thd - thread used during the execution of the event
et - the event itself
Returns
0 - OK (always)
*/
bool
evex_print_warnings(THD *thd, event_timed *et)
{
MYSQL_ERROR *err;
DBUG_ENTER("evex_show_warnings");
char msg_buf[1024];
char prefix_buf[512];
String prefix(prefix_buf, sizeof(prefix_buf), system_charset_info);
prefix.length(0);
List_iterator_fast<MYSQL_ERROR> it(thd->warn_list);
while ((err= it++))
{
String err_msg(msg_buf, sizeof(msg_buf), system_charset_info);
err_msg.length(0);// set it to 0 or we start adding at the end
if (!prefix.length())
{
prefix.append("SCHEDULER: [");
append_identifier(thd,&prefix,et->definer_user.str,et->definer_user.length);
prefix.append('@');
append_identifier(thd,&prefix,et->definer_host.str,et->definer_host.length);
prefix.append("][", 2);
append_identifier(thd,&prefix, et->dbname.str, et->dbname.length);
prefix.append('.');
append_identifier(thd,&prefix, et->name.str, et->name.length);
prefix.append("] ", 2);
}
err_msg.append(prefix);
err_msg.append('[');
err_msg.append(warning_level_names[err->level].str,
warning_level_names[err->level].length, system_charset_info);
err_msg.append("] [");
err_msg.append(err->msg, strlen(err->msg), system_charset_info);
err_msg.append("]");
DBUG_ASSERT(err->level < 3);
(sql_print_xxx_handlers[err->level])("%*s", err_msg.length(), err_msg.c_ptr());
// sql_print_information("%*s", err_msg.length(), err_msg.c_ptr());
}
DBUG_RETURN(FALSE);
}
......@@ -1051,12 +1051,13 @@ event_timed::get_create_event(THD *thd, String *buf)
Executes the event (the underlying sp_head object);
SYNOPSIS
evex_fill_row()
event_timed::execute()
thd THD
mem_root If != NULL use it to compile the event on it
Returns
0 - success
-99 - No access to the database.
-100 - event in execution (parallel execution is impossible)
others - retcodes of sp_head::execute_procedure()
......@@ -1065,10 +1066,12 @@ event_timed::get_create_event(THD *thd, String *buf)
int
event_timed::execute(THD *thd, MEM_ROOT *mem_root)
{
List<Item> empty_item_list;
Security_context *save_ctx;
int ret= 0;
DBUG_ENTER("event_timed::execute");
DBUG_PRINT("info", (" EVEX EXECUTING event %s.%s [EXPR:%d]",
dbname.str, name.str, (int) expression));
VOID(pthread_mutex_lock(&this->LOCK_running));
if (running)
......@@ -1080,12 +1083,35 @@ event_timed::execute(THD *thd, MEM_ROOT *mem_root)
VOID(pthread_mutex_unlock(&this->LOCK_running));
// TODO Andrey : make this as member variable and delete in destructor
empty_item_list.empty();
if (!sphead && (ret= compile(thd, mem_root)))
goto done;
ret= sphead->execute_procedure(thd, &empty_item_list);
thd->db= dbname.str;
thd->db_length= dbname.length;
DBUG_PRINT("info", ("master_access=%d db_access=%d",
thd->security_ctx->master_access, thd->security_ctx->db_access));
change_security_context(thd, &save_ctx);
DBUG_PRINT("info", ("master_access=%d db_access=%d",
thd->security_ctx->master_access, thd->security_ctx->db_access));
// if (mysql_change_db(thd, dbname.str, 0))
if (!check_access(thd, EVENT_ACL,dbname.str, 0, 0, 0,is_schema_db(dbname.str)))
{
List<Item> empty_item_list;
empty_item_list.empty();
ret= sphead->execute_procedure(thd, &empty_item_list);
}
else
{
DBUG_PRINT("error", ("%s@%s has no rights on %s", definer_user.str,
definer_host.str, dbname.str));
ret= -99;
}
restore_security_context(thd, save_ctx);
DBUG_PRINT("info", ("master_access=%d db_access=%d",
thd->security_ctx->master_access, thd->security_ctx->db_access));
thd->db= 0;
VOID(pthread_mutex_lock(&this->LOCK_running));
running= false;
......@@ -1098,11 +1124,61 @@ event_timed::execute(THD *thd, MEM_ROOT *mem_root)
delete sphead;
sphead= 0;
}
DBUG_PRINT("info", (" EVEX EXECUTED event %s.%s [EXPR:%d]. RetCode=%d",
dbname.str, name.str, (int) expression, ret));
DBUG_RETURN(ret);
}
/*
Switches the security context
Synopsis
event_timed::change_security_context()
thd - thread
backup - where to store the old context
RETURN
0 - OK
1 - Error (generates error too)
*/
bool
event_timed::change_security_context(THD *thd, Security_context **backup)
{
DBUG_ENTER("event_timed::change_security_context");
DBUG_PRINT("info",("%s@%s@%s",definer_user.str,definer_host.str, dbname.str));
*backup= 0;
if (acl_getroot_no_password(&sphead->m_security_ctx, definer_user.str,
definer_host.str, definer_host.str, dbname.str))
{
my_error(ER_NO_SUCH_USER, MYF(0), definer_user.str, definer_host.str);
DBUG_RETURN(TRUE);
}
*backup= thd->security_ctx;
thd->security_ctx= &sphead->m_security_ctx;
DBUG_RETURN(FALSE);
}
/*
Restores the security context
Synopsis
event_timed::restore_security_context()
thd - thread
backup - switch to this context
*/
void
event_timed::restore_security_context(THD *thd, Security_context *backup)
{
DBUG_ENTER("event_timed::change_security_context");
if (backup)
thd->security_ctx= backup;
DBUG_VOID_RETURN;
}
/*
Compiles an event before it's execution. Compiles the anonymous
sp_head object held by the event
......
......@@ -211,8 +211,13 @@ void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level,
TRUE Error sending data to client
*/
static const char *warning_level_names[]= {"Note", "Warning", "Error", "?"};
static int warning_level_length[]= { 4, 7, 5, 1 };
LEX_STRING warning_level_names[]=
{
{(char*) STRING_WITH_LEN("Note")},
{(char*) STRING_WITH_LEN("Warning")},
{(char*) STRING_WITH_LEN("Error")},
{(char*) STRING_WITH_LEN("?")}
};
bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
{
......@@ -246,8 +251,8 @@ bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
if (idx > unit->select_limit_cnt)
break;
protocol->prepare_for_resend();
protocol->store(warning_level_names[err->level],
warning_level_length[err->level], system_charset_info);
protocol->store(warning_level_names[err->level].str,
warning_level_names[err->level].length, system_charset_info);
protocol->store((uint32) err->code);
protocol->store(err->msg, strlen(err->msg), system_charset_info);
if (protocol->write())
......
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