From dfb8b37048b67392e86f20399d54859c31fcd9b6 Mon Sep 17 00:00:00 2001
From: Daniel Gustafsson <daniel@yesql.se>
Date: Thu, 5 Mar 2020 14:34:53 +0100
Subject: [PATCH] Remove support for pre-7.3 constraint trigger conversion

To handle pre-7.3 constraint triggers, commit a2899ebdc28080eab0f4
added support for automatically converting them. This is unlikely
to be used today, so retire the functionality.
---
 src/backend/commands/trigger.c | 300 ---------------------------------
 1 file changed, 300 deletions(-)

diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 6e8b7223fe..4e79e74127 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -80,7 +80,6 @@ static int	MyTriggerDepth = 0;
 			   exec_rt_fetch((relinfo)->ri_RangeTableIndex, estate)->extraUpdatedCols))
 
 /* Local function prototypes */
-static void ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid);
 static void SetTriggerFlags(TriggerDesc *trigdesc, Trigger *trigger);
 static bool GetTupleForTrigger(EState *estate,
 							   EPQState *epqstate,
@@ -719,26 +718,6 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
 							NameListToString(stmt->funcname), "trigger")));
 	}
 
-	/*
-	 * If the command is a user-entered CREATE CONSTRAINT TRIGGER command that
-	 * references one of the built-in RI_FKey trigger functions, assume it is
-	 * from a dump of a pre-7.3 foreign key constraint, and take steps to
-	 * convert this legacy representation into a regular foreign key
-	 * constraint.  Ugly, but necessary for loading old dump files.
-	 */
-	if (stmt->isconstraint && !isInternal &&
-		list_length(stmt->args) >= 6 &&
-		(list_length(stmt->args) % 2) == 0 &&
-		RI_FKey_trigger_type(funcoid) != RI_TRIGGER_NONE)
-	{
-		/* Keep lock on target rel until end of xact */
-		table_close(rel, NoLock);
-
-		ConvertTriggerToFK(stmt, funcoid);
-
-		return InvalidObjectAddress;
-	}
-
 	/*
 	 * If it's a user-entered CREATE CONSTRAINT TRIGGER command, make a
 	 * corresponding pg_constraint entry.
@@ -1206,285 +1185,6 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
 }
 
 
-/*
- * Convert legacy (pre-7.3) CREATE CONSTRAINT TRIGGER commands into
- * full-fledged foreign key constraints.
- *
- * The conversion is complex because a pre-7.3 foreign key involved three
- * separate triggers, which were reported separately in dumps.  While the
- * single trigger on the referencing table adds no new information, we need
- * to know the trigger functions of both of the triggers on the referenced
- * table to build the constraint declaration.  Also, due to lack of proper
- * dependency checking pre-7.3, it is possible that the source database had
- * an incomplete set of triggers resulting in an only partially enforced
- * FK constraint.  (This would happen if one of the tables had been dropped
- * and re-created, but only if the DB had been affected by a 7.0 pg_dump bug
- * that caused loss of tgconstrrelid information.)	We choose to translate to
- * an FK constraint only when we've seen all three triggers of a set.  This is
- * implemented by storing unmatched items in a list in TopMemoryContext.
- * We match triggers together by comparing the trigger arguments (which
- * include constraint name, table and column names, so should be good enough).
- */
-typedef struct
-{
-	List	   *args;			/* list of (T_String) Values or NIL */
-	Oid			funcoids[3];	/* OIDs of trigger functions */
-	/* The three function OIDs are stored in the order update, delete, child */
-} OldTriggerInfo;
-
-static void
-ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid)
-{
-	static List *info_list = NIL;
-
-	static const char *const funcdescr[3] = {
-		gettext_noop("Found referenced table's UPDATE trigger."),
-		gettext_noop("Found referenced table's DELETE trigger."),
-		gettext_noop("Found referencing table's trigger.")
-	};
-
-	char	   *constr_name;
-	char	   *fk_table_name;
-	char	   *pk_table_name;
-	char		fk_matchtype = FKCONSTR_MATCH_SIMPLE;
-	List	   *fk_attrs = NIL;
-	List	   *pk_attrs = NIL;
-	StringInfoData buf;
-	int			funcnum;
-	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_SIMPLE;
-			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)
-	{
-		case F_RI_FKEY_CASCADE_UPD:
-		case F_RI_FKEY_RESTRICT_UPD:
-		case F_RI_FKEY_SETNULL_UPD:
-		case F_RI_FKEY_SETDEFAULT_UPD:
-		case F_RI_FKEY_NOACTION_UPD:
-			funcnum = 0;
-			break;
-
-		case F_RI_FKEY_CASCADE_DEL:
-		case F_RI_FKEY_RESTRICT_DEL:
-		case F_RI_FKEY_SETNULL_DEL:
-		case F_RI_FKEY_SETDEFAULT_DEL:
-		case F_RI_FKEY_NOACTION_DEL:
-			funcnum = 1;
-			break;
-
-		default:
-			funcnum = 2;
-			break;
-	}
-
-	/* See if we have a match to this trigger */
-	foreach(l, info_list)
-	{
-		info = (OldTriggerInfo *) lfirst(l);
-		if (info->funcoids[funcnum] == InvalidOid &&
-			equal(info->args, stmt->args))
-		{
-			info->funcoids[funcnum] = funcoid;
-			break;
-		}
-	}
-
-	if (l == NULL)
-	{
-		/* First trigger of set, so create a new list entry */
-		MemoryContext oldContext;
-
-		ereport(NOTICE,
-				(errmsg("ignoring incomplete trigger group for constraint \"%s\" %s",
-						constr_name, buf.data),
-				 errdetail_internal("%s", _(funcdescr[funcnum]))));
-		oldContext = MemoryContextSwitchTo(TopMemoryContext);
-		info = (OldTriggerInfo *) palloc0(sizeof(OldTriggerInfo));
-		info->args = copyObject(stmt->args);
-		info->funcoids[funcnum] = funcoid;
-		info_list = lappend(info_list, info);
-		MemoryContextSwitchTo(oldContext);
-	}
-	else if (info->funcoids[0] == InvalidOid ||
-			 info->funcoids[1] == InvalidOid ||
-			 info->funcoids[2] == InvalidOid)
-	{
-		/* Second trigger of set */
-		ereport(NOTICE,
-				(errmsg("ignoring incomplete trigger group for constraint \"%s\" %s",
-						constr_name, buf.data),
-				 errdetail_internal("%s", _(funcdescr[funcnum]))));
-	}
-	else
-	{
-		/* OK, we have a set, so make the FK constraint ALTER TABLE cmd */
-		AlterTableStmt *atstmt = makeNode(AlterTableStmt);
-		AlterTableCmd *atcmd = makeNode(AlterTableCmd);
-		Constraint *fkcon = makeNode(Constraint);
-		PlannedStmt *wrapper = makeNode(PlannedStmt);
-
-		ereport(NOTICE,
-				(errmsg("converting trigger group into constraint \"%s\" %s",
-						constr_name, buf.data),
-				 errdetail_internal("%s", _(funcdescr[funcnum]))));
-		fkcon->contype = CONSTR_FOREIGN;
-		fkcon->location = -1;
-		if (funcnum == 2)
-		{
-			/* This trigger is on the FK table */
-			atstmt->relation = stmt->relation;
-			if (stmt->constrrel)
-				fkcon->pktable = stmt->constrrel;
-			else
-			{
-				/* Work around ancient pg_dump bug that omitted constrrel */
-				fkcon->pktable = makeRangeVar(NULL, pk_table_name, -1);
-			}
-		}
-		else
-		{
-			/* This trigger is on the PK table */
-			fkcon->pktable = stmt->relation;
-			if (stmt->constrrel)
-				atstmt->relation = stmt->constrrel;
-			else
-			{
-				/* Work around ancient pg_dump bug that omitted constrrel */
-				atstmt->relation = makeRangeVar(NULL, fk_table_name, -1);
-			}
-		}
-		atstmt->cmds = list_make1(atcmd);
-		atstmt->relkind = OBJECT_TABLE;
-		atcmd->subtype = AT_AddConstraint;
-		atcmd->def = (Node *) fkcon;
-		if (strcmp(constr_name, "<unnamed>") == 0)
-			fkcon->conname = NULL;
-		else
-			fkcon->conname = constr_name;
-		fkcon->fk_attrs = fk_attrs;
-		fkcon->pk_attrs = pk_attrs;
-		fkcon->fk_matchtype = fk_matchtype;
-		switch (info->funcoids[0])
-		{
-			case F_RI_FKEY_NOACTION_UPD:
-				fkcon->fk_upd_action = FKCONSTR_ACTION_NOACTION;
-				break;
-			case F_RI_FKEY_CASCADE_UPD:
-				fkcon->fk_upd_action = FKCONSTR_ACTION_CASCADE;
-				break;
-			case F_RI_FKEY_RESTRICT_UPD:
-				fkcon->fk_upd_action = FKCONSTR_ACTION_RESTRICT;
-				break;
-			case F_RI_FKEY_SETNULL_UPD:
-				fkcon->fk_upd_action = FKCONSTR_ACTION_SETNULL;
-				break;
-			case F_RI_FKEY_SETDEFAULT_UPD:
-				fkcon->fk_upd_action = FKCONSTR_ACTION_SETDEFAULT;
-				break;
-			default:
-				/* can't get here because of earlier checks */
-				elog(ERROR, "confused about RI update function");
-		}
-		switch (info->funcoids[1])
-		{
-			case F_RI_FKEY_NOACTION_DEL:
-				fkcon->fk_del_action = FKCONSTR_ACTION_NOACTION;
-				break;
-			case F_RI_FKEY_CASCADE_DEL:
-				fkcon->fk_del_action = FKCONSTR_ACTION_CASCADE;
-				break;
-			case F_RI_FKEY_RESTRICT_DEL:
-				fkcon->fk_del_action = FKCONSTR_ACTION_RESTRICT;
-				break;
-			case F_RI_FKEY_SETNULL_DEL:
-				fkcon->fk_del_action = FKCONSTR_ACTION_SETNULL;
-				break;
-			case F_RI_FKEY_SETDEFAULT_DEL:
-				fkcon->fk_del_action = FKCONSTR_ACTION_SETDEFAULT;
-				break;
-			default:
-				/* can't get here because of earlier checks */
-				elog(ERROR, "confused about RI delete function");
-		}
-		fkcon->deferrable = stmt->deferrable;
-		fkcon->initdeferred = stmt->initdeferred;
-		fkcon->skip_validation = false;
-		fkcon->initially_valid = true;
-
-		/* finally, wrap it in a dummy PlannedStmt */
-		wrapper->commandType = CMD_UTILITY;
-		wrapper->canSetTag = false;
-		wrapper->utilityStmt = (Node *) atstmt;
-		wrapper->stmt_location = -1;
-		wrapper->stmt_len = -1;
-
-		/* ... and execute it */
-		ProcessUtility(wrapper,
-					   "(generated ALTER TABLE ADD FOREIGN KEY command)",
-					   PROCESS_UTILITY_SUBCOMMAND, NULL, NULL,
-					   None_Receiver, NULL);
-
-		/* Remove the matched item from the list */
-		info_list = list_delete_ptr(info_list, info);
-		pfree(info);
-		/* We leak the copied args ... not worth worrying about */
-	}
-}
-
 /*
  * Guts of trigger deletion.
  */
-- 
2.21.1 (Apple Git-122.3)

