mirror of
https://github.com/MariaDB/server.git
synced 2025-08-07 00:04:31 +03:00
Merge bk-internal.mysql.com:/home/bk/mysql-5.0
into bodhi.local:/opt/local/work/mysql-5.1-runtime-merge libmysql/libmysql.c: Auto merged libmysqld/lib_sql.cc: Auto merged mysql-test/lib/mtr_io.pl: Auto merged mysql-test/r/im_daemon_life_cycle.result: Auto merged mysql-test/r/im_life_cycle.result: Auto merged mysql-test/r/rpl_trigger.result: Auto merged mysql-test/r/trigger.result: Auto merged mysql-test/t/im_daemon_life_cycle.imtest: Auto merged mysql-test/t/im_life_cycle.imtest: Auto merged mysql-test/t/im_utils.imtest: Auto merged mysql-test/t/rpl_trigger.test: Auto merged mysql-test/t/trigger.test: Auto merged sql/item_cmpfunc.cc: Auto merged sql/item_func.cc: Auto merged sql/item_strfunc.cc: Auto merged sql/item_sum.cc: Auto merged sql/mysqld.cc: Auto merged sql/sql_cache.cc: Auto merged tests/mysql_client_test.c: Auto merged mysql-test/lib/mtr_process.pl: Use local. mysql-test/r/func_str.result: SCCS merged mysql-test/t/func_str.test: Manual merge. sql/sql_trigger.cc: Manual merge. sql/sql_yacc.yy: Manual merge.
This commit is contained in:
@@ -107,7 +107,9 @@ const LEX_STRING trg_event_type_names[]=
|
||||
};
|
||||
|
||||
|
||||
static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig);
|
||||
static int
|
||||
add_table_for_trigger(THD *thd, sp_name *trig, bool if_exists,
|
||||
TABLE_LIST ** table);
|
||||
|
||||
class Handle_old_incorrect_sql_modes_hook: public Unknown_key_hook
|
||||
{
|
||||
@@ -156,6 +158,13 @@ private:
|
||||
*/
|
||||
bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
|
||||
{
|
||||
/*
|
||||
FIXME: The code below takes too many different paths depending on the
|
||||
'create' flag, so that the justification for a single function
|
||||
'mysql_create_or_drop_trigger', compared to two separate functions
|
||||
'mysql_create_trigger' and 'mysql_drop_trigger' is not apparent.
|
||||
This is a good candidate for a minor refactoring.
|
||||
*/
|
||||
TABLE *table;
|
||||
bool result= TRUE;
|
||||
String stmt_query;
|
||||
@@ -181,10 +190,6 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
if (!create &&
|
||||
!(tables= add_table_for_trigger(thd, thd->lex->spname)))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
/*
|
||||
We don't allow creating triggers on tables in the 'mysql' schema
|
||||
*/
|
||||
@@ -194,9 +199,6 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
/* We should have only one table in table list. */
|
||||
DBUG_ASSERT(tables->next_global == 0);
|
||||
|
||||
/*
|
||||
Check that the user has TRIGGER privilege on the subject table.
|
||||
*/
|
||||
@@ -216,8 +218,10 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
|
||||
/*
|
||||
There is no DETERMINISTIC clause for triggers, so can't check it.
|
||||
But a trigger can in theory be used to do nasty things (if it supported
|
||||
DROP for example) so we do the check for privileges. Triggers have the
|
||||
same nature as functions regarding binlogging: their body is implicitely
|
||||
DROP for example) so we do the check for privileges. For now there is
|
||||
already a stronger test right above; but when this stronger test will
|
||||
be removed, the test below will hold. Because triggers have the same
|
||||
nature as functions regarding binlogging: their body is implicitly
|
||||
binlogged, so they share the same danger, so trust_function_creators
|
||||
applies to them too.
|
||||
*/
|
||||
@@ -228,24 +232,52 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
/* We do not allow creation of triggers on temporary tables. */
|
||||
if (create && find_temporary_table(thd, tables))
|
||||
{
|
||||
my_error(ER_TRG_ON_VIEW_OR_TEMP_TABLE, MYF(0), tables->alias);
|
||||
DBUG_RETURN(TRUE);
|
||||
}
|
||||
|
||||
/*
|
||||
We don't want perform our operations while global read lock is held
|
||||
so we have to wait until its end and then prevent it from occuring
|
||||
so we have to wait until its end and then prevent it from occurring
|
||||
again until we are done. (Acquiring LOCK_open is not enough because
|
||||
global read lock is held without helding LOCK_open).
|
||||
global read lock is held without holding LOCK_open).
|
||||
*/
|
||||
if (wait_if_global_read_lock(thd, 0, 1))
|
||||
DBUG_RETURN(TRUE);
|
||||
|
||||
VOID(pthread_mutex_lock(&LOCK_open));
|
||||
|
||||
if (!create)
|
||||
{
|
||||
bool if_exists= thd->lex->drop_if_exists;
|
||||
|
||||
if (add_table_for_trigger(thd, thd->lex->spname, if_exists, & tables))
|
||||
goto end;
|
||||
|
||||
if (!tables)
|
||||
{
|
||||
DBUG_ASSERT(if_exists);
|
||||
/*
|
||||
Since the trigger does not exist, there is no associated table,
|
||||
and therefore :
|
||||
- no TRIGGER privileges to check,
|
||||
- no trigger to drop,
|
||||
- no table to lock/modify,
|
||||
so the drop statement is successful.
|
||||
*/
|
||||
result= FALSE;
|
||||
/* Still, we need to log the query ... */
|
||||
stmt_query.append(thd->query, thd->query_length);
|
||||
goto end;
|
||||
}
|
||||
}
|
||||
|
||||
/* We should have only one table in table list. */
|
||||
DBUG_ASSERT(tables->next_global == 0);
|
||||
|
||||
/* We do not allow creation of triggers on temporary tables. */
|
||||
if (create && find_temporary_table(thd, tables->db, tables->table_name))
|
||||
{
|
||||
my_error(ER_TRG_ON_VIEW_OR_TEMP_TABLE, MYF(0), tables->alias);
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (lock_table_names(thd, tables))
|
||||
goto end;
|
||||
|
||||
@@ -1141,13 +1173,17 @@ bool Table_triggers_list::get_trigger_info(THD *thd, trg_event_type event,
|
||||
mysql_table_for_trigger()
|
||||
thd - current thread context
|
||||
trig - identifier for trigger
|
||||
if_exists - treat a not existing trigger as a warning if TRUE
|
||||
table - pointer to TABLE_LIST object for the table trigger (output)
|
||||
|
||||
RETURN VALUE
|
||||
0 - error
|
||||
# - pointer to TABLE_LIST object for the table
|
||||
0 Success
|
||||
1 Error
|
||||
*/
|
||||
|
||||
static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig)
|
||||
static int
|
||||
add_table_for_trigger(THD *thd, sp_name *trig, bool if_exists,
|
||||
TABLE_LIST **table)
|
||||
{
|
||||
LEX *lex= thd->lex;
|
||||
char path_buff[FN_REFLEN];
|
||||
@@ -1158,6 +1194,7 @@ static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig)
|
||||
path_buff, &trigname.trigger_table);
|
||||
|
||||
DBUG_ENTER("add_table_for_trigger");
|
||||
DBUG_ASSERT(table != NULL);
|
||||
|
||||
path.length= build_table_filename(path_buff, FN_REFLEN-1,
|
||||
trig->m_db.str, trig->m_name.str,
|
||||
@@ -1166,30 +1203,45 @@ static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig)
|
||||
|
||||
if (access(path_buff, F_OK))
|
||||
{
|
||||
if (if_exists)
|
||||
{
|
||||
push_warning_printf(thd,
|
||||
MYSQL_ERROR::WARN_LEVEL_NOTE,
|
||||
ER_TRG_DOES_NOT_EXIST,
|
||||
ER(ER_TRG_DOES_NOT_EXIST));
|
||||
*table= NULL;
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
my_error(ER_TRG_DOES_NOT_EXIST, MYF(0));
|
||||
DBUG_RETURN(0);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
if (!(parser= sql_parse_prepare(&path, thd->mem_root, 1)))
|
||||
DBUG_RETURN(0);
|
||||
DBUG_RETURN(1);
|
||||
|
||||
if (!is_equal(&trigname_file_type, parser->type()))
|
||||
{
|
||||
my_error(ER_WRONG_OBJECT, MYF(0), trig->m_name.str, trigname_file_ext+1,
|
||||
"TRIGGERNAME");
|
||||
DBUG_RETURN(0);
|
||||
DBUG_RETURN(1);
|
||||
}
|
||||
|
||||
if (parser->parse((gptr)&trigname, thd->mem_root,
|
||||
trigname_file_parameters, 1,
|
||||
&trigger_table_hook))
|
||||
DBUG_RETURN(0);
|
||||
DBUG_RETURN(1);
|
||||
|
||||
/* We need to reset statement table list to be PS/SP friendly. */
|
||||
lex->query_tables= 0;
|
||||
lex->query_tables_last= &lex->query_tables;
|
||||
DBUG_RETURN(sp_add_to_query_tables(thd, lex, trig->m_db.str,
|
||||
trigname.trigger_table.str, TL_IGNORE));
|
||||
*table= sp_add_to_query_tables(thd, lex, trig->m_db.str,
|
||||
trigname.trigger_table.str, TL_IGNORE);
|
||||
|
||||
if (! *table)
|
||||
DBUG_RETURN(1);
|
||||
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
||||
|
Reference in New Issue
Block a user