8000 Check for pending trigger events on far end when dropping an FK const… · phan-pivotal/postgres@6a363a4 · GitHub
[go: up one dir, main page]

Skip to content

Commit 6a363a4

Browse files
committed
Check for pending trigger events on far end when dropping an FK constraint.
When dropping a foreign key constraint with ALTER TABLE DROP CONSTRAINT, we refuse the drop if there are any pending trigger events on the named table; this ensures that we won't remove the pg_trigger row that will be consulted by those events. But we should make the same check for the referenced relation, else we might remove a due-to-be-referenced pg_trigger row for that relation too, resulting in "could not find trigger NNN" or "relation NNN has no triggers" errors at commit. Per bug #14431 from Benjie Gillam. Back-patch to all supported branches. Report: <20161124114911.6530.31200@wrigleys.postgresql.org>
1 parent 05975ab commit 6a363a4

File tree

3 files changed

+44
-0
lines changed

3 files changed

+44
-0
lines changed

src/backend/commands/tablecmds.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6989,6 +6989,24 @@ ATExecDropConstraint(Relation rel, const char *constrName,
69896989
if (con->contype != CONSTRAINT_CHECK)
69906990
is_no_inherit_constraint = true;
69916991

6992+
/*
6993+
* If it's a foreign-key constraint, we'd better lock the referenced
6994+
* table and check that that's not in use, just as we've already done
6995+
* for the constrained table (else we might, eg, be dropping a trigger
6996+
* that has unfired events). But we can/must skip that in the
6997+
* self-referential case.
6998+
*/
6999+
if (con->contype == CONSTRAINT_FOREIGN &&
7000+
con->confrelid != RelationGetRelid(rel))
7001+
{
7002+
Relation frel;
7003+
7004+
/* Must match lock taken by RemoveTriggerById: */
7005+
frel = heap_open(con->confrelid, AccessExclusiveLock);
7006+
CheckTableNotInUse(frel, "ALTER TABLE");
7007+
heap_close(frel, NoLock);
7008+
}
7009+
69927010
/*
69937011
* Perform the actual constraint deletion
69947012
*/

src/test/regress/expected/foreign_key.out

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1340,4 +1340,17 @@ rollback to x;
13401340
commit; -- fail
13411341
ERROR: insert or update on table "fktable2" violates foreign key constraint "fktable2_f1_fkey"
13421342
DETAIL: Key (f1)=(2) is not present in table "pktable2".
1343+
--
1344+
-- Test that we prevent dropping FK constraint with pending trigger events
1345+
--
1346+
begin;
1347+
insert into fktable2 values(2);
1348+
alter table fktable2 drop constraint fktable2_f1_fkey;
1349+
ERROR: cannot ALTER TABLE "fktable2" because it has pending trigger events
1350+
commit;
1351+
begin;
1352+
delete from pktable2 where f1 = 1;
1353+
alter table fktable2 drop constraint fktable2_f1_fkey;
1354+
ERROR: cannot ALTER TABLE "pktable2" because it has pending trigger events
1355+
commit;
13431356
drop table pktable2, fktable2;

src/test/regress/sql/foreign_key.sql

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -965,4 +965,17 @@ delete from fktable2;
965965
rollback to x;
966966
commit; -- fail
967967

968+
--
969+
-- Test that we prevent dropping FK constraint with pending trigger events
970+
--
971+
begin;
972+
insert into fktable2 values(2);
973+
alter table fktable2 drop constraint fktable2_f1_fkey;
974+
commit;
975+
976+
begin;
977+
delete from pktable2 where f1 = 1;
978+
alter table fktable2 drop constraint fktable2_f1_fkey;
979+
commit;
980+
968981
drop table pktable2, fktable2;

0 commit comments

Comments
 (0)
0