summaryrefslogtreecommitdiff
path: root/sql/sql_trigger.cc
diff options
context:
space:
mode:
authorunknown <kostja@bodhi.local>2006-11-30 02:36:18 +0300
committerunknown <kostja@bodhi.local>2006-11-30 02:36:18 +0300
commit126375b16aa31066cfb6e1332b73d8fb9f23467c (patch)
tree04251b69b15ebb521e538025af2e5124e09aabb1 /sql/sql_trigger.cc
parent66b53b16426509150fecaf7a4d6dd0625bff4424 (diff)
parent4ec847218dca3fa31d6b7d61fffdf71c444c1c74 (diff)
downloadmariadb-git-126375b16aa31066cfb6e1332b73d8fb9f23467c.tar.gz
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.
Diffstat (limited to 'sql/sql_trigger.cc')
-rw-r--r--sql/sql_trigger.cc108
1 files changed, 80 insertions, 28 deletions
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index 8baf84585b2..df648c49c09 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -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);
}