Commit 7402f669 authored by unknown's avatar unknown

Fix for bug #14863 "Triggers: crash if create and there is no current database".

Now when we create or drop trigger we check that both trigger name and trigger
table always have database part specified. Thus we give an error if it they
are not specified explicitly or implicitly via current database.


mysql-test/r/trigger.result:
  Added test for bug #14863 "Triggers: crash if create and there is no current
  database".
mysql-test/t/trigger.test:
  Added test for bug #14863 "Triggers: crash if create and there is no current
  database".
sql/sql_trigger.cc:
  mysql_create_or_drop_trigger():
    Now we check that both trigger name and trigger table have database
    part specified (explicitly or implicitly via current database. Note
    that in latter case sp_name::m_db is already set by parser).
  Table_triggers_list::create_trigger()/::add_table_for_trigger():
    Simplified method/function's code since now they can assume that
    sp_name::m_db is always filled now.
  trigname_file_parameters:
    Removed comment which is no longer true.
parent 4d87cf98
...@@ -780,3 +780,9 @@ end// ...@@ -780,3 +780,9 @@ end//
CALL p2(); CALL p2();
drop procedure p2; drop procedure p2;
drop table t1; drop table t1;
create trigger t1_bi before insert on test.t1 for each row set @a:=0;
ERROR 3D000: No database selected
create trigger test.t1_bi before insert on t1 for each row set @a:=0;
ERROR 3D000: No database selected
drop trigger t1_bi;
ERROR 3D000: No database selected
...@@ -13,6 +13,8 @@ drop procedure if exists p1; ...@@ -13,6 +13,8 @@ drop procedure if exists p1;
# Create additional connections used through test # Create additional connections used through test
connect (addconroot1, localhost, root,,); connect (addconroot1, localhost, root,,);
connect (addconroot2, localhost, root,,); connect (addconroot2, localhost, root,,);
# Connection without current database set
connect (addconwithoutdb, localhost, root,,*NO-ONE*);
connection default; connection default;
create table t1 (i int); create table t1 (i int);
...@@ -946,3 +948,16 @@ CALL p2(); ...@@ -946,3 +948,16 @@ CALL p2();
drop procedure p2; drop procedure p2;
drop table t1; drop table t1;
#
# Test for bug #14863 "Triggers: crash if create and there is no current
# database". We should not crash and give proper error when database for
# trigger or its table is not specified and there is no current database.
#
connection addconwithoutdb;
--error ER_NO_DB_ERROR
create trigger t1_bi before insert on test.t1 for each row set @a:=0;
--error ER_NO_DB_ERROR
create trigger test.t1_bi before insert on t1 for each row set @a:=0;
--error ER_NO_DB_ERROR
drop trigger t1_bi;
connection default;
...@@ -78,10 +78,6 @@ const char * const trigname_file_ext= ".TRN"; ...@@ -78,10 +78,6 @@ const char * const trigname_file_ext= ".TRN";
static File_option trigname_file_parameters[]= static File_option trigname_file_parameters[]=
{ {
{ {
/*
FIXME: Length specified for "trigger_table" key is erroneous, problem
caused by this are reported as BUG#14090 and should be fixed ASAP.
*/
{STRING_WITH_LEN("trigger_table")}, {STRING_WITH_LEN("trigger_table")},
offsetof(struct st_trigname, trigger_table), offsetof(struct st_trigname, trigger_table),
FILE_OPTIONS_ESTRING FILE_OPTIONS_ESTRING
...@@ -155,6 +151,17 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create) ...@@ -155,6 +151,17 @@ bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
But do we want this ? But do we want this ?
*/ */
/*
Note that once we will have check for TRIGGER privilege in place we won't
need second part of condition below, since check_access() function also
checks that db is specified.
*/
if (!thd->lex->spname->m_db.length || create && !tables->db_length)
{
my_error(ER_NO_DB_ERROR, MYF(0));
DBUG_RETURN(TRUE);
}
if (!create && if (!create &&
!(tables= add_table_for_trigger(thd, thd->lex->spname))) !(tables= add_table_for_trigger(thd, thd->lex->spname)))
DBUG_RETURN(TRUE); DBUG_RETURN(TRUE);
...@@ -285,6 +292,9 @@ end: ...@@ -285,6 +292,9 @@ end:
definer. The caller is responsible to provide memory for definer. The caller is responsible to provide memory for
storing LEX_STRING object. storing LEX_STRING object.
NOTE
Assumes that trigger name is fully qualified.
RETURN VALUE RETURN VALUE
False - success False - success
True - error True - error
...@@ -307,9 +317,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables, ...@@ -307,9 +317,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables,
/* Trigger must be in the same schema as target table. */ /* Trigger must be in the same schema as target table. */
if (my_strcasecmp(table_alias_charset, table->s->db, if (my_strcasecmp(table_alias_charset, table->s->db, lex->spname->m_db.str))
lex->spname->m_db.str ? lex->spname->m_db.str :
thd->db))
{ {
my_error(ER_TRG_IN_WRONG_SCHEMA, MYF(0)); my_error(ER_TRG_IN_WRONG_SCHEMA, MYF(0));
return 1; return 1;
...@@ -1010,7 +1018,6 @@ bool Table_triggers_list::get_trigger_info(THD *thd, trg_event_type event, ...@@ -1010,7 +1018,6 @@ bool Table_triggers_list::get_trigger_info(THD *thd, trg_event_type event,
static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig) static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig)
{ {
const char *db= !trig->m_db.str ? thd->db : trig->m_db.str;
LEX *lex= thd->lex; LEX *lex= thd->lex;
char path_buff[FN_REFLEN]; char path_buff[FN_REFLEN];
LEX_STRING path; LEX_STRING path;
...@@ -1018,7 +1025,7 @@ static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig) ...@@ -1018,7 +1025,7 @@ static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig)
struct st_trigname trigname; struct st_trigname trigname;
DBUG_ENTER("add_table_for_trigger"); DBUG_ENTER("add_table_for_trigger");
strxnmov(path_buff, FN_REFLEN, mysql_data_home, "/", db, "/", strxnmov(path_buff, FN_REFLEN, mysql_data_home, "/", trig->m_db.str, "/",
trig->m_name.str, trigname_file_ext, NullS); trig->m_name.str, trigname_file_ext, NullS);
path.length= unpack_filename(path_buff, path_buff); path.length= unpack_filename(path_buff, path_buff);
path.str= path_buff; path.str= path_buff;
...@@ -1047,7 +1054,7 @@ static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig) ...@@ -1047,7 +1054,7 @@ static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig)
/* We need to reset statement table list to be PS/SP friendly. */ /* We need to reset statement table list to be PS/SP friendly. */
lex->query_tables= 0; lex->query_tables= 0;
lex->query_tables_last= &lex->query_tables; lex->query_tables_last= &lex->query_tables;
DBUG_RETURN(sp_add_to_query_tables(thd, lex, db, DBUG_RETURN(sp_add_to_query_tables(thd, lex, trig->m_db.str,
trigname.trigger_table.str, TL_WRITE)); trigname.trigger_table.str, TL_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