* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.220 2007/11/04 01:16:19 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/trigger.c,v 1.221 2007/11/04 21:25:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
* constraint. Ugly, but necessary for loading old dump files.
*/
if (stmt->isconstraint && !OidIsValid(constraintOid) &&
- stmt->constrrel != NULL &&
list_length(stmt->args) >= 6 &&
(list_length(stmt->args) % 2) == 0 &&
RI_FKey_trigger_type(funcoid) != RI_TRIGGER_NONE)
{
static List *info_list = NIL;
+ char *constr_name;
+ char *fk_table_name;
+ char *pk_table_name;
+ char fk_matchtype = FKCONSTR_MATCH_UNSPECIFIED;
+ List *fk_attrs = NIL;
+ List *pk_attrs = NIL;
+ StringInfoData buf;
bool isupd;
OldTriggerInfo *info = NULL;
ListCell *l;
+ int i;
+
+ /* Parse out the trigger arguments */
+ constr_name = strVal(linitial(stmt->args));
+ fk_table_name = strVal(lsecond(stmt->args));
+ pk_table_name = strVal(lthird(stmt->args));
+ i = 0;
+ foreach(l, stmt->args)
+ {
+ Value *arg = (Value *) lfirst(l);
+
+ i++;
+ if (i < 4) /* skip constraint and table names */
+ continue;
+ if (i == 4) /* handle match type */
+ {
+ if (strcmp(strVal(arg), "FULL") == 0)
+ fk_matchtype = FKCONSTR_MATCH_FULL;
+ else
+ fk_matchtype = FKCONSTR_MATCH_UNSPECIFIED;
+ continue;
+ }
+ if (i % 2)
+ fk_attrs = lappend(fk_attrs, arg);
+ else
+ pk_attrs = lappend(pk_attrs, arg);
+ }
+
+ /* Prepare description of constraint for use in messages */
+ initStringInfo(&buf);
+ appendStringInfo(&buf, "FOREIGN KEY %s(",
+ quote_identifier(fk_table_name));
+ i = 0;
+ foreach(l, fk_attrs)
+ {
+ Value *arg = (Value *) lfirst(l);
+
+ if (i++ > 0)
+ appendStringInfoChar(&buf, ',');
+ appendStringInfoString(&buf, quote_identifier(strVal(arg)));
+ }
+ appendStringInfo(&buf, ") REFERENCES %s(",
+ quote_identifier(pk_table_name));
+ i = 0;
+ foreach(l, pk_attrs)
+ {
+ Value *arg = (Value *) lfirst(l);
+
+ if (i++ > 0)
+ appendStringInfoChar(&buf, ',');
+ appendStringInfoString(&buf, quote_identifier(strVal(arg)));
+ }
+ appendStringInfoChar(&buf, ')');
/* Identify class of trigger --- update, delete, or referencing-table */
switch (funcoid)
default:
/* Ignore triggers on referencing table */
ereport(NOTICE,
- (errmsg("ignoring incomplete foreign-key trigger group for constraint \"%s\" on table \"%s\"",
- stmt->trigname, stmt->relation->relname)));
+ (errmsg("ignoring incomplete trigger group for constraint \"%s\" %s",
+ constr_name, buf.data)));
return;
}
MemoryContext oldContext;
ereport(NOTICE,
- (errmsg("ignoring incomplete foreign-key trigger group for constraint \"%s\" on table \"%s\"",
- stmt->trigname, stmt->constrrel->relname)));
+ (errmsg("ignoring incomplete trigger group for constraint \"%s\" %s",
+ constr_name, buf.data)));
oldContext = MemoryContextSwitchTo(TopMemoryContext);
info = (OldTriggerInfo *) palloc(sizeof(OldTriggerInfo));
info->args = copyObject(stmt->args);
}
else
{
- /* OK, we have a pair, so make the FK constraint */
+ /* OK, we have a pair, so make the FK constraint ALTER TABLE cmd */
AlterTableStmt *atstmt = makeNode(AlterTableStmt);
AlterTableCmd *atcmd = makeNode(AlterTableCmd);
FkConstraint *fkcon = makeNode(FkConstraint);
- int i;
Oid updfunc,
delfunc;
ereport(NOTICE,
- (errmsg("converting foreign-key trigger group into constraint \"%s\" on table \"%s\"",
- stmt->trigname, stmt->constrrel->relname)));
- atstmt->relation = stmt->constrrel;
+ (errmsg("converting trigger group into constraint \"%s\" %s",
+ constr_name, buf.data)));
+
+ if (stmt->constrrel)
+ atstmt->relation = stmt->constrrel;
+ else
+ {
+ /* Work around ancient pg_dump bug that omitted constrrel */
+ atstmt->relation = makeRangeVar(NULL, fk_table_name);
+ }
atstmt->cmds = list_make1(atcmd);
atstmt->relkind = OBJECT_TABLE;
atcmd->subtype = AT_AddConstraint;
atcmd->def = (Node *) fkcon;
- if (strcmp(stmt->trigname, "<unnamed>") == 0)
+ if (strcmp(constr_name, "<unnamed>") == 0)
fkcon->constr_name = NULL;
else
- fkcon->constr_name = stmt->trigname;
+ fkcon->constr_name = constr_name;
fkcon->pktable = stmt->relation;
-
- i = 0;
- foreach(l, stmt->args)
- {
- Value *arg = (Value *) lfirst(l);
-
- i++;
- if (i < 4) /* ignore constraint and table names */
- continue;
- if (i == 4) /* handle match type */
- {
- if (strcmp(strVal(arg), "FULL") == 0)
- fkcon->fk_matchtype = FKCONSTR_MATCH_FULL;
- else
- fkcon->fk_matchtype = FKCONSTR_MATCH_UNSPECIFIED;
- continue;
- }
- if (i % 2)
- fkcon->fk_attrs = lappend(fkcon->fk_attrs, arg);
- else
- fkcon->pk_attrs = lappend(fkcon->pk_attrs, arg);
- }
+ fkcon->fk_attrs = fk_attrs;
+ fkcon->pk_attrs = pk_attrs;
+ fkcon->fk_matchtype = fk_matchtype;
if (isupd)
{
fkcon->deferrable = stmt->deferrable;
fkcon->initdeferred = stmt->initdeferred;
+ /* ... and execute it */
ProcessUtility((Node *) atstmt,
NULL, NULL, false, None_Receiver, NULL);