Commit 138e34cf authored by unknown's avatar unknown

Fix for bug #17866 "Problem with renaming table with triggers with fully

qualified subject table" which was introduced during work on bug #13525
"Rename table does not keep info of triggers".

The bug was caused by the fact that during reconstruction of CREATE TRIGGER
statement stored in .TRG file which happened during RENAME TABLE we damaged
trigger definition in case when it contained fully qualified name of subject
table (see comment for sql_yacc.yy for more info).


mysql-test/r/trigger.result:
  Added test for bug #17866 "Problem with renaming table with triggers with fully
  qualified subject table".
mysql-test/t/trigger.test:
  Added test for bug #17866 "Problem with renaming table with triggers with fully
  qualified subject table".
sql/sql_trigger.cc:
  Table_triggers_list::change_table_name_in_triggers():
    Instead of trying to use pointer to the end of subject table identifier
    we use pointer to the beginning of FOR lexeme now, so during reconstruction
    of CREATE TRIGGER statement in this function we need to add extra space
    before part which begins with FOR to get nice trigger definition.
sql/sql_yacc.yy:
  trigger_tail:
    In this rule we can't rely on using remember_end token after table_ident token,
    since value returned depends on whether table name is fully qualified or not.
    So instead of trying to get pointer to the end of table identifier we use
    pointer to the beginning of FOR lexeme.
