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>
This commit is contained in:
Tom Lane 2016-11-25 13:44:48 -05:00
parent 7816d13563
commit 6cbe84c826
3 changed files with 44 additions and 0 deletions

View File

@ -7688,6 +7688,24 @@ ATExecDropConstraint(Relation rel, const char *constrName,
is_no_inherit_constraint = con->connoinherit;
/*
* If it's a foreign-key constraint, we'd better lock the referenced
* table and check that that's not in use, just as we've already done
* for the constrained table (else we might, eg, be dropping a trigger
* that has unfired events). But we can/must skip that in the
* self-referential case.
*/
if (con->contype == CONSTRAINT_FOREIGN &&
con->confrelid != RelationGetRelid(rel))
{
Relation frel;
/* Must match lock taken by RemoveTriggerById: */
frel = heap_open(con->confrelid, AccessExclusiveLock);
CheckTableNotInUse(frel, "ALTER TABLE");
heap_close(frel, NoLock);
}
/*
* Perform the actual constraint deletion
*/

View File

@ -1379,4 +1379,17 @@ rollback to x;
commit; -- fail
ERROR: insert or update on table "fktable2" violates foreign key constraint "fktable2_f1_fkey"
DETAIL: Key (f1)=(2) is not present in table "pktable2".
--
-- Test that we prevent dropping FK constraint with pending trigger events
--
begin;
insert into fktable2 values(2);
alter table fktable2 drop constraint fktable2_f1_fkey;
ERROR: cannot ALTER TABLE "fktable2" because it has pending trigger events
commit;
begin;
delete from pktable2 where f1 = 1;
alter table fktable2 drop constraint fktable2_f1_fkey;
ERROR: cannot ALTER TABLE "pktable2" because it has pending trigger events
commit;
drop table pktable2, fktable2;

View File

@ -1031,4 +1031,17 @@ delete from fktable2;
rollback to x;
commit; -- fail
--
-- Test that we prevent dropping FK constraint with pending trigger events
--
begin;
insert into fktable2 values(2);
alter table fktable2 drop constraint fktable2_f1_fkey;
commit;
begin;
delete from pktable2 where f1 = 1;
alter table fktable2 drop constraint fktable2_f1_fkey;
commit;
drop table pktable2, fktable2;