From aab47baf6c0d818f550abd59d43003be3602e741 Mon Sep 17 00:00:00 2001 From: Tom Lane Date: Thu, 3 Oct 2002 21:06:23 +0000 Subject: [PATCH] Hack to make it possible to load CREATE CONSTRAINT TRIGGER commands that are missing the FROM clause (due to a long-ago pg_dump bug). Patch by Stephan Szabo, minor tweaking by Tom Lane. --- src/backend/commands/trigger.c | 47 +++++++++++++++-- src/backend/utils/adt/ri_triggers.c | 79 ++++++++++++++++++++++++++++- 2 files changed, 120 insertions(+), 6 deletions(-) diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index fcc16c4342..4af8a9f9cd 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.133 2002/09/23 22:57:44 tgl Exp $ + * $Header: /cvsroot/pgsql/src/backend/commands/trigger.c,v 1.134 2002/10/03 21:06:23 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -28,6 +28,7 @@ #include "commands/trigger.h" #include "executor/executor.h" #include "miscadmin.h" +#include "nodes/makefuncs.h" #include "parser/parse_func.h" #include "utils/acl.h" #include "utils/builtins.h" @@ -83,7 +84,7 @@ CreateTrigger(CreateTrigStmt *stmt, bool forConstraint) char constrtrigname[NAMEDATALEN]; char *trigname; char *constrname; - Oid constrrelid; + Oid constrrelid = InvalidOid; ObjectAddress myself, referenced; @@ -91,8 +92,46 @@ CreateTrigger(CreateTrigStmt *stmt, bool forConstraint) if (stmt->constrrel != NULL) constrrelid = RangeVarGetRelid(stmt->constrrel, false); - else - constrrelid = InvalidOid; + else if (stmt->isconstraint) + { + /* + * If this trigger is a constraint (and a foreign key one) + * then we really need a constrrelid. Since we don't have one, + * we'll try to generate one from the argument information. + * + * This is really just a workaround for a long-ago pg_dump bug + * that omitted the FROM clause in dumped CREATE CONSTRAINT TRIGGER + * commands. We don't want to bomb out completely here if we can't + * determine the correct relation, because that would prevent loading + * the dump file. Instead, NOTICE here and ERROR in the trigger. + */ + bool needconstrrelid = false; + void *elem = NULL; + + if (strncmp(strVal(llast(stmt->funcname)), "RI_FKey_check_", 14) == 0) + { + /* A trigger on FK table. */ + needconstrrelid = true; + if (length(stmt->args) > RI_PK_RELNAME_ARGNO) + elem = nth(RI_PK_RELNAME_ARGNO, stmt->args); + } + else if (strncmp(strVal(llast(stmt->funcname)), "RI_FKey_", 8) == 0) + { + /* A trigger on PK table. */ + needconstrrelid = true; + if (length(stmt->args) > RI_FK_RELNAME_ARGNO) + elem = nth(RI_FK_RELNAME_ARGNO, stmt->args); + } + if (elem != NULL) + { + RangeVar *rel = makeRangeVar(NULL, strVal(elem)); + + constrrelid = RangeVarGetRelid(rel, true); + } + if (needconstrrelid && constrrelid == InvalidOid) + elog(NOTICE, "Unable to find table for constraint \"%s\"", + stmt->trigname); + } if (rel->rd_rel->relkind != RELKIND_RELATION) elog(ERROR, "CreateTrigger: relation \"%s\" is not a table", diff --git a/src/backend/utils/adt/ri_triggers.c b/src/backend/utils/adt/ri_triggers.c index d66fe4d95d..76cc1bdb54 100644 --- a/src/backend/utils/adt/ri_triggers.c +++ b/src/backend/utils/adt/ri_triggers.c @@ -17,7 +17,7 @@ * * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group * - * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.42 2002/09/04 20:31:28 momjian Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/adt/ri_triggers.c,v 1.43 2002/10/03 21:06:23 tgl Exp $ * * ---------- */ @@ -207,9 +207,18 @@ RI_FKey_check(PG_FUNCTION_ARGS) * * pk_rel is opened in RowShareLock mode since that's what our eventual * SELECT FOR UPDATE will get on it. + * + * Error check here is needed because of ancient pg_dump bug; see notes + * in CreateTrigger(). */ - fk_rel = trigdata->tg_relation; + if (!OidIsValid(trigdata->tg_trigger->tgconstrrelid)) + elog(ERROR, "No target table given for trigger \"%s\" on \"%s\"" + "\n\tRemove these RI triggers and do ALTER TABLE ADD CONSTRAINT", + trigdata->tg_trigger->tgname, + RelationGetRelationName(trigdata->tg_relation)); + pk_rel = heap_open(trigdata->tg_trigger->tgconstrrelid, RowShareLock); + fk_rel = trigdata->tg_relation; if (TRIGGER_FIRED_BY_UPDATE(trigdata->tg_event)) { old_row = trigdata->tg_trigtuple; @@ -745,6 +754,12 @@ RI_FKey_noaction_del(PG_FUNCTION_ARGS) * fk_rel is opened in RowShareLock mode since that's what our eventual * SELECT FOR UPDATE will get on it. */ + if (!OidIsValid(trigdata->tg_trigger->tgconstrrelid)) + elog(ERROR, "No target table given for trigger \"%s\" on \"%s\"" + "\n\tRemove these RI triggers and do ALTER TABLE ADD CONSTRAINT", + trigdata->tg_trigger->tgname, + RelationGetRelationName(trigdata->tg_relation)); + fk_rel = heap_open(trigdata->tg_trigger->tgconstrrelid, RowShareLock); pk_rel = trigdata->tg_relation; old_row = trigdata->tg_trigtuple; @@ -969,6 +984,12 @@ RI_FKey_noaction_upd(PG_FUNCTION_ARGS) * fk_rel is opened in RowShareLock mode since that's what our eventual * SELECT FOR UPDATE will get on it. */ + if (!OidIsValid(trigdata->tg_trigger->tgconstrrelid)) + elog(ERROR, "No target table given for trigger \"%s\" on \"%s\"" + "\n\tRemove these RI triggers and do ALTER TABLE ADD CONSTRAINT", + trigdata->tg_trigger->tgname, + RelationGetRelationName(trigdata->tg_relation)); + fk_rel = heap_open(trigdata->tg_trigger->tgconstrrelid, RowShareLock); pk_rel = trigdata->tg_relation; new_row = trigdata->tg_newtuple; @@ -1199,6 +1220,12 @@ RI_FKey_cascade_del(PG_FUNCTION_ARGS) * fk_rel is opened in RowExclusiveLock mode since that's what our * eventual DELETE will get on it. */ + if (!OidIsValid(trigdata->tg_trigger->tgconstrrelid)) + elog(ERROR, "No target table given for trigger \"%s\" on \"%s\"" + "\n\tRemove these RI triggers and do ALTER TABLE ADD CONSTRAINT", + trigdata->tg_trigger->tgname, + RelationGetRelationName(trigdata->tg_relation)); + fk_rel = heap_open(trigdata->tg_trigger->tgconstrrelid, RowExclusiveLock); pk_rel = trigdata->tg_relation; old_row = trigdata->tg_trigtuple; @@ -1401,6 +1428,12 @@ RI_FKey_cascade_upd(PG_FUNCTION_ARGS) * fk_rel is opened in RowExclusiveLock mode since that's what our * eventual UPDATE will get on it. */ + if (!OidIsValid(trigdata->tg_trigger->tgconstrrelid)) + elog(ERROR, "No target table given for trigger \"%s\" on \"%s\"" + "\n\tRemove these RI triggers and do ALTER TABLE ADD CONSTRAINT", + trigdata->tg_trigger->tgname, + RelationGetRelationName(trigdata->tg_relation)); + fk_rel = heap_open(trigdata->tg_trigger->tgconstrrelid, RowExclusiveLock); pk_rel = trigdata->tg_relation; new_row = trigdata->tg_newtuple; @@ -1639,6 +1672,12 @@ RI_FKey_restrict_del(PG_FUNCTION_ARGS) * fk_rel is opened in RowShareLock mode since that's what our eventual * SELECT FOR UPDATE will get on it. */ + if (!OidIsValid(trigdata->tg_trigger->tgconstrrelid)) + elog(ERROR, "No target table given for trigger \"%s\" on \"%s\"" + "\n\tRemove these RI triggers and do ALTER TABLE ADD CONSTRAINT", + trigdata->tg_trigger->tgname, + RelationGetRelationName(trigdata->tg_relation)); + fk_rel = heap_open(trigdata->tg_trigger->tgconstrrelid, RowShareLock); pk_rel = trigdata->tg_relation; old_row = trigdata->tg_trigtuple; @@ -1856,6 +1895,12 @@ RI_FKey_restrict_upd(PG_FUNCTION_ARGS) * fk_rel is opened in RowShareLock mode since that's what our eventual * SELECT FOR UPDATE will get on it. */ + if (!OidIsValid(trigdata->tg_trigger->tgconstrrelid)) + elog(ERROR, "No target table given for trigger \"%s\" on \"%s\"" + "\n\tRemove these RI triggers and do ALTER TABLE ADD CONSTRAINT", + trigdata->tg_trigger->tgname, + RelationGetRelationName(trigdata->tg_relation)); + fk_rel = heap_open(trigdata->tg_trigger->tgconstrrelid, RowShareLock); pk_rel = trigdata->tg_relation; new_row = trigdata->tg_newtuple; @@ -2078,6 +2123,12 @@ RI_FKey_setnull_del(PG_FUNCTION_ARGS) * fk_rel is opened in RowExclusiveLock mode since that's what our * eventual UPDATE will get on it. */ + if (!OidIsValid(trigdata->tg_trigger->tgconstrrelid)) + elog(ERROR, "No target table given for trigger \"%s\" on \"%s\"" + "\n\tRemove these RI triggers and do ALTER TABLE ADD CONSTRAINT", + trigdata->tg_trigger->tgname, + RelationGetRelationName(trigdata->tg_relation)); + fk_rel = heap_open(trigdata->tg_trigger->tgconstrrelid, RowExclusiveLock); pk_rel = trigdata->tg_relation; old_row = trigdata->tg_trigtuple; @@ -2291,6 +2342,12 @@ RI_FKey_setnull_upd(PG_FUNCTION_ARGS) * fk_rel is opened in RowExclusiveLock mode since that's what our * eventual UPDATE will get on it. */ + if (!OidIsValid(trigdata->tg_trigger->tgconstrrelid)) + elog(ERROR, "No target table given for trigger \"%s\" on \"%s\"" + "\n\tRemove these RI triggers and do ALTER TABLE ADD CONSTRAINT", + trigdata->tg_trigger->tgname, + RelationGetRelationName(trigdata->tg_relation)); + fk_rel = heap_open(trigdata->tg_trigger->tgconstrrelid, RowExclusiveLock); pk_rel = trigdata->tg_relation; new_row = trigdata->tg_newtuple; @@ -2550,6 +2607,12 @@ RI_FKey_setdefault_del(PG_FUNCTION_ARGS) * fk_rel is opened in RowExclusiveLock mode since that's what our * eventual UPDATE will get on it. */ + if (!OidIsValid(trigdata->tg_trigger->tgconstrrelid)) + elog(ERROR, "No target table given for trigger \"%s\" on \"%s\"" + "\n\tRemove these RI triggers and do ALTER TABLE ADD CONSTRAINT", + trigdata->tg_trigger->tgname, + RelationGetRelationName(trigdata->tg_relation)); + fk_rel = heap_open(trigdata->tg_trigger->tgconstrrelid, RowExclusiveLock); pk_rel = trigdata->tg_relation; old_row = trigdata->tg_trigtuple; @@ -2806,6 +2869,12 @@ RI_FKey_setdefault_upd(PG_FUNCTION_ARGS) * fk_rel is opened in RowExclusiveLock mode since that's what our * eventual UPDATE will get on it. */ + if (!OidIsValid(trigdata->tg_trigger->tgconstrrelid)) + elog(ERROR, "No target table given for trigger \"%s\" on \"%s\"" + "\n\tRemove these RI triggers and do ALTER TABLE ADD CONSTRAINT", + trigdata->tg_trigger->tgname, + RelationGetRelationName(trigdata->tg_relation)); + fk_rel = heap_open(trigdata->tg_trigger->tgconstrrelid, RowExclusiveLock); pk_rel = trigdata->tg_relation; new_row = trigdata->tg_newtuple; @@ -3070,6 +3139,12 @@ RI_FKey_keyequal_upd(TriggerData *trigdata) * * Use minimal locking for fk_rel here. */ + if (!OidIsValid(trigdata->tg_trigger->tgconstrrelid)) + elog(ERROR, "No target table given for trigger \"%s\" on \"%s\"" + "\n\tRemove these RI triggers and do ALTER TABLE ADD CONSTRAINT", + trigdata->tg_trigger->tgname, + RelationGetRelationName(trigdata->tg_relation)); + fk_rel = heap_open(trigdata->tg_trigger->tgconstrrelid, AccessShareLock); pk_rel = trigdata->tg_relation; new_row = trigdata->tg_newtuple;