diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/backend/commands/tablecmds.c | 28 | ||||
| -rw-r--r-- | src/test/regress/expected/foreign_key.out | 32 | ||||
| -rw-r--r-- | src/test/regress/sql/foreign_key.sql | 22 | 
3 files changed, 75 insertions, 7 deletions
| diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 64141c03408..85fc2793b87 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -5496,13 +5496,6 @@ createForeignKeyTriggers(Relation rel, Constraint *fkconstraint,  	CommandCounterIncrement();  	/* -	 * Build and execute a CREATE CONSTRAINT TRIGGER statement for the CHECK -	 * action for both INSERTs and UPDATEs on the referencing table. -	 */ -	CreateFKCheckTrigger(myRel, fkconstraint, constraintOid, indexOid, true); -	CreateFKCheckTrigger(myRel, fkconstraint, constraintOid, indexOid, false); - -	/*  	 * Build and execute a CREATE CONSTRAINT TRIGGER statement for the ON  	 * DELETE action on the referenced table.  	 */ @@ -5604,6 +5597,27 @@ createForeignKeyTriggers(Relation rel, Constraint *fkconstraint,  	fk_trigger->args = NIL;  	(void) CreateTrigger(fk_trigger, NULL, constraintOid, indexOid, true); + +	/* Make changes-so-far visible */ +	CommandCounterIncrement(); + +	/* +	 * Build and execute CREATE CONSTRAINT TRIGGER statements for the CHECK +	 * action for both INSERTs and UPDATEs on the referencing table. +	 * +	 * Note: for a self-referential FK (referencing and referenced tables are +	 * the same), it is important that the ON UPDATE action fires before the +	 * CHECK action, since both triggers will fire on the same row during an +	 * UPDATE event; otherwise the CHECK trigger will be checking a non-final +	 * state of the row.  Because triggers fire in name order, we are +	 * effectively relying on the OIDs of the triggers to sort correctly as +	 * text.  This will work except when the OID counter wraps around or adds +	 * a digit, eg "99999" sorts after "100000".  That is infrequent enough, +	 * and the use of self-referential FKs is rare enough, that we live with +	 * it for now.  There will be a real fix in PG 9.2. +	 */ +	CreateFKCheckTrigger(myRel, fkconstraint, constraintOid, indexOid, true); +	CreateFKCheckTrigger(myRel, fkconstraint, constraintOid, indexOid, false);  }  /* diff --git a/src/test/regress/expected/foreign_key.out b/src/test/regress/expected/foreign_key.out index 0367f532337..4a9d054d4a0 100644 --- a/src/test/regress/expected/foreign_key.out +++ b/src/test/regress/expected/foreign_key.out @@ -1287,3 +1287,35 @@ SELECT * FROM tasks;  (3 rows)  COMMIT; +-- +-- Test self-referential FK with CASCADE (bug #6268) +-- +create temp table selfref ( +    a int primary key, +    b int, +    foreign key (b) references selfref (a) +        on update cascade on delete cascade +); +NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "selfref_pkey" for table "selfref" +insert into selfref (a, b) +values +    (0, 0), +    (1, 1); +begin; +    update selfref set a = 123 where a = 0; +    select a, b from selfref; +  a  |  b   +-----+----- +   1 |   1 + 123 | 123 +(2 rows) + +    update selfref set a = 456 where a = 123; +    select a, b from selfref; +  a  |  b   +-----+----- +   1 |   1 + 456 | 456 +(2 rows) + +commit; diff --git a/src/test/regress/sql/foreign_key.sql b/src/test/regress/sql/foreign_key.sql index cc7b23f113a..2e94c41ff78 100644 --- a/src/test/regress/sql/foreign_key.sql +++ b/src/test/regress/sql/foreign_key.sql @@ -921,3 +921,25 @@ SELECT * FROM tasks;  DELETE FROM users WHERE id = 2;  SELECT * FROM tasks;  COMMIT; + +-- +-- Test self-referential FK with CASCADE (bug #6268) +-- +create temp table selfref ( +    a int primary key, +    b int, +    foreign key (b) references selfref (a) +        on update cascade on delete cascade +); + +insert into selfref (a, b) +values +    (0, 0), +    (1, 1); + +begin; +    update selfref set a = 123 where a = 0; +    select a, b from selfref; +    update selfref set a = 456 where a = 123; +    select a, b from selfref; +commit; | 
