diff options
author | unknown <dlenev@mysql.com> | 2006-02-26 16:38:48 +0300 |
---|---|---|
committer | unknown <dlenev@mysql.com> | 2006-02-26 16:38:48 +0300 |
commit | 1c93eeaa16774f4c9c0e1a3be9376541b218f053 (patch) | |
tree | 4b1048c53e299ed44184fa45c4acce47e62f0c82 | |
parent | 258ad72c83154ef23bb4b9c0f492aa3e97b0bbed (diff) | |
parent | f8386dfa4821b79b6f88f8d9950ed370ba22e508 (diff) | |
download | mariadb-git-1c93eeaa16774f4c9c0e1a3be9376541b218f053.tar.gz |
Merge bk-internal.mysql.com:/home/bk/mysql-5.0-runtime
into mysql.com:/home/dlenev/src/mysql-5.0-bg13525
sql/sql_table.cc:
Auto merged
sql/sql_trigger.cc:
Auto merged
sql/sql_trigger.h:
Auto merged
sql/sql_yacc.yy:
Auto merged
mysql-test/r/trigger.result:
SCCS merged
mysql-test/t/trigger.test:
SCCS merged
-rw-r--r-- | mysql-test/r/trigger.result | 103 | ||||
-rw-r--r-- | mysql-test/t/trigger.test | 87 | ||||
-rw-r--r-- | sql/sql_rename.cc | 23 | ||||
-rw-r--r-- | sql/sql_table.cc | 13 | ||||
-rw-r--r-- | sql/sql_trigger.cc | 290 | ||||
-rw-r--r-- | sql/sql_trigger.h | 17 | ||||
-rw-r--r-- | sql/sql_yacc.yy | 16 |
7 files changed, 513 insertions, 36 deletions
diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index 62c0d01327d..ea232e081ba 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -1,4 +1,4 @@ -drop table if exists t1, t2, t3; +drop table if exists t1, t2, t3, t4; drop view if exists v1; drop database if exists mysqltest; drop function if exists f1; @@ -785,6 +785,107 @@ 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 +create table t1 (id int); +create trigger t1_bi before insert on t1 for each row set @a:=new.id; +insert into t1 values (101); +select @a; +@a +101 +select trigger_schema, trigger_name, event_object_schema, +event_object_table, action_statement from information_schema.triggers +where event_object_schema = 'test'; +trigger_schema trigger_name event_object_schema event_object_table action_statement +test t1_bi test t1 set @a:=new.id +rename table t1 to t2; +insert into t2 values (102); +select @a; +@a +102 +select trigger_schema, trigger_name, event_object_schema, +event_object_table, action_statement from information_schema.triggers +where event_object_schema = 'test'; +trigger_schema trigger_name event_object_schema event_object_table action_statement +test t1_bi test t2 set @a:=new.id +alter table t2 rename to t3; +insert into t3 values (103); +select @a; +@a +103 +select trigger_schema, trigger_name, event_object_schema, +event_object_table, action_statement from information_schema.triggers +where event_object_schema = 'test'; +trigger_schema trigger_name event_object_schema event_object_table action_statement +test t1_bi test t3 set @a:=new.id +alter table t3 rename to t4, add column val int default 0; +insert into t4 values (104, 1); +select @a; +@a +104 +select trigger_schema, trigger_name, event_object_schema, +event_object_table, action_statement from information_schema.triggers +where event_object_schema = 'test'; +trigger_schema trigger_name event_object_schema event_object_table action_statement +test t1_bi test t4 set @a:=new.id +drop trigger t1_bi; +drop table t4; +create database mysqltest; +use mysqltest; +create table t1 (id int); +create trigger t1_bi before insert on t1 for each row set @a:=new.id; +insert into t1 values (101); +select @a; +@a +101 +select trigger_schema, trigger_name, event_object_schema, +event_object_table, action_statement from information_schema.triggers +where event_object_schema = 'test' or event_object_schema = 'mysqltest'; +trigger_schema trigger_name event_object_schema event_object_table action_statement +mysqltest t1_bi mysqltest t1 set @a:=new.id +rename table t1 to test.t2; +ERROR HY000: Trigger in wrong schema +insert into t1 values (102); +select @a; +@a +102 +select trigger_schema, trigger_name, event_object_schema, +event_object_table, action_statement from information_schema.triggers +where event_object_schema = 'test' or event_object_schema = 'mysqltest'; +trigger_schema trigger_name event_object_schema event_object_table action_statement +mysqltest t1_bi mysqltest t1 set @a:=new.id +drop trigger test.t1_bi; +ERROR HY000: Trigger does not exist +drop trigger t1_bi; +drop table t1; +drop database mysqltest; +use test; +create table t1 (id int); +create trigger t1_bi before insert on t1 for each row set @a:=new.id; +create trigger t1_ai after insert on t1 for each row set @b:=new.id; +insert into t1 values (101); +select @a, @b; +@a @b +101 101 +select trigger_schema, trigger_name, event_object_schema, +event_object_table, action_statement from information_schema.triggers +where event_object_schema = 'test'; +trigger_schema trigger_name event_object_schema event_object_table action_statement +test t1_bi test t1 set @a:=new.id +test t1_ai test t1 set @b:=new.id +rename table t1 to t2; +ERROR HY000: Can't create/write to file './test/t1_ai.TRN~' (Errcode: 13) +insert into t1 values (102); +select @a, @b; +@a @b +102 102 +select trigger_schema, trigger_name, event_object_schema, +event_object_table, action_statement from information_schema.triggers +where event_object_schema = 'test'; +trigger_schema trigger_name event_object_schema event_object_table action_statement +test t1_bi test t1 set @a:=new.id +test t1_ai test t1 set @b:=new.id +drop trigger t1_bi; +drop trigger t1_ai; +drop table t1; create table t1 (i int); create trigger t1_bi before insert on t1 for each row return 0; ERROR 42000: RETURN is only allowed in a FUNCTION diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index c3cc8e3f8e8..e1564e33a43 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -3,7 +3,7 @@ # --disable_warnings -drop table if exists t1, t2, t3; +drop table if exists t1, t2, t3, t4; drop view if exists v1; drop database if exists mysqltest; drop function if exists f1; @@ -959,6 +959,91 @@ create trigger test.t1_bi before insert on t1 for each row set @a:=0; drop trigger t1_bi; connection default; +# +# Test for bug #13525 "Rename table does not keep info of triggers" +# +create table t1 (id int); +create trigger t1_bi before insert on t1 for each row set @a:=new.id; +insert into t1 values (101); +select @a; +select trigger_schema, trigger_name, event_object_schema, + event_object_table, action_statement from information_schema.triggers + where event_object_schema = 'test'; +rename table t1 to t2; +# Trigger should work after rename +insert into t2 values (102); +select @a; +select trigger_schema, trigger_name, event_object_schema, + event_object_table, action_statement from information_schema.triggers + where event_object_schema = 'test'; +# Let us check that the same works for simple ALTER TABLE ... RENAME +alter table t2 rename to t3; +insert into t3 values (103); +select @a; +select trigger_schema, trigger_name, event_object_schema, + event_object_table, action_statement from information_schema.triggers + where event_object_schema = 'test'; +# And for more complex ALTER TABLE +alter table t3 rename to t4, add column val int default 0; +insert into t4 values (104, 1); +select @a; +select trigger_schema, trigger_name, event_object_schema, + event_object_table, action_statement from information_schema.triggers + where event_object_schema = 'test'; +# .TRN file should be updated with new table name +drop trigger t1_bi; +drop table t4; +# Rename between different databases if triggers exist should fail +create database mysqltest; +use mysqltest; +create table t1 (id int); +create trigger t1_bi before insert on t1 for each row set @a:=new.id; +insert into t1 values (101); +select @a; +select trigger_schema, trigger_name, event_object_schema, + event_object_table, action_statement from information_schema.triggers + where event_object_schema = 'test' or event_object_schema = 'mysqltest'; +--error ER_TRG_IN_WRONG_SCHEMA +rename table t1 to test.t2; +insert into t1 values (102); +select @a; +select trigger_schema, trigger_name, event_object_schema, + event_object_table, action_statement from information_schema.triggers + where event_object_schema = 'test' or event_object_schema = 'mysqltest'; +# There should be no fantom .TRN files +--error ER_TRG_DOES_NOT_EXIST +drop trigger test.t1_bi; +drop trigger t1_bi; +drop table t1; +drop database mysqltest; +use test; +# And now let us check that the properly handle rename if there is some +# error during it (that we rollback such renames completely). +create table t1 (id int); +create trigger t1_bi before insert on t1 for each row set @a:=new.id; +create trigger t1_ai after insert on t1 for each row set @b:=new.id; +insert into t1 values (101); +select @a, @b; +select trigger_schema, trigger_name, event_object_schema, + event_object_table, action_statement from information_schema.triggers + where event_object_schema = 'test'; +# Trick which makes update of second .TRN file impossible +system echo dummy >var/master-data/test/t1_ai.TRN~; +system chmod 000 var/master-data/test/t1_ai.TRN~; +--error 1 +rename table t1 to t2; +# 't1' should be still there and triggers should work correctly +insert into t1 values (102); +select @a, @b; +select trigger_schema, trigger_name, event_object_schema, + event_object_table, action_statement from information_schema.triggers + where event_object_schema = 'test'; +system chmod 600 var/master-data/test/t1_ai.TRN; +# Let us check that updates to .TRN files were rolled back too +drop trigger t1_bi; +drop trigger t1_ai; +drop table t1; + # Test for bug #16829 "Firing trigger with RETURN crashes the server" # RETURN is not supposed to be used anywhere except functions, so error # should be returned when one attempts to create trigger with RETURN. diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc index 80fcb973028..74951029de9 100644 --- a/sql/sql_rename.cc +++ b/sql/sql_rename.cc @@ -19,6 +19,7 @@ */ #include "mysql_priv.h" +#include "sql_trigger.h" static TABLE_LIST *rename_tables(THD *thd, TABLE_LIST *table_list, @@ -176,8 +177,26 @@ rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error) if (table_type == DB_TYPE_UNKNOWN) my_error(ER_FILE_NOT_FOUND, MYF(0), name, my_errno); else - rc= mysql_rename_table(table_type, ren_table->db, old_alias, - new_table->db, new_alias); + { + if (!(rc= mysql_rename_table(table_type, ren_table->db, old_alias, + new_table->db, new_alias))) + { + if ((rc= Table_triggers_list::change_table_name(thd, ren_table->db, + old_alias, + new_table->db, + new_alias))) + { + /* + We've succeeded in renaming table's .frm and in updating + corresponding handler data, but have failed to update table's + triggers appropriately. So let us revert operations on .frm + and handler's data and report about failure to rename table. + */ + (void) mysql_rename_table(table_type, new_table->db, new_alias, + ren_table->db, old_alias); + } + } + } break; } case FRMTYPE_VIEW: diff --git a/sql/sql_table.cc b/sql/sql_table.cc index de350b83985..c4b45e96ad7 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -3287,6 +3287,13 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, close_cached_table(thd, table); if (mysql_rename_table(old_db_type,db,table_name,new_db,new_alias)) error= -1; + else if (Table_triggers_list::change_table_name(thd, db, table_name, + new_db, new_alias)) + { + VOID(mysql_rename_table(old_db_type, new_db, new_alias, db, + table_name)); + error= -1; + } } VOID(pthread_mutex_unlock(&LOCK_open)); } @@ -3835,7 +3842,11 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, VOID(quick_rm_table(new_db_type,new_db,tmp_name)); } else if (mysql_rename_table(new_db_type,new_db,tmp_name,new_db, - new_alias)) + new_alias) || + (new_name != table_name || new_db != db) && // we also do rename + Table_triggers_list::change_table_name(thd, db, table_name, + new_db, new_alias)) + { // Try to get everything back error=1; VOID(quick_rm_table(new_db_type,new_db,new_alias)); diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc index 53743314782..4c3ae5c032d 100644 --- a/sql/sql_trigger.cc +++ b/sql/sql_trigger.cc @@ -65,7 +65,6 @@ File_option sql_modes_parameters= */ static const int TRG_NUM_REQUIRED_PARAMETERS= 4; -static const int TRG_MAX_VERSIONS= 3; /* Structure representing contents of .TRN file which are used to support @@ -467,8 +466,7 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables, definer_host->str, NullS) - trg_definer->str; if (!sql_create_definition_file(&dir, &file, &triggers_file_type, - (gptr)this, triggers_file_parameters, - TRG_MAX_VERSIONS)) + (gptr)this, triggers_file_parameters, 0)) return 0; err_with_cleanup: @@ -492,7 +490,8 @@ err_with_cleanup: True - error */ -static bool rm_trigger_file(char *path, char *db, char *table_name) +static bool rm_trigger_file(char *path, const char *db, + const char *table_name) { strxnmov(path, FN_REFLEN, mysql_data_home, "/", db, "/", table_name, triggers_file_ext, NullS); @@ -516,7 +515,8 @@ static bool rm_trigger_file(char *path, char *db, char *table_name) True - error */ -static bool rm_trigname_file(char *path, char *db, char *trigger_name) +static bool rm_trigname_file(char *path, const char *db, + const char *trigger_name) { strxnmov(path, FN_REFLEN, mysql_data_home, "/", db, "/", trigger_name, trigname_file_ext, NullS); @@ -526,6 +526,38 @@ static bool rm_trigname_file(char *path, char *db, char *trigger_name) /* + Helper function that saves .TRG file for Table_triggers_list object. + + SYNOPSIS + save_trigger_file() + triggers Table_triggers_list object for which file should be saved + db Name of database for subject table + table_name Name of subject table + + RETURN VALUE + FALSE Success + TRUE Error +*/ + +static bool save_trigger_file(Table_triggers_list *triggers, const char *db, + const char *table_name) +{ + char dir_buff[FN_REFLEN], file_buff[FN_REFLEN]; + LEX_STRING dir, file; + + strxnmov(dir_buff, FN_REFLEN, mysql_data_home, "/", db, "/", NullS); + dir.length= unpack_filename(dir_buff, dir_buff); + dir.str= dir_buff; + file.length= strxnmov(file_buff, FN_REFLEN, table_name, triggers_file_ext, + NullS) - file_buff; + file.str= file_buff; + + return sql_create_definition_file(&dir, &file, &triggers_file_type, + (gptr)triggers, triggers_file_parameters, 0); +} + + +/* Drop trigger for table. SYNOPSIS @@ -578,20 +610,7 @@ bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables) } else { - char dir_buff[FN_REFLEN], file_buff[FN_REFLEN]; - LEX_STRING dir, file; - - strxnmov(dir_buff, FN_REFLEN, mysql_data_home, "/", tables->db, - "/", NullS); - dir.length= unpack_filename(dir_buff, dir_buff); - dir.str= dir_buff; - file.length= strxnmov(file_buff, FN_REFLEN, tables->table_name, - triggers_file_ext, NullS) - file_buff; - file.str= file_buff; - - if (sql_create_definition_file(&dir, &file, &triggers_file_type, - (gptr)this, triggers_file_parameters, - TRG_MAX_VERSIONS)) + if (save_trigger_file(this, tables->db, tables->table_name)) return 1; } @@ -831,12 +850,12 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, if (!names_only && triggers->prepare_record1_accessors(table)) DBUG_RETURN(1); - char *trg_name_buff; List_iterator_fast<ulonglong> itm(triggers->definition_modes_list); List_iterator_fast<LEX_STRING> it_definer(triggers->definers_list); LEX *old_lex= thd->lex, lex; sp_rcontext *save_spcont= thd->spcont; ulong save_sql_mode= thd->variables.sql_mode; + LEX_STRING *on_table_name; thd->lex= &lex; @@ -902,6 +921,21 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db, &table->mem_root)) goto err_with_lex_cleanup; + if (!(on_table_name= (LEX_STRING*) alloc_root(&table->mem_root, + sizeof(LEX_STRING)))) + goto err_with_lex_cleanup; + *on_table_name= lex.ident; + if (triggers->on_table_names_list.push_back(on_table_name, &table->mem_root)) + goto err_with_lex_cleanup; + + /* + Let us check that we correctly update trigger definitions when we + rename tables with triggers. + */ + DBUG_ASSERT(!my_strcasecmp(table_alias_charset, lex.query_tables->db, db) && + !my_strcasecmp(table_alias_charset, lex.query_tables->table_name, + table_name)); + if (names_only) { lex_end(&lex); @@ -1067,7 +1101,7 @@ static TABLE_LIST *add_table_for_trigger(THD *thd, sp_name *trig) 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_WRITE)); + trigname.trigger_table.str, TL_IGNORE)); } @@ -1137,6 +1171,220 @@ end: } +/* + Update .TRG file after renaming triggers' subject table + (change name of table in triggers' definitions). + + SYNOPSIS + change_table_name_in_triggers() + thd Thread context + db_name Database of subject table + old_table_name Old subject table's name + new_table_name New subject table's name + + RETURN VALUE + FALSE Success + TRUE Failure +*/ + +bool +Table_triggers_list::change_table_name_in_triggers(THD *thd, + const char *db_name, + LEX_STRING *old_table_name, + LEX_STRING *new_table_name) +{ + char path_buff[FN_REFLEN]; + LEX_STRING *def, *on_table_name, new_def; + ulonglong *sql_mode; + ulong save_sql_mode= thd->variables.sql_mode; + List_iterator_fast<LEX_STRING> it_def(definitions_list); + List_iterator_fast<LEX_STRING> it_on_table_name(on_table_names_list); + List_iterator_fast<ulonglong> it_mode(definition_modes_list); + uint on_q_table_name_len, before_on_len; + String buff; + + DBUG_ASSERT(definitions_list.elements == on_table_names_list.elements && + definitions_list.elements == definition_modes_list.elements); + + while ((def= it_def++)) + { + on_table_name= it_on_table_name++; + thd->variables.sql_mode= *(it_mode++); + + /* Construct CREATE TRIGGER statement with new table name. */ + buff.length(0); + before_on_len= on_table_name->str - def->str; + buff.append(def->str, before_on_len); + buff.append(STRING_WITH_LEN("ON ")); + append_identifier(thd, &buff, new_table_name->str, new_table_name->length); + on_q_table_name_len= buff.length() - before_on_len; + buff.append(on_table_name->str + on_table_name->length, + def->length - (before_on_len + on_table_name->length)); + /* + It is OK to allocate some memory on table's MEM_ROOT since this + table instance will be thrown out at the end of rename anyway. + */ + new_def.str= memdup_root(&table->mem_root, buff.ptr(), buff.length()); + new_def.length= buff.length(); + on_table_name->str= new_def.str + before_on_len; + on_table_name->length= on_q_table_name_len; + *def= new_def; + } + + thd->variables.sql_mode= save_sql_mode; + + if (thd->is_fatal_error) + return TRUE; /* OOM */ + + if (save_trigger_file(this, db_name, new_table_name->str)) + return TRUE; + if (rm_trigger_file(path_buff, db_name, old_table_name->str)) + { + (void) rm_trigger_file(path_buff, db_name, new_table_name->str); + return TRUE; + } + return FALSE; +} + + +/* + Iterate though Table_triggers_list::names_list list and update .TRN files + after renaming triggers' subject table. + + SYNOPSIS + change_table_name_in_trignames() + db_name Database of subject table + new_table_name New subject table's name + stopper Pointer to Table_triggers_list::names_list at + which we should stop updating. + + RETURN VALUE + 0 Success + non-0 Failure, pointer to Table_triggers_list::names_list element + for which update failed. +*/ + +LEX_STRING* +Table_triggers_list::change_table_name_in_trignames(const char *db_name, + LEX_STRING *new_table_name, + LEX_STRING *stopper) +{ + char dir_buff[FN_REFLEN], trigname_buff[FN_REFLEN]; + struct st_trigname trigname; + LEX_STRING dir, trigname_file; + LEX_STRING *trigger; + List_iterator_fast<LEX_STRING> it_name(names_list); + + strxnmov(dir_buff, FN_REFLEN, mysql_data_home, "/", db_name, "/", NullS); + dir.length= unpack_filename(dir_buff, dir_buff); + dir.str= dir_buff; + + while ((trigger= it_name++) != stopper) + { + trigname_file.length= strxnmov(trigname_buff, FN_REFLEN, trigger->str, + trigname_file_ext, NullS) - trigname_buff; + trigname_file.str= trigname_buff; + + trigname.trigger_table= *new_table_name; + + if (sql_create_definition_file(&dir, &trigname_file, &trigname_file_type, + (gptr)&trigname, trigname_file_parameters, 0)) + return trigger; + } + + return 0; +} + + +/* + Update .TRG and .TRN files after renaming triggers' subject table. + + SYNOPSIS + change_table_name() + thd Thread context + db Old database of subject table + old_table Old name of subject table + new_db New database for subject table + new_table New name of subject table + + NOTE + This method tries to leave trigger related files in consistent state, + i.e. it either will complete successfully, or will fail leaving files + in their initial state. + + RETURN VALUE + FALSE Success + TRUE Error +*/ + +bool Table_triggers_list::change_table_name(THD *thd, const char *db, + const char *old_table, + const char *new_db, + const char *new_table) +{ + TABLE table; + bool result= 0; + LEX_STRING *err_trigname; + DBUG_ENTER("change_table_name"); + + bzero(&table, sizeof(table)); + init_alloc_root(&table.mem_root, 8192, 0); + + safe_mutex_assert_owner(&LOCK_open); + + if (Table_triggers_list::check_n_load(thd, db, old_table, &table, TRUE)) + { + result= 1; + goto end; + } + if (table.triggers) + { + LEX_STRING_WITH_INIT old_table_name(old_table, strlen(old_table)); + LEX_STRING_WITH_INIT new_table_name(new_table, strlen(new_table)); + /* + Since triggers should be in the same schema as their subject tables + moving table with them between two schemas raises too many questions. + (E.g. what should happen if in new schema we already have trigger + with same name ?). + */ + if (my_strcasecmp(table_alias_charset, db, new_db)) + { + my_error(ER_TRG_IN_WRONG_SCHEMA, MYF(0)); + result= 1; + goto end; + } + if (table.triggers->change_table_name_in_triggers(thd, db, + &old_table_name, + &new_table_name)) + { + result= 1; + goto end; + } + if ((err_trigname= table.triggers->change_table_name_in_trignames( + db, &new_table_name, 0))) + { + /* + If we were unable to update one of .TRN files properly we will + revert all changes that we have done and report about error. + We assume that we will be able to undo our changes without errors + (we can't do much if there will be an error anyway). + */ + (void) table.triggers->change_table_name_in_trignames(db, + &old_table_name, + err_trigname); + (void) table.triggers->change_table_name_in_triggers(thd, db, + &new_table_name, + &old_table_name); + result= 1; + goto end; + } + } +end: + delete table.triggers; + free_root(&table.mem_root, MYF(0)); + DBUG_RETURN(result); +} + bool Table_triggers_list::process_triggers(THD *thd, trg_event_type event, trg_action_time_type time_type, diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h index 8992de63b37..b67c22e0588 100644 --- a/sql/sql_trigger.h +++ b/sql/sql_trigger.h @@ -47,6 +47,11 @@ class Table_triggers_list: public Sql_alloc */ List<LEX_STRING> names_list; /* + List of "ON table_name" parts in trigger definitions, used for + updating trigger definitions during RENAME TABLE. + */ + List<LEX_STRING> on_table_names_list; + /* Key representing triggers for this table in set of all stored routines used by statement. TODO: We won't need this member once triggers namespace will be @@ -97,7 +102,10 @@ public: static bool check_n_load(THD *thd, const char *db, const char *table_name, TABLE *table, bool names_only); static bool drop_all_triggers(THD *thd, char *db, char *table_name); - + static bool change_table_name(THD *thd, const char *db, + const char *old_table, + const char *new_db, + const char *new_table); bool has_delete_triggers() { return (bodies[TRG_EVENT_DELETE][TRG_ACTION_BEFORE] || @@ -117,6 +125,13 @@ public: private: bool prepare_record1_accessors(TABLE *table); + LEX_STRING* change_table_name_in_trignames(const char *db_name, + LEX_STRING *new_table_name, + LEX_STRING *stopper); + bool change_table_name_in_triggers(THD *thd, + const char *db_name, + LEX_STRING *old_table_name, + LEX_STRING *new_table_name); }; extern const LEX_STRING trg_action_time_type_names[]; diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy index 97410333c48..d6d2939bed3 100644 --- a/sql/sql_yacc.yy +++ b/sql/sql_yacc.yy @@ -9126,8 +9126,8 @@ view_check_option: **************************************************************************/ trigger_tail: - TRIGGER_SYM remember_name sp_name trg_action_time trg_event - ON table_ident FOR_SYM EACH_SYM ROW_SYM + TRIGGER_SYM remember_name sp_name trg_action_time trg_event + ON remember_name table_ident remember_end FOR_SYM EACH_SYM ROW_SYM { LEX *lex= Lex; sp_head *sp; @@ -9144,7 +9144,9 @@ trigger_tail: sp->init(lex); lex->trigger_definition_begin= $2; - + lex->ident.str= $7; + lex->ident.length= $9 - $7; + sp->m_type= TYPE_ENUM_TRIGGER; lex->sphead= sp; lex->spname= $3; @@ -9181,15 +9183,11 @@ trigger_tail: We have to do it after parsing trigger body, because some of sp_proc_stmt alternatives are not saving/restoring LEX, so lex->query_tables can be wiped out. - - QQ: What are other consequences of this? - - QQ: Could we loosen lock type in certain cases ? */ - if (!lex->select_lex.add_table_to_list(YYTHD, $7, + if (!lex->select_lex.add_table_to_list(YYTHD, $8, (LEX_STRING*) 0, TL_OPTION_UPDATING, - TL_WRITE)) + TL_IGNORE)) YYABORT; } ; |