diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 98fbe4595eed6499c4c782a40c6f1ae2a73d9cb5..8798992ecf944069448a9321c0b7a3c2216a61f9 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
- *	  $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 $
  *
  *-------------------------------------------------------------------------
  */
@@ -218,7 +218,6 @@ CreateTrigger(CreateTrigStmt *stmt, Oid constraintOid)
 	 * 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)
@@ -482,9 +481,69 @@ ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid)
 {
 	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)
@@ -508,8 +567,8 @@ ConvertTriggerToFK(CreateTrigStmt *stmt, Oid 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;
 	}
 
@@ -527,8 +586,8 @@ ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid)
 		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);
@@ -539,49 +598,36 @@ ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid)
 	}
 	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)
 		{
@@ -638,6 +684,7 @@ ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid)
 		fkcon->deferrable = stmt->deferrable;
 		fkcon->initdeferred = stmt->initdeferred;
 
+		/* ... and execute it */
 		ProcessUtility((Node *) atstmt,
 					   NULL, NULL, false, None_Receiver, NULL);