parent 3f73bc43
...@@ -787,46 +787,52 @@ drop trigger t1_bi; ...@@ -787,46 +787,52 @@ drop trigger t1_bi;
ERROR 3D000: No database selected ERROR 3D000: No database selected
create table t1 (id int); create table t1 (id int);
create trigger t1_bi before insert on t1 for each row set @a:=new.id; create trigger t1_bi before insert on t1 for each row set @a:=new.id;
create trigger t1_ai after insert on test.t1 for each row set @b:=new.id;
insert into t1 values (101); insert into t1 values (101);
select @a; select @a, @b;
@a @a @b
101 101 101
select trigger_schema, trigger_name, event_object_schema, select trigger_schema, trigger_name, event_object_schema,
event_object_table, action_statement from information_schema.triggers event_object_table, action_statement from information_schema.triggers
where event_object_schema = 'test'; where event_object_schema = 'test';
trigger_schema trigger_name event_object_schema event_object_table action_statement trigger_schema trigger_name event_object_schema event_object_table action_statement
test t1_bi test t1 set @a:=new.id test t1_bi test t1 set @a:=new.id
test t1_ai test t1 set @b:=new.id
rename table t1 to t2; rename table t1 to t2;
insert into t2 values (102); insert into t2 values (102);
select @a; select @a, @b;
@a @a @b
102 102 102
select trigger_schema, trigger_name, event_object_schema, select trigger_schema, trigger_name, event_object_schema,
event_object_table, action_statement from information_schema.triggers event_object_table, action_statement from information_schema.triggers
where event_object_schema = 'test'; where event_object_schema = 'test';
trigger_schema trigger_name event_object_schema event_object_table action_statement trigger_schema trigger_name event_object_schema event_object_table action_statement
test t1_bi test t2 set @a:=new.id test t1_bi test t2 set @a:=new.id
test t1_ai test t2 set @b:=new.id
alter table t2 rename to t3; alter table t2 rename to t3;
insert into t3 values (103); insert into t3 values (103);
select @a; select @a, @b;
@a @a @b
103 103 103
select trigger_schema, trigger_name, event_object_schema, select trigger_schema, trigger_name, event_object_schema,
event_object_table, action_statement from information_schema.triggers event_object_table, action_statement from information_schema.triggers
where event_object_schema = 'test'; where event_object_schema = 'test';
trigger_schema trigger_name event_object_schema event_object_table action_statement trigger_schema trigger_name event_object_schema event_object_table action_statement
test t1_bi test t3 set @a:=new.id test t1_bi test t3 set @a:=new.id
test t1_ai test t3 set @b:=new.id
alter table t3 rename to t4, add column val int default 0; alter table t3 rename to t4, add column val int default 0;
insert into t4 values (104, 1); insert into t4 values (104, 1);
select @a; select @a, @b;
@a @a @b
104 104 104
select trigger_schema, trigger_name, event_object_schema, select trigger_schema, trigger_name, event_object_schema,
event_object_table, action_statement from information_schema.triggers event_object_table, action_statement from information_schema.triggers
where event_object_schema = 'test'; where event_object_schema = 'test';
trigger_schema trigger_name event_object_schema event_object_table action_statement trigger_schema trigger_name event_object_schema event_object_table action_statement
test t1_bi test t4 set @a:=new.id test t1_bi test t4 set @a:=new.id
test t1_ai test t4 set @b:=new.id
drop trigger t1_bi; drop trigger t1_bi;
drop trigger t1_ai;
drop table t4; drop table t4;
create database mysqltest; create database mysqltest;
use mysqltest; use mysqltest;
......
...@@ -960,38 +960,42 @@ drop trigger t1_bi; ...@@ -960,38 +960,42 @@ drop trigger t1_bi;
connection default; connection default;
# #
# Test for bug #13525 "Rename table does not keep info of triggers" # Tests for bug #13525 "Rename table does not keep info of triggers"
# and bug #17866 "Problem with renaming table with triggers with fully
# qualified subject table".
# #
create table t1 (id int); create table t1 (id int);
create trigger t1_bi before insert on t1 for each row set @a:=new.id; create trigger t1_bi before insert on t1 for each row set @a:=new.id;
create trigger t1_ai after insert on test.t1 for each row set @b:=new.id;
insert into t1 values (101); insert into t1 values (101);
select @a; select @a, @b;
select trigger_schema, trigger_name, event_object_schema, select trigger_schema, trigger_name, event_object_schema,
event_object_table, action_statement from information_schema.triggers event_object_table, action_statement from information_schema.triggers
where event_object_schema = 'test'; where event_object_schema = 'test';
rename table t1 to t2; rename table t1 to t2;
# Trigger should work after rename # Trigger should work after rename
insert into t2 values (102); insert into t2 values (102);
select @a; select @a, @b;
select trigger_schema, trigger_name, event_object_schema, select trigger_schema, trigger_name, event_object_schema,
event_object_table, action_statement from information_schema.triggers event_object_table, action_statement from information_schema.triggers
where event_object_schema = 'test'; where event_object_schema = 'test';
# Let us check that the same works for simple ALTER TABLE ... RENAME # Let us check that the same works for simple ALTER TABLE ... RENAME
alter table t2 rename to t3; alter table t2 rename to t3;
insert into t3 values (103); insert into t3 values (103);
select @a; select @a, @b;
select trigger_schema, trigger_name, event_object_schema, select trigger_schema, trigger_name, event_object_schema,
event_object_table, action_statement from information_schema.triggers event_object_table, action_statement from information_schema.triggers
where event_object_schema = 'test'; where event_object_schema = 'test';
# And for more complex ALTER TABLE # And for more complex ALTER TABLE
alter table t3 rename to t4, add column val int default 0; alter table t3 rename to t4, add column val int default 0;
insert into t4 values (104, 1); insert into t4 values (104, 1);
select @a; select @a, @b;
select trigger_schema, trigger_name, event_object_schema, select trigger_schema, trigger_name, event_object_schema,
event_object_table, action_statement from information_schema.triggers event_object_table, action_statement from information_schema.triggers
where event_object_schema = 'test'; where event_object_schema = 'test';
# .TRN file should be updated with new table name # .TRN file should be updated with new table name
drop trigger t1_bi; drop trigger t1_bi;
drop trigger t1_ai;
drop table t4; drop table t4;
# Rename between different databases if triggers exist should fail # Rename between different databases if triggers exist should fail
create database mysqltest; create database mysqltest;
......
...@@ -1217,6 +1217,7 @@ Table_triggers_list::change_table_name_in_triggers(THD *thd, ...@@ -1217,6 +1217,7 @@ Table_triggers_list::change_table_name_in_triggers(THD *thd,
buff.append(def->str, before_on_len); buff.append(def->str, before_on_len);
buff.append(STRING_WITH_LEN("ON ")); buff.append(STRING_WITH_LEN("ON "));
append_identifier(thd, &buff, new_table_name->str, new_table_name->length); append_identifier(thd, &buff, new_table_name->str, new_table_name->length);
buff.append(STRING_WITH_LEN(" "));
on_q_table_name_len= buff.length() - before_on_len; on_q_table_name_len= buff.length() - before_on_len;
buff.append(on_table_name->str + on_table_name->length, buff.append(on_table_name->str + on_table_name->length,
def->length - (before_on_len + on_table_name->length)); def->length - (before_on_len + on_table_name->length));
......
...@@ -9127,7 +9127,7 @@ view_check_option: ...@@ -9127,7 +9127,7 @@ view_check_option:
trigger_tail: trigger_tail:
TRIGGER_SYM remember_name sp_name trg_action_time trg_event TRIGGER_SYM remember_name sp_name trg_action_time trg_event
ON remember_name table_ident remember_end FOR_SYM EACH_SYM ROW_SYM ON remember_name table_ident FOR_SYM remember_name EACH_SYM ROW_SYM
{ {
LEX *lex= Lex; LEX *lex= Lex;
sp_head *sp; sp_head *sp;
...@@ -9145,7 +9145,7 @@ trigger_tail: ...@@ -9145,7 +9145,7 @@ trigger_tail:
lex->trigger_definition_begin= $2; lex->trigger_definition_begin= $2;
lex->ident.str= $7; lex->ident.str= $7;
lex->ident.length= $9 - $7; lex->ident.length= $10 - $7;
sp->m_type= TYPE_ENUM_TRIGGER; sp->m_type= TYPE_ENUM_TRIGGER;
lex->sphead= sp; lex->sphead= sp;
......
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