mirror of
https://github.com/MariaDB/server.git
synced 2025-01-16 20:12:31 +01:00
Merge weblab.(none):/home/marcsql/TREE/mysql-5.1-base
into weblab.(none):/home/marcsql/TREE/mysql-5.1-rt-merge client/mysqldump.c: Auto merged mysql-test/t/sp.test: Auto merged sql/event_data_objects.cc: Auto merged sql/item_func.cc: Auto merged sql/sp_head.cc: Auto merged sql/sql_class.cc: Auto merged sql/sql_class.h: Auto merged
This commit is contained in:
commit
e3ccf3c663
14 changed files with 470 additions and 426 deletions
|
@ -830,11 +830,15 @@ static int get_options(int *argc, char ***argv)
|
|||
(hash_get_key) get_table_key,
|
||||
(hash_free_key) free_table_ent, 0))
|
||||
return(EX_EOM);
|
||||
/* Don't copy cluster internal log tables */
|
||||
/* Don't copy internal log tables */
|
||||
if (my_hash_insert(&ignore_table,
|
||||
(byte*) my_strdup("mysql.apply_status", MYF(MY_WME))) ||
|
||||
my_hash_insert(&ignore_table,
|
||||
(byte*) my_strdup("mysql.schema", MYF(MY_WME))))
|
||||
(byte*) my_strdup("mysql.schema", MYF(MY_WME))) ||
|
||||
my_hash_insert(&ignore_table,
|
||||
(byte*) my_strdup("mysql.general_log", MYF(MY_WME))) ||
|
||||
my_hash_insert(&ignore_table,
|
||||
(byte*) my_strdup("mysql.slow_log", MYF(MY_WME))))
|
||||
return(EX_EOM);
|
||||
|
||||
if ((ho_error= handle_options(argc, argv, my_long_options, get_one_option)))
|
||||
|
@ -3354,8 +3358,12 @@ static int dump_all_tables_in_db(char *database)
|
|||
init_dynamic_string_checked(&query, "LOCK TABLES ", 256, 1024);
|
||||
for (numrows= 0 ; (table= getTableName(1)) ; numrows++)
|
||||
{
|
||||
dynstr_append_checked(&query, quote_name(table, table_buff, 1));
|
||||
dynstr_append_checked(&query, " READ /*!32311 LOCAL */,");
|
||||
char *end= strmov(afterdot, table);
|
||||
if (include_table(hash_key,end - hash_key))
|
||||
{
|
||||
dynstr_append_checked(&query, quote_name(table, table_buff, 1));
|
||||
dynstr_append_checked(&query, " READ /*!32311 LOCAL */,");
|
||||
}
|
||||
}
|
||||
if (numrows && mysql_real_query(mysql, query.str, query.length-1))
|
||||
DB_error(mysql, "when using LOCK TABLES");
|
||||
|
|
|
@ -34,7 +34,6 @@ id c ts
|
|||
affected rows: 2
|
||||
SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'justonce';
|
||||
db name status originator
|
||||
test justonce SLAVESIDE_DISABLED 1
|
||||
DROP EVENT IF EXISTS test.slave_once;
|
||||
CREATE EVENT test.slave_once ON SCHEDULE EVERY 5 MINUTE DO
|
||||
INSERT INTO t1(c) VALUES ('from slave_once');
|
||||
|
@ -111,7 +110,6 @@ id c ts
|
|||
affected rows: 2
|
||||
SELECT db, name, status, originator FROM mysql.event WHERE db = 'test' AND name = 'justonce';
|
||||
db name status originator
|
||||
test justonce SLAVESIDE_DISABLED 1
|
||||
DROP EVENT IF EXISTS test.slave_once;
|
||||
CREATE EVENT test.slave_once ON SCHEDULE EVERY 5 MINUTE DO
|
||||
INSERT INTO t1(c) VALUES ('from slave_once');
|
||||
|
|
|
@ -6061,21 +6061,6 @@ SUM(f2) bug25373(f1)
|
|||
21.300000071526 NULL
|
||||
DROP FUNCTION bug25373|
|
||||
DROP TABLE t3|
|
||||
DROP DATABASE IF EXISTS mysqltest1|
|
||||
DROP DATABASE IF EXISTS mysqltest2|
|
||||
CREATE DATABASE mysqltest1|
|
||||
CREATE DATABASE mysqltest2|
|
||||
CREATE PROCEDURE mysqltest1.p1()
|
||||
DROP DATABASE mysqltest2|
|
||||
use mysqltest2|
|
||||
CALL mysqltest1.p1()|
|
||||
Warnings:
|
||||
Note 1049 Unknown database 'mysqltest2'
|
||||
SELECT DATABASE()|
|
||||
DATABASE()
|
||||
NULL
|
||||
DROP DATABASE mysqltest1|
|
||||
use test|
|
||||
drop function if exists bug20777|
|
||||
drop table if exists examplebug20777|
|
||||
create function bug20777(f1 bigint unsigned) returns bigint unsigned
|
||||
|
@ -6160,30 +6145,55 @@ select bug20777(18446744073709551613)+1;
|
|||
bug20777(18446744073709551613)+1
|
||||
18446744073709551614
|
||||
drop function bug20777;
|
||||
DROP FUNCTION IF EXISTS bug5274_f1|
|
||||
DROP FUNCTION IF EXISTS bug5274_f2|
|
||||
CREATE FUNCTION bug5274_f1(p1 CHAR) RETURNS CHAR
|
||||
RETURN CONCAT(p1, p1)|
|
||||
CREATE FUNCTION bug5274_f2() RETURNS CHAR
|
||||
BEGIN
|
||||
DECLARE v1 INT DEFAULT 0;
|
||||
DECLARE v2 CHAR DEFAULT 'x';
|
||||
WHILE v1 < 30 DO
|
||||
SET v1 = v1 + 1;
|
||||
SET v2 = bug5274_f1(v2);
|
||||
END WHILE;
|
||||
RETURN v2;
|
||||
END|
|
||||
SELECT bug5274_f2()|
|
||||
bug5274_f2()
|
||||
x
|
||||
Warnings:
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
Warning 1265 Data truncated for column 'bug5274_f1' at row 1
|
||||
DROP FUNCTION bug5274_f1|
|
||||
DROP FUNCTION bug5274_f2|
|
||||
End of 5.0 tests.
|
||||
drop table t1,t2;
|
||||
CREATE TABLE t1 (a int auto_increment primary key) engine=MyISAM;
|
||||
CREATE TABLE t2 (a int auto_increment primary key, b int) engine=innodb;
|
||||
set @a=0;
|
||||
CREATE function bug27354() RETURNS int deterministic
|
||||
begin
|
||||
insert into t1 values (null);
|
||||
set @a=@a+1;
|
||||
return @a;
|
||||
end|
|
||||
update t2 set b=1 where a=bug27354();
|
||||
select count(t_1.a),count(t_2.a) from t1 as t_1, t2 as t_2 /* must be 0,0 */;
|
||||
count(t_1.a) count(t_2.a)
|
||||
0 0
|
||||
insert into t2 values (1,1),(2,2),(3,3);
|
||||
update t2 set b=-b where a=bug27354();
|
||||
select * from t2 /* must return 1,-1 ... */;
|
||||
a b
|
||||
1 -1
|
||||
2 -2
|
||||
3 -3
|
||||
select count(*) from t1 /* must be 3 */;
|
||||
count(*)
|
||||
3
|
||||
drop table t1,t2;
|
||||
drop function bug27354;
|
||||
|
|
|
@ -1612,6 +1612,13 @@ drop view v1;
|
|||
drop table t1;
|
||||
drop database mysqldump_test_db;
|
||||
|
||||
#
|
||||
# BUG#26121 mysqldump includes LOCK TABLES general_log WRITE
|
||||
#
|
||||
--exec $MYSQL_DUMP --all-databases > $MYSQLTEST_VARDIR/tmp/bug26121.sql
|
||||
--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/bug26121.sql
|
||||
--remove_file $MYSQLTEST_VARDIR/tmp/bug26121.sql
|
||||
|
||||
--echo #
|
||||
--echo # End of 5.1 tests
|
||||
--echo #
|
||||
|
|
|
@ -7109,6 +7109,44 @@ select bug20777(18446744073709551613)+1;
|
|||
drop function bug20777;
|
||||
delimiter |;
|
||||
|
||||
|
||||
#
|
||||
# BUG#5274: Stored procedure crash if length of CHAR variable too great.
|
||||
#
|
||||
|
||||
# Prepare.
|
||||
|
||||
--disable_warnings
|
||||
DROP FUNCTION IF EXISTS bug5274_f1|
|
||||
DROP FUNCTION IF EXISTS bug5274_f2|
|
||||
--enable_warnings
|
||||
|
||||
# Test.
|
||||
|
||||
CREATE FUNCTION bug5274_f1(p1 CHAR) RETURNS CHAR
|
||||
RETURN CONCAT(p1, p1)|
|
||||
|
||||
CREATE FUNCTION bug5274_f2() RETURNS CHAR
|
||||
BEGIN
|
||||
DECLARE v1 INT DEFAULT 0;
|
||||
DECLARE v2 CHAR DEFAULT 'x';
|
||||
|
||||
WHILE v1 < 30 DO
|
||||
SET v1 = v1 + 1;
|
||||
SET v2 = bug5274_f1(v2);
|
||||
END WHILE;
|
||||
|
||||
RETURN v2;
|
||||
END|
|
||||
|
||||
SELECT bug5274_f2()|
|
||||
|
||||
# Cleanup.
|
||||
|
||||
DROP FUNCTION bug5274_f1|
|
||||
DROP FUNCTION bug5274_f2|
|
||||
|
||||
|
||||
###
|
||||
--echo End of 5.0 tests.
|
||||
|
||||
|
|
|
@ -23,14 +23,6 @@
|
|||
|
||||
#define EVEX_MAX_INTERVAL_VALUE 1000000000L
|
||||
|
||||
static bool
|
||||
event_change_security_context(THD *thd, LEX_STRING user, LEX_STRING host,
|
||||
LEX_STRING db, Security_context *backup);
|
||||
|
||||
static void
|
||||
event_restore_security_context(THD *thd, Security_context *backup);
|
||||
|
||||
|
||||
/*
|
||||
Initiliazes dbname and name of an Event_queue_element_for_exec
|
||||
object
|
||||
|
@ -816,27 +808,10 @@ Event_timed::~Event_timed()
|
|||
*/
|
||||
|
||||
Event_job_data::Event_job_data()
|
||||
:sphead(NULL), sql_mode(0)
|
||||
:sql_mode(0)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Destructor
|
||||
|
||||
SYNOPSIS
|
||||
Event_timed::~Event_timed()
|
||||
*/
|
||||
|
||||
Event_job_data::~Event_job_data()
|
||||
{
|
||||
DBUG_ENTER("Event_job_data::~Event_job_data");
|
||||
delete sphead;
|
||||
sphead= NULL;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Init all member variables
|
||||
|
||||
|
@ -1769,102 +1744,238 @@ Event_timed::get_create_event(THD *thd, String *buf)
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Get SHOW CREATE EVENT as string
|
||||
|
||||
SYNOPSIS
|
||||
Event_job_data::get_create_event(THD *thd, String *buf)
|
||||
thd Thread
|
||||
buf String*, should be already allocated. CREATE EVENT goes inside.
|
||||
|
||||
RETURN VALUE
|
||||
0 OK
|
||||
EVEX_MICROSECOND_UNSUP Error (for now if mysql.event has been
|
||||
tampered and MICROSECONDS interval or
|
||||
derivative has been put there.
|
||||
/**
|
||||
Get an artificial stored procedure to parse as an event definition.
|
||||
*/
|
||||
|
||||
int
|
||||
Event_job_data::get_fake_create_event(String *buf)
|
||||
bool
|
||||
Event_job_data::construct_sp_sql(THD *thd, String *sp_sql)
|
||||
{
|
||||
DBUG_ENTER("Event_job_data::get_create_event");
|
||||
/* FIXME: "EVERY 3337 HOUR" is asking for trouble. */
|
||||
buf->append(STRING_WITH_LEN("CREATE EVENT anonymous ON SCHEDULE "
|
||||
"EVERY 3337 HOUR DO "));
|
||||
buf->append(body.str, body.length);
|
||||
LEX_STRING buffer;
|
||||
const uint STATIC_SQL_LENGTH= 44;
|
||||
|
||||
DBUG_RETURN(0);
|
||||
DBUG_ENTER("Event_job_data::construct_sp_sql");
|
||||
|
||||
/*
|
||||
Allocate a large enough buffer on the thread execution memory
|
||||
root to avoid multiple [re]allocations on system heap
|
||||
*/
|
||||
buffer.length= STATIC_SQL_LENGTH + name.length + body.length;
|
||||
if (! (buffer.str= (char*) thd->alloc(buffer.length)))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
sp_sql->set(buffer.str, buffer.length, system_charset_info);
|
||||
sp_sql->length(0);
|
||||
|
||||
|
||||
sp_sql->append(C_STRING_WITH_LEN("CREATE "));
|
||||
sp_sql->append(C_STRING_WITH_LEN("PROCEDURE "));
|
||||
/*
|
||||
Let's use the same name as the event name to perhaps produce a
|
||||
better error message in case it is a part of some parse error.
|
||||
We're using append_identifier here to successfully parse
|
||||
events with reserved names.
|
||||
*/
|
||||
append_identifier(thd, sp_sql, name.str, name.length);
|
||||
|
||||
/*
|
||||
The default SQL security of a stored procedure is DEFINER. We
|
||||
have already activated the security context of the event, so
|
||||
let's execute the procedure with the invoker rights to save on
|
||||
resets of security contexts.
|
||||
*/
|
||||
sp_sql->append(C_STRING_WITH_LEN("() SQL SECURITY INVOKER "));
|
||||
|
||||
sp_sql->append(body.str, body.length);
|
||||
|
||||
DBUG_RETURN(thd->is_fatal_error);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Executes the event (the underlying sp_head object);
|
||||
|
||||
SYNOPSIS
|
||||
Event_job_data::execute()
|
||||
thd THD
|
||||
|
||||
RETURN VALUE
|
||||
0 success
|
||||
-99 No rights on this.dbname.str
|
||||
others retcodes of sp_head::execute_procedure()
|
||||
/**
|
||||
Get DROP EVENT statement to binlog the drop of ON COMPLETION NOT
|
||||
PRESERVE event.
|
||||
*/
|
||||
|
||||
int
|
||||
bool
|
||||
Event_job_data::construct_drop_event_sql(THD *thd, String *sp_sql)
|
||||
{
|
||||
LEX_STRING buffer;
|
||||
const uint STATIC_SQL_LENGTH= 14;
|
||||
|
||||
DBUG_ENTER("Event_job_data::construct_drop_event_sql");
|
||||
|
||||
buffer.length= STATIC_SQL_LENGTH + name.length*2 + dbname.length*2;
|
||||
if (! (buffer.str= (char*) thd->alloc(buffer.length)))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
sp_sql->set(buffer.str, buffer.length, system_charset_info);
|
||||
sp_sql->length(0);
|
||||
|
||||
sp_sql->append(C_STRING_WITH_LEN("DROP EVENT "));
|
||||
append_identifier(thd, sp_sql, dbname.str, dbname.length);
|
||||
sp_sql->append('.');
|
||||
append_identifier(thd, sp_sql, name.str, name.length);
|
||||
|
||||
DBUG_RETURN(thd->is_fatal_error);
|
||||
}
|
||||
|
||||
/**
|
||||
Compiles and executes the event (the underlying sp_head object)
|
||||
|
||||
@retval TRUE error (reported to the error log)
|
||||
@retval FALSE success
|
||||
*/
|
||||
|
||||
bool
|
||||
Event_job_data::execute(THD *thd, bool drop)
|
||||
{
|
||||
Security_context save_ctx;
|
||||
/* this one is local and not needed after exec */
|
||||
int ret= 0;
|
||||
String sp_sql;
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
Security_context event_sctx, *save_sctx= NULL;
|
||||
#endif
|
||||
CHARSET_INFO *charset_connection;
|
||||
List<Item> empty_item_list;
|
||||
bool ret= TRUE;
|
||||
|
||||
DBUG_ENTER("Event_job_data::execute");
|
||||
DBUG_PRINT("info", ("EXECUTING %s.%s", dbname.str, name.str));
|
||||
|
||||
if ((ret= compile(thd, NULL)))
|
||||
goto done;
|
||||
mysql_reset_thd_for_next_command(thd);
|
||||
|
||||
event_change_security_context(thd, definer_user, definer_host, dbname,
|
||||
&save_ctx);
|
||||
/*
|
||||
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 on a mem_root.
|
||||
MySQL parser currently assumes that current database is either
|
||||
present in THD or all names in all statements are fully specified.
|
||||
And yet not fully specified names inside stored programs must be
|
||||
be supported, even if the current database is not set:
|
||||
CREATE PROCEDURE db1.p1() BEGIN CREATE TABLE t1; END//
|
||||
-- in this example t1 should be always created in db1 and the statement
|
||||
must parse even if there is no current database.
|
||||
|
||||
To support this feature and still address the parser limitation,
|
||||
we need to set the current database here.
|
||||
We don't have to call mysql_change_db, since the checks performed
|
||||
in it are unnecessary for the purpose of parsing, and
|
||||
mysql_change_db will be invoked anyway later, to activate the
|
||||
procedure database before it's executed.
|
||||
*/
|
||||
thd->db= my_strdup(dbname.str, MYF(0));
|
||||
thd->db_length= dbname.length;
|
||||
if (!check_access(thd, EVENT_ACL,dbname.str, 0, 0, 0,is_schema_db(dbname.str)))
|
||||
thd->set_db(dbname.str, dbname.length);
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (event_sctx.change_security_context(thd,
|
||||
&definer_user, &definer_host,
|
||||
&dbname, &save_sctx))
|
||||
{
|
||||
List<Item> empty_item_list;
|
||||
empty_item_list.empty();
|
||||
sql_print_error("Event Scheduler: "
|
||||
"[%s].[%s.%s] execution failed, "
|
||||
"failed to authenticate the user.",
|
||||
definer.str, dbname.str, name.str);
|
||||
goto end;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (check_access(thd, EVENT_ACL, dbname.str,
|
||||
0, 0, 0, is_schema_db(dbname.str)))
|
||||
{
|
||||
/*
|
||||
This aspect of behavior is defined in the worklog,
|
||||
and this is how triggers work too: if TRIGGER
|
||||
privilege is revoked from trigger definer,
|
||||
triggers are not executed.
|
||||
*/
|
||||
sql_print_error("Event Scheduler: "
|
||||
"[%s].[%s.%s] execution failed, "
|
||||
"user no longer has EVENT privilege.",
|
||||
definer.str, dbname.str, name.str);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (construct_sp_sql(thd, &sp_sql))
|
||||
goto end;
|
||||
|
||||
/*
|
||||
Set up global thread attributes to reflect the properties of
|
||||
this Event. We can simply reset these instead of usual
|
||||
backup/restore employed in stored programs since we know that
|
||||
this is a top level statement and the worker thread is
|
||||
allocated exclusively to execute this event.
|
||||
*/
|
||||
charset_connection= get_charset_by_csname("utf8",
|
||||
MY_CS_PRIMARY, MYF(MY_WME));
|
||||
thd->variables.character_set_client= charset_connection;
|
||||
thd->variables.character_set_results= charset_connection;
|
||||
thd->variables.collation_connection= charset_connection;
|
||||
thd->update_charset();
|
||||
|
||||
thd->variables.sql_mode= sql_mode;
|
||||
thd->variables.time_zone= time_zone;
|
||||
|
||||
thd->query= sp_sql.c_ptr_safe();
|
||||
thd->query_length= sp_sql.length();
|
||||
|
||||
lex_start(thd, thd->query, thd->query_length);
|
||||
|
||||
if (MYSQLparse(thd) || thd->is_fatal_error)
|
||||
{
|
||||
sql_print_error("Event Scheduler: "
|
||||
"%serror during compilation of %s.%s",
|
||||
thd->is_fatal_error ? "fatal " : "",
|
||||
(const char *) dbname.str, (const char *) name.str);
|
||||
goto end;
|
||||
}
|
||||
|
||||
{
|
||||
sp_head *sphead= thd->lex->sphead;
|
||||
|
||||
DBUG_ASSERT(sphead);
|
||||
|
||||
if (thd->enable_slow_log)
|
||||
sphead->m_flags|= sp_head::LOG_SLOW_STATEMENTS;
|
||||
sphead->m_flags|= sp_head::LOG_GENERAL_LOG;
|
||||
|
||||
/* Execute the event in its time zone. */
|
||||
thd->variables.time_zone= time_zone;
|
||||
sphead->set_info(0, 0, &thd->lex->sp_chistics, sql_mode);
|
||||
sphead->optimize();
|
||||
|
||||
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;
|
||||
}
|
||||
if (drop)
|
||||
{
|
||||
sql_print_information("Event Scheduler: Dropping %s.%s",
|
||||
dbname.str, name.str);
|
||||
/*
|
||||
We must do it here since here we're under the right authentication
|
||||
ID of the event definer
|
||||
There is no pre-locking and therefore there should be no
|
||||
tables open and locked left after execute_procedure.
|
||||
*/
|
||||
if (Events::drop_event(thd, dbname, name, FALSE))
|
||||
ret= 1;
|
||||
}
|
||||
|
||||
event_restore_security_context(thd, &save_ctx);
|
||||
done:
|
||||
end:
|
||||
if (drop && !thd->is_fatal_error)
|
||||
{
|
||||
/*
|
||||
We must do it here since here we're under the right authentication
|
||||
ID of the event definer.
|
||||
*/
|
||||
sql_print_information("Event Scheduler: Dropping %s.%s",
|
||||
(const char *) dbname.str, (const char *) name.str);
|
||||
/*
|
||||
Construct a query for the binary log, to ensure the event is dropped
|
||||
on the slave
|
||||
*/
|
||||
if (construct_drop_event_sql(thd, &sp_sql))
|
||||
ret= 1;
|
||||
else
|
||||
{
|
||||
thd->query= sp_sql.c_ptr_safe();
|
||||
thd->query_length= sp_sql.length();
|
||||
if (Events::drop_event(thd, dbname, name, FALSE))
|
||||
ret= 1;
|
||||
}
|
||||
}
|
||||
if (thd->lex->sphead) /* NULL only if a parse error */
|
||||
{
|
||||
delete thd->lex->sphead;
|
||||
thd->lex->sphead= NULL;
|
||||
}
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (save_sctx)
|
||||
event_sctx.restore_security_context(thd, save_sctx);
|
||||
#endif
|
||||
lex_end(thd->lex);
|
||||
thd->lex->unit.cleanup();
|
||||
thd->end_statement();
|
||||
thd->cleanup_after_query();
|
||||
|
||||
|
@ -1874,134 +1985,6 @@ done:
|
|||
}
|
||||
|
||||
|
||||
/*
|
||||
Compiles an event before it's execution. Compiles the anonymous
|
||||
sp_head object held by the event
|
||||
|
||||
SYNOPSIS
|
||||
Event_job_data::compile()
|
||||
thd thread context, used for memory allocation mostly
|
||||
mem_root if != NULL then this memory root is used for allocs
|
||||
instead of thd->mem_root
|
||||
|
||||
RETURN VALUE
|
||||
0 success
|
||||
EVEX_COMPILE_ERROR error during compilation
|
||||
EVEX_MICROSECOND_UNSUP mysql.event was tampered
|
||||
*/
|
||||
|
||||
int
|
||||
Event_job_data::compile(THD *thd, MEM_ROOT *mem_root)
|
||||
{
|
||||
int ret= 0;
|
||||
MEM_ROOT *tmp_mem_root= 0;
|
||||
LEX *old_lex= thd->lex, lex;
|
||||
char *old_db;
|
||||
int old_db_length;
|
||||
char *old_query;
|
||||
uint old_query_len;
|
||||
ulong old_sql_mode= thd->variables.sql_mode;
|
||||
char create_buf[15 * STRING_BUFFER_USUAL_SIZE];
|
||||
String show_create(create_buf, sizeof(create_buf), system_charset_info);
|
||||
CHARSET_INFO *old_character_set_client,
|
||||
*old_collation_connection,
|
||||
*old_character_set_results;
|
||||
Security_context save_ctx;
|
||||
|
||||
DBUG_ENTER("Event_job_data::compile");
|
||||
|
||||
show_create.length(0);
|
||||
|
||||
switch (get_fake_create_event(&show_create)) {
|
||||
case EVEX_MICROSECOND_UNSUP:
|
||||
DBUG_RETURN(EVEX_MICROSECOND_UNSUP);
|
||||
case 0:
|
||||
break;
|
||||
default:
|
||||
DBUG_ASSERT(0);
|
||||
}
|
||||
|
||||
old_character_set_client= thd->variables.character_set_client;
|
||||
old_character_set_results= thd->variables.character_set_results;
|
||||
old_collation_connection= thd->variables.collation_connection;
|
||||
|
||||
thd->variables.character_set_client=
|
||||
thd->variables.character_set_results=
|
||||
thd->variables.collation_connection=
|
||||
get_charset_by_csname("utf8", MY_CS_PRIMARY, MYF(MY_WME));
|
||||
|
||||
thd->update_charset();
|
||||
|
||||
DBUG_PRINT("info",("old_sql_mode: %lu new_sql_mode: %lu",old_sql_mode, sql_mode));
|
||||
thd->variables.sql_mode= this->sql_mode;
|
||||
/* Change the memory root for the execution time */
|
||||
if (mem_root)
|
||||
{
|
||||
tmp_mem_root= thd->mem_root;
|
||||
thd->mem_root= mem_root;
|
||||
}
|
||||
old_query_len= thd->query_length;
|
||||
old_query= thd->query;
|
||||
old_db= thd->db;
|
||||
old_db_length= thd->db_length;
|
||||
thd->db= dbname.str;
|
||||
thd->db_length= dbname.length;
|
||||
|
||||
thd->query= show_create.c_ptr_safe();
|
||||
thd->query_length= show_create.length();
|
||||
DBUG_PRINT("info", ("query: %s",thd->query));
|
||||
|
||||
event_change_security_context(thd, definer_user, definer_host, dbname,
|
||||
&save_ctx);
|
||||
thd->lex= &lex;
|
||||
mysql_init_query(thd, thd->query, thd->query_length);
|
||||
if (MYSQLparse((void *)thd) || thd->is_fatal_error)
|
||||
{
|
||||
DBUG_PRINT("error", ("error during compile or thd->is_fatal_error: %d",
|
||||
thd->is_fatal_error));
|
||||
lex.unit.cleanup();
|
||||
|
||||
sql_print_error("Event Scheduler: "
|
||||
"%serror during compilation of %s.%s",
|
||||
thd->is_fatal_error ? "fatal " : "",
|
||||
dbname.str, name.str);
|
||||
|
||||
ret= EVEX_COMPILE_ERROR;
|
||||
goto done;
|
||||
}
|
||||
DBUG_PRINT("note", ("success compiling %s.%s", dbname.str, name.str));
|
||||
|
||||
sphead= lex.sphead;
|
||||
|
||||
sphead->set_definer(definer.str, definer.length);
|
||||
sphead->set_info(0, 0, &lex.sp_chistics, sql_mode);
|
||||
sphead->optimize();
|
||||
ret= 0;
|
||||
done:
|
||||
|
||||
lex_end(&lex);
|
||||
event_restore_security_context(thd, &save_ctx);
|
||||
DBUG_PRINT("note", ("return old data on its place. set back NAMES"));
|
||||
|
||||
thd->lex= old_lex;
|
||||
thd->query= old_query;
|
||||
thd->query_length= old_query_len;
|
||||
thd->db= old_db;
|
||||
|
||||
thd->variables.sql_mode= old_sql_mode;
|
||||
thd->variables.character_set_client= old_character_set_client;
|
||||
thd->variables.character_set_results= old_character_set_results;
|
||||
thd->variables.collation_connection= old_collation_connection;
|
||||
thd->update_charset();
|
||||
|
||||
/* Change the memory root for the execution time. */
|
||||
if (mem_root)
|
||||
thd->mem_root= tmp_mem_root;
|
||||
|
||||
DBUG_RETURN(ret);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Checks whether two events are in the same schema
|
||||
|
||||
|
@ -2042,64 +2025,3 @@ event_basic_identifier_equal(LEX_STRING db, LEX_STRING name, Event_basic *b)
|
|||
return !sortcmp_lex_string(name, b->name, system_charset_info) &&
|
||||
!sortcmp_lex_string(db, b->dbname, system_charset_info);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Switches the security context.
|
||||
|
||||
SYNOPSIS
|
||||
event_change_security_context()
|
||||
thd Thread
|
||||
user The user
|
||||
host The host of the user
|
||||
db The schema for which the security_ctx will be loaded
|
||||
backup Where to store the old context
|
||||
|
||||
RETURN VALUE
|
||||
FALSE OK
|
||||
TRUE Error (generates error too)
|
||||
*/
|
||||
|
||||
static bool
|
||||
event_change_security_context(THD *thd, LEX_STRING user, LEX_STRING host,
|
||||
LEX_STRING db, Security_context *backup)
|
||||
{
|
||||
DBUG_ENTER("event_change_security_context");
|
||||
DBUG_PRINT("info",("%s@%s@%s", user.str, host.str, db.str));
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
|
||||
*backup= thd->main_security_ctx;
|
||||
if (acl_getroot_no_password(&thd->main_security_ctx, user.str, host.str,
|
||||
host.str, db.str))
|
||||
{
|
||||
my_error(ER_NO_SUCH_USER, MYF(0), user.str, host.str);
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
thd->security_ctx= &thd->main_security_ctx;
|
||||
#endif
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Restores the security context.
|
||||
|
||||
SYNOPSIS
|
||||
event_restore_security_context()
|
||||
thd Thread
|
||||
backup Context to switch to
|
||||
*/
|
||||
|
||||
static void
|
||||
event_restore_security_context(THD *thd, Security_context *backup)
|
||||
{
|
||||
DBUG_ENTER("event_restore_security_context");
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (backup)
|
||||
{
|
||||
thd->main_security_ctx= *backup;
|
||||
thd->security_ctx= &thd->main_security_ctx;
|
||||
}
|
||||
#endif
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
|
||||
#define EVEX_GET_FIELD_FAILED -2
|
||||
#define EVEX_COMPILE_ERROR -3
|
||||
#define EVEX_BAD_PARAMS -5
|
||||
#define EVEX_MICROSECOND_UNSUP -6
|
||||
|
||||
|
@ -169,8 +168,6 @@ public:
|
|||
class Event_job_data : public Event_basic
|
||||
{
|
||||
public:
|
||||
sp_head *sphead;
|
||||
|
||||
LEX_STRING body;
|
||||
LEX_STRING definer_user;
|
||||
LEX_STRING definer_host;
|
||||
|
@ -178,19 +175,17 @@ public:
|
|||
ulong sql_mode;
|
||||
|
||||
Event_job_data();
|
||||
virtual ~Event_job_data();
|
||||
|
||||
virtual int
|
||||
load_from_row(THD *thd, TABLE *table);
|
||||
|
||||
int
|
||||
bool
|
||||
execute(THD *thd, bool drop);
|
||||
|
||||
int
|
||||
compile(THD *thd, MEM_ROOT *mem_root);
|
||||
private:
|
||||
int
|
||||
get_fake_create_event(String *buf);
|
||||
bool
|
||||
construct_sp_sql(THD *thd, String *sp_sql);
|
||||
bool
|
||||
construct_drop_event_sql(THD *thd, String *sp_sql);
|
||||
|
||||
Event_job_data(const Event_job_data &); /* Prevent use of these */
|
||||
void operator=(Event_job_data &);
|
||||
|
|
|
@ -277,8 +277,7 @@ Event_worker_thread::run(THD *thd, Event_queue_element_for_exec *event)
|
|||
{
|
||||
/* needs to be first for thread_stack */
|
||||
char my_stack;
|
||||
int ret;
|
||||
Event_job_data *job_data= NULL;
|
||||
Event_job_data job_data;
|
||||
bool res;
|
||||
|
||||
thd->thread_stack= &my_stack; // remember where our stack is
|
||||
|
@ -291,60 +290,43 @@ Event_worker_thread::run(THD *thd, Event_queue_element_for_exec *event)
|
|||
if (res)
|
||||
goto end;
|
||||
|
||||
if (!(job_data= new Event_job_data()))
|
||||
goto end;
|
||||
else if ((ret= db_repository->
|
||||
load_named_event(thd, event->dbname, event->name, job_data)))
|
||||
if ((res= db_repository->load_named_event(thd, event->dbname, event->name,
|
||||
&job_data)))
|
||||
{
|
||||
DBUG_PRINT("error", ("Got %d from load_named_event", ret));
|
||||
DBUG_PRINT("error", ("Got error from load_named_event"));
|
||||
goto end;
|
||||
}
|
||||
|
||||
sql_print_information("Event Scheduler: "
|
||||
"[%s.%s of %s] executing in thread %lu. ",
|
||||
job_data->dbname.str, job_data->name.str,
|
||||
job_data->definer.str, thd->thread_id);
|
||||
"[%s].[%s.%s] started in thread %lu.",
|
||||
job_data.definer.str,
|
||||
job_data.dbname.str, job_data.name.str,
|
||||
thd->thread_id);
|
||||
|
||||
thd->enable_slow_log= TRUE;
|
||||
|
||||
ret= job_data->execute(thd, event->dropped);
|
||||
res= job_data.execute(thd, event->dropped);
|
||||
|
||||
print_warnings(thd, job_data);
|
||||
print_warnings(thd, &job_data);
|
||||
|
||||
switch (ret) {
|
||||
case 0:
|
||||
sql_print_information("Event Scheduler: "
|
||||
"[%s].[%s.%s] executed successfully in thread %lu.",
|
||||
job_data->definer.str,
|
||||
job_data->dbname.str, job_data->name.str,
|
||||
thd->thread_id);
|
||||
break;
|
||||
case EVEX_COMPILE_ERROR:
|
||||
sql_print_information("Event Scheduler: "
|
||||
"[%s].[%s.%s] event compilation failed.",
|
||||
job_data->definer.str,
|
||||
job_data->dbname.str, job_data->name.str);
|
||||
break;
|
||||
default:
|
||||
if (res)
|
||||
sql_print_information("Event Scheduler: "
|
||||
"[%s].[%s.%s] event execution failed.",
|
||||
job_data->definer.str,
|
||||
job_data->dbname.str, job_data->name.str);
|
||||
break;
|
||||
}
|
||||
job_data.definer.str,
|
||||
job_data.dbname.str, job_data.name.str);
|
||||
else
|
||||
sql_print_information("Event Scheduler: "
|
||||
"[%s].[%s.%s] executed successfully in thread %lu.",
|
||||
job_data.definer.str,
|
||||
job_data.dbname.str, job_data.name.str,
|
||||
thd->thread_id);
|
||||
|
||||
end:
|
||||
delete job_data;
|
||||
|
||||
DBUG_PRINT("info", ("Done with Event %s.%s", event->dbname.str,
|
||||
event->name.str));
|
||||
|
||||
delete event;
|
||||
deinit_event_thread(thd);
|
||||
/*
|
||||
Do not pthread_exit since we want local destructors for stack objects
|
||||
to be invoked.
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -424,7 +424,8 @@ Events::create_event(THD *thd, Event_parse_data *parse_data,
|
|||
if (event_queue)
|
||||
event_queue->create_event(thd, new_element, &created);
|
||||
/* Binlog the create event. */
|
||||
if (mysql_bin_log.is_open() && (thd->query_length > 0))
|
||||
DBUG_ASSERT(thd->query && thd->query_length);
|
||||
if (mysql_bin_log.is_open())
|
||||
{
|
||||
thd->clear_error();
|
||||
thd->binlog_query(THD::MYSQL_QUERY_TYPE,
|
||||
|
@ -549,7 +550,8 @@ Events::update_event(THD *thd, Event_parse_data *parse_data,
|
|||
event_queue->update_event(thd, parse_data->dbname, parse_data->name,
|
||||
new_element);
|
||||
/* Binlog the alter event. */
|
||||
if (mysql_bin_log.is_open() && (thd->query_length > 0))
|
||||
DBUG_ASSERT(thd->query && thd->query_length);
|
||||
if (mysql_bin_log.is_open())
|
||||
{
|
||||
thd->clear_error();
|
||||
thd->binlog_query(THD::MYSQL_QUERY_TYPE,
|
||||
|
@ -628,7 +630,8 @@ Events::drop_event(THD *thd, LEX_STRING dbname, LEX_STRING name, bool if_exists)
|
|||
if (event_queue)
|
||||
event_queue->drop_event(thd, dbname, name);
|
||||
/* Binlog the drop event. */
|
||||
if (mysql_bin_log.is_open() && (thd->query_length > 0))
|
||||
DBUG_ASSERT(thd->query && thd->query_length);
|
||||
if (mysql_bin_log.is_open())
|
||||
{
|
||||
thd->clear_error();
|
||||
thd->binlog_query(THD::MYSQL_QUERY_TYPE,
|
||||
|
|
|
@ -5352,7 +5352,7 @@ Item_func_sp::fix_fields(THD *thd, Item **ref)
|
|||
Security_context *save_secutiry_ctx;
|
||||
res= set_routine_security_ctx(thd, m_sp, false, &save_secutiry_ctx);
|
||||
if (!res)
|
||||
sp_restore_security_context(thd, save_secutiry_ctx);
|
||||
m_sp->m_security_ctx.restore_security_context(thd, save_secutiry_ctx);
|
||||
|
||||
#endif /* ! NO_EMBEDDED_ACCESS_CHECKS */
|
||||
}
|
||||
|
|
|
@ -1245,7 +1245,11 @@ set_routine_security_ctx(THD *thd, sp_head *sp, bool is_proc,
|
|||
Security_context **save_ctx)
|
||||
{
|
||||
*save_ctx= 0;
|
||||
if (sp_change_security_context(thd, sp, save_ctx))
|
||||
if (sp->m_chistics->suid != SP_IS_NOT_SUID &&
|
||||
sp->m_security_ctx.change_security_context(thd, &sp->m_definer_user,
|
||||
&sp->m_definer_host,
|
||||
&sp->m_db,
|
||||
save_ctx))
|
||||
return TRUE;
|
||||
|
||||
/*
|
||||
|
@ -1262,7 +1266,7 @@ set_routine_security_ctx(THD *thd, sp_head *sp, bool is_proc,
|
|||
check_routine_access(thd, EXECUTE_ACL,
|
||||
sp->m_db.str, sp->m_name.str, is_proc, FALSE))
|
||||
{
|
||||
sp_restore_security_context(thd, *save_ctx);
|
||||
sp->m_security_ctx.restore_security_context(thd, *save_ctx);
|
||||
*save_ctx= 0;
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -1573,7 +1577,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount,
|
|||
}
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
sp_restore_security_context(thd, save_security_ctx);
|
||||
m_security_ctx.restore_security_context(thd, save_security_ctx);
|
||||
#endif
|
||||
|
||||
err_with_cleanup:
|
||||
|
@ -1791,7 +1795,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
|
|||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
if (save_security_ctx)
|
||||
sp_restore_security_context(thd, save_security_ctx);
|
||||
m_security_ctx.restore_security_context(thd, save_security_ctx);
|
||||
#endif
|
||||
|
||||
if (!save_spcont)
|
||||
|
@ -3431,44 +3435,6 @@ sp_instr_set_case_expr::opt_move(uint dst, List<sp_instr> *bp)
|
|||
|
||||
/* ------------------------------------------------------------------ */
|
||||
|
||||
/*
|
||||
Security context swapping
|
||||
*/
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
bool
|
||||
sp_change_security_context(THD *thd, sp_head *sp, Security_context **backup)
|
||||
{
|
||||
*backup= 0;
|
||||
if (sp->m_chistics->suid != SP_IS_NOT_SUID &&
|
||||
(strcmp(sp->m_definer_user.str,
|
||||
thd->security_ctx->priv_user) ||
|
||||
my_strcasecmp(system_charset_info, sp->m_definer_host.str,
|
||||
thd->security_ctx->priv_host)))
|
||||
{
|
||||
if (acl_getroot_no_password(&sp->m_security_ctx, sp->m_definer_user.str,
|
||||
sp->m_definer_host.str,
|
||||
sp->m_definer_host.str,
|
||||
sp->m_db.str))
|
||||
{
|
||||
my_error(ER_NO_SUCH_USER, MYF(0), sp->m_definer_user.str,
|
||||
sp->m_definer_host.str);
|
||||
return TRUE;
|
||||
}
|
||||
*backup= thd->security_ctx;
|
||||
thd->security_ctx= &sp->m_security_ctx;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void
|
||||
sp_restore_security_context(THD *thd, Security_context *backup)
|
||||
{
|
||||
if (backup)
|
||||
thd->security_ctx= backup;
|
||||
}
|
||||
|
||||
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
|
||||
|
||||
/*
|
||||
Structure that represent all instances of one table
|
||||
|
|
|
@ -2125,6 +2125,102 @@ bool Security_context::set_user(char *user_arg)
|
|||
return user == 0;
|
||||
}
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
/**
|
||||
Initialize this security context from the passed in credentials
|
||||
and activate it in the current thread.
|
||||
|
||||
@param[out] backup Save a pointer to the current security context
|
||||
in the thread. In case of success it points to the
|
||||
saved old context, otherwise it points to NULL.
|
||||
|
||||
|
||||
During execution of a statement, multiple security contexts may
|
||||
be needed:
|
||||
- the security context of the authenticated user, used as the
|
||||
default security context for all top-level statements
|
||||
- in case of a view or a stored program, possibly the security
|
||||
context of the definer of the routine, if the object is
|
||||
defined with SQL SECURITY DEFINER option.
|
||||
|
||||
The currently "active" security context is parameterized in THD
|
||||
member security_ctx. By default, after a connection is
|
||||
established, this member points at the "main" security context
|
||||
- the credentials of the authenticated user.
|
||||
|
||||
Later, if we would like to execute some sub-statement or a part
|
||||
of a statement under credentials of a different user, e.g.
|
||||
definer of a procedure, we authenticate this user in a local
|
||||
instance of Security_context by means of this method (and
|
||||
ultimately by means of acl_getroot_no_password), and make the
|
||||
local instance active in the thread by re-setting
|
||||
thd->security_ctx pointer.
|
||||
|
||||
Note, that the life cycle and memory management of the "main" and
|
||||
temporary security contexts are different.
|
||||
For the main security context, the memory for user/host/ip is
|
||||
allocated on system heap, and the THD class frees this memory in
|
||||
its destructor. The only case when contents of the main security
|
||||
context may change during its life time is when someone issued
|
||||
CHANGE USER command.
|
||||
Memory management of a "temporary" security context is
|
||||
responsibility of the module that creates it.
|
||||
|
||||
@retval TRUE there is no user with the given credentials. The erro
|
||||
is reported in the thread.
|
||||
@retval FALSE success
|
||||
*/
|
||||
|
||||
bool
|
||||
Security_context::
|
||||
change_security_context(THD *thd,
|
||||
LEX_STRING *definer_user,
|
||||
LEX_STRING *definer_host,
|
||||
LEX_STRING *db,
|
||||
Security_context **backup)
|
||||
{
|
||||
bool needs_change;
|
||||
|
||||
DBUG_ENTER("Security_context::change_security_context");
|
||||
|
||||
DBUG_ASSERT(definer_user->str && definer_host->str);
|
||||
|
||||
*backup= NULL;
|
||||
/*
|
||||
The current security context may have NULL members
|
||||
if we have just started the thread and not authenticated
|
||||
any user. This use case is currently in events worker thread.
|
||||
*/
|
||||
needs_change= (thd->security_ctx->priv_user == NULL ||
|
||||
strcmp(definer_user->str, thd->security_ctx->priv_user) ||
|
||||
thd->security_ctx->priv_host == NULL ||
|
||||
my_strcasecmp(system_charset_info, definer_host->str,
|
||||
thd->security_ctx->priv_host));
|
||||
if (needs_change)
|
||||
{
|
||||
if (acl_getroot_no_password(this, definer_user->str, definer_host->str,
|
||||
definer_host->str, db->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= this;
|
||||
}
|
||||
|
||||
DBUG_RETURN(FALSE);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Security_context::restore_security_context(THD *thd,
|
||||
Security_context *backup)
|
||||
{
|
||||
if (backup)
|
||||
thd->security_ctx= backup;
|
||||
}
|
||||
#endif
|
||||
|
||||
/****************************************************************************
|
||||
Handling of open and locked tables states.
|
||||
|
|
|
@ -658,6 +658,18 @@ public:
|
|||
}
|
||||
|
||||
bool set_user(char *user_arg);
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
bool
|
||||
change_security_context(THD *thd,
|
||||
LEX_STRING *definer_user,
|
||||
LEX_STRING *definer_host,
|
||||
LEX_STRING *db,
|
||||
Security_context **backup);
|
||||
|
||||
void
|
||||
restore_security_context(THD *thd, Security_context *backup);
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -1543,9 +1543,16 @@ bool Table_triggers_list::process_triggers(THD *thd, trg_event_type event,
|
|||
old_field= trigger_table->field;
|
||||
}
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
Security_context *save_ctx;
|
||||
Security_context *sctx= &sp_trigger->m_security_ctx;
|
||||
Security_context *save_ctx= NULL;
|
||||
|
||||
if (sp_change_security_context(thd, sp_trigger, &save_ctx))
|
||||
|
||||
if (sp_trigger->m_chistics->suid != SP_IS_NOT_SUID &&
|
||||
sctx->change_security_context(thd,
|
||||
&sp_trigger->m_definer_user,
|
||||
&sp_trigger->m_definer_host,
|
||||
&sp_trigger->m_db,
|
||||
&save_ctx))
|
||||
return TRUE;
|
||||
|
||||
/*
|
||||
|
@ -1570,7 +1577,7 @@ bool Table_triggers_list::process_triggers(THD *thd, trg_event_type event,
|
|||
thd->security_ctx->priv_user, thd->security_ctx->host_or_ip,
|
||||
trigger_table->s->table_name.str);
|
||||
|
||||
sp_restore_security_context(thd, save_ctx);
|
||||
sctx->restore_security_context(thd, save_ctx);
|
||||
return TRUE;
|
||||
}
|
||||
#endif // NO_EMBEDDED_ACCESS_CHECKS
|
||||
|
@ -1582,7 +1589,7 @@ bool Table_triggers_list::process_triggers(THD *thd, trg_event_type event,
|
|||
thd->restore_sub_statement_state(&statement_state);
|
||||
|
||||
#ifndef NO_EMBEDDED_ACCESS_CHECKS
|
||||
sp_restore_security_context(thd, save_ctx);
|
||||
sctx->restore_security_context(thd, save_ctx);
|
||||
#endif // NO_EMBEDDED_ACCESS_CHECKS
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue