Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit e58a599

Browse files
committed
Remove ancient support for upgrading pre-7.3 foreign key constraints.
Before 7.3, foreign key constraints had no explicit catalog representation, so that what pg_dump produced for them was (usually) a set of three CREATE CONSTRAINT TRIGGER commands. Commit a2899eb and some follow-on fixes added an ugly hack in CreateTrigger() to recognize that pattern and reconstruct the foreign key definition. However, we've never had any test coverage for that code, so that it's legitimate to wonder if it still works; and having to maintain it in the face of upcoming trigger-related patches seems rather pointless. Let's decree that its time has passed, and drop it. This is part of a group of patches removing various server-side kluges for transparently upgrading pre-8.0 dump files. Since we've had few complaints about dropping pg_dump's support for dumping from pre-8.0 servers (commit 64f3524), it seems okay to now remove these kluges. Daniel Gustafsson Discussion: https://postgr.es/m/805874E2-999C-4CDA-856F-1AFBD9DFE933@yesql.se
1 parent a77315f commit e58a599

File tree

1 file changed

+0
-304
lines changed

1 file changed

+0
-304
lines changed

src/backend/commands/trigger.c

-304
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,6 @@ static int MyTriggerDepth = 0;
8080
exec_rt_fetch((relinfo)->ri_RangeTableIndex, estate)->extraUpdatedCols))
8181

8282
/* Local function prototypes */
83-
static void ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid);
8483
static void SetTriggerFlags(TriggerDesc *trigdesc, Trigger *trigger);
8584
static bool GetTupleForTrigger(EState *estate,
8685
EPQState *epqstate,
@@ -153,10 +152,6 @@ static bool before_stmt_triggers_fired(Oid relid, CmdType cmdType);
153152
* When called on partitioned tables, this function recurses to create the
154153
* trigger on all the partitions, except if isInternal is true, in which
155154
* case caller is expected to execute recursion on its own.
156-
*
157-
* Note: can return InvalidObjectAddress if we decided to not create a trigger
158-
* at all, but a foreign-key constraint. This is a kluge for backwards
159-
* compatibility.
160155
*/
161156
ObjectAddress
162157
CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
@@ -719,26 +714,6 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
719714
NameListToString(stmt->funcname), "trigger")));
720715
}
721716

722-
/*
723-
* If the command is a user-entered CREATE CONSTRAINT TRIGGER command that
724-
* references one of the built-in RI_FKey trigger functions, assume it is
725-
* from a dump of a pre-7.3 foreign key constraint, and take steps to
726-
* convert this legacy representation into a regular foreign key
727-
* constraint. Ugly, but necessary for loading old dump files.
728-
*/
729-
if (stmt->isconstraint && !isInternal &&
730-
list_length(stmt->args) >= 6 &&
731-
(list_length(stmt->args) % 2) == 0 &&
732-
RI_FKey_trigger_type(funcoid) != RI_TRIGGER_NONE)
733-
{
734-
/* Keep lock on target rel until end of xact */
735-
table_close(rel, NoLock);
736-
737-
ConvertTriggerToFK(stmt, funcoid);
738-
739-
return InvalidObjectAddress;
740-
}
741-
742717
/*
743718
* If it's a user-entered CREATE CONSTRAINT TRIGGER command, make a
744719
* corresponding pg_constraint entry.
@@ -1206,285 +1181,6 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
12061181
}
12071182

12081183

1209-
/*
1210-
* Convert legacy (pre-7.3) CREATE CONSTRAINT TRIGGER commands into
1211-
* full-fledged foreign key constraints.
1212-
*
1213-
* The conversion is complex because a pre-7.3 foreign key involved three
1214-
* separate triggers, which were reported separately in dumps. While the
1215-
* single trigger on the referencing table adds no new information, we need
1216-
* to know the trigger functions of both of the triggers on the referenced
1217-
* table to build the constraint declaration. Also, due to lack of proper
1218-
* dependency checking pre-7.3, it is possible that the source database had
1219-
* an incomplete set of triggers resulting in an only partially enforced
1220-
* FK constraint. (This would happen if one of the tables had been dropped
1221-
* and re-created, but only if the DB had been affected by a 7.0 pg_dump bug
1222-
* that caused loss of tgconstrrelid information.) We choose to translate to
1223-
* an FK constraint only when we've seen all three triggers of a set. This is
1224-
* implemented by storing unmatched items in a list in TopMemoryContext.
1225-
* We match triggers together by comparing the trigger arguments (which
1226-
* include constraint name, table and column names, so should be good enough).
1227-
*/
1228-
typedef struct
1229-
{
1230-
List *args; /* list of (T_String) Values or NIL */
1231-
Oid funcoids[3]; /* OIDs of trigger functions */
1232-
/* The three function OIDs are stored in the order update, delete, child */
1233-
} OldTriggerInfo;
1234-
1235-
static void
1236-
ConvertTriggerToFK(CreateTrigStmt *stmt, Oid funcoid)
1237-
{
1238-
static List *info_list = NIL;
1239-
1240-
static const char *const funcdescr[3] = {
1241-
gettext_noop("Found referenced table's UPDATE trigger."),
1242-
gettext_noop("Found referenced table's DELETE trigger."),
1243-
gettext_noop("Found referencing table's trigger.")
1244-
};
1245-
1246-
char *constr_name;
1247-
char *fk_table_name;
1248-
char *pk_table_name;
1249-
char fk_matchtype = FKCONSTR_MATCH_SIMPLE;
1250-
List *fk_attrs = NIL;
1251-
List *pk_attrs = NIL;
1252-
StringInfoData buf;
1253-
int funcnum;
1254-
OldTriggerInfo *info = NULL;
1255-
ListCell *l;
1256-
int i;
1257-
1258-
/* Parse out the trigger arguments */
1259-
constr_name = strVal(linitial(stmt->args));
1260-
fk_table_name = strVal(lsecond(stmt->args));
1261-
pk_table_name = strVal(lthird(stmt->args));
1262-
i = 0;
1263-
foreach(l, stmt->args)
1264-
{
1265-
Value *arg = (Value *) lfirst(l);
1266-
1267-
i++;
1268-
if (i < 4) /* skip constraint and table names */
1269-
continue;
1270-
if (i == 4) /* handle match type */
1271-
{
1272-
if (strcmp(strVal(arg), "FULL") == 0)
1273-
fk_matchtype = FKCONSTR_MATCH_FULL;
1274-
else
1275-
fk_matchtype = FKCONSTR_MATCH_SIMPLE;
1276-
continue;
1277-
}
1278-
if (i % 2)
1279-
fk_attrs = lappend(fk_attrs, arg);
1280-
else
1281-
pk_attrs = lappend(pk_attrs, arg);
1282-
}
1283-
1284-
/* Prepare description of constraint for use in messages */
1285-
initStringInfo(&buf);
1286-
appendStringInfo(&buf, "FOREIGN KEY %s(",
1287-
quote_identifier(fk_table_name));
1288-
i = 0;
1289-
foreach(l, fk_attrs)
1290-
{
1291-
Value *arg = (Value *) lfirst(l);
1292-
1293-
if (i++ > 0)
1294-
appendStringInfoChar(&buf, ',');
1295-
appendStringInfoString(&buf, quote_identifier(strVal(arg)));
1296-
}
1297-
appendStringInfo(&buf, ") REFERENCES %s(",
1298-
quote_identifier(pk_table_name));
1299-
i = 0;
1300-
foreach(l, pk_attrs)
1301-
{
1302-
Value *arg = (Value *) lfirst(l);
1303-
1304-
if (i++ > 0)
1305-
appendStringInfoChar(&buf, ',');
1306-
appendStringInfoString(&buf, quote_identifier(strVal(arg)));
1307-
}
1308-
appendStringInfoChar(&buf, ')');
1309-
1310-
/* Identify class of trigger --- update, delete, or referencing-table */
1311-
switch (funcoid)
1312-
{
1313-
case F_RI_FKEY_CASCADE_UPD:
1314-
case F_RI_FKEY_RESTRICT_UPD:
1315-
case F_RI_FKEY_SETNULL_UPD:
1316-
case F_RI_FKEY_SETDEFAULT_UPD:
1317-
case F_RI_FKEY_NOACTION_UPD:
1318-
funcnum = 0;
1319-
break;
1320-
1321-
case F_RI_FKEY_CASCADE_DEL:
1322-
case F_RI_FKEY_RESTRICT_DEL:
1323-
case F_RI_FKEY_SETNULL_DEL:
1324-
case F_RI_FKEY_SETDEFAULT_DEL:
1325-
case F_RI_FKEY_NOACTION_DEL:
1326-
funcnum = 1;
1327-
break;
1328-
1329-
default:
1330-
funcnum = 2;
1331-
break;
1332-
}
1333-
1334-
/* See if we have a match to this trigger */
1335-
foreach(l, info_list)
1336-
{
1337-
info = (OldTriggerInfo *) lfirst(l);
1338-
if (info->funcoids[funcnum] == InvalidOid &&
1339-
equal(info->args, stmt->args))
1340-
{
1341-
info->funcoids[funcnum] = funcoid;
1342-
break;
1343-
}
1344-
}
1345-
1346-
if (l == NULL)
1347-
{
1348-
/* First trigger of set, so create a new list entry */
1349-
MemoryContext oldContext;
1350-
1351-
ereport(NOTICE,
1352-
(errmsg("ignoring incomplete trigger group for constraint \"%s\" %s",
1353-
constr_name, buf.data),
1354-
errdetail_internal("%s", _(funcdescr[funcnum]))));
1355-
oldContext = MemoryContextSwitchTo(TopMemoryContext);
1356-
info = (OldTriggerInfo *) palloc0(sizeof(OldTriggerInfo));
1357-
info->args = copyObject(stmt->args);
1358-
info->funcoids[funcnum] = funcoid;
1359-
info_list = lappend(info_list, info);
1360-
MemoryContextSwitchTo(oldContext);
1361-
}
1362-
else if (info->funcoids[0] == InvalidOid ||
1363-
info->funcoids[1] == InvalidOid ||
1364-
info->funcoids[2] == InvalidOid)
1365-
{
1366-
/* Second trigger of set */
1367-
ereport(NOTICE,
1368-
(errmsg("ignoring incomplete trigger group for constraint \"%s\" %s",
1369-
constr_name, buf.data),
1370-
errdetail_internal("%s", _(funcdescr[funcnum]))));
1371-
}
1372-
else
1373-
{
1374-
/* OK, we have a set, so make the FK constraint ALTER TABLE cmd */
1375-
AlterTableStmt *atstmt = makeNode(AlterTableStmt);
1376-
AlterTableCmd *atcmd = makeNode(AlterTableCmd);
1377-
Constraint *fkcon = makeNode(Constraint);
1378-
PlannedStmt *wrapper = makeNode(PlannedStmt);
1379-
1380-
ereport(NOTICE,
1381-
(errmsg("converting trigger group into constraint \"%s\" %s",
1382-
constr_name, buf.data),
1383-
errdetail_internal("%s", _(funcdescr[funcnum]))));
1384-
fkcon->contype = CONSTR_FOREIGN;
1385-
fkcon->location = -1;
1386-
if (funcnum == 2)
1387-
{
1388-
/* This trigger is on the FK table */
1389-
atstmt->relation = stmt->relation;
1390-
if (stmt->constrrel)
1391-
fkcon->pktable = stmt->constrrel;
1392-
else
1393-
{
1394-
/* Work around ancient pg_dump bug that omitted constrrel */
1395-
fkcon->pktable = makeRangeVar(NULL, pk_table_name, -1);
1396-
}
1397-
}
1398-
else
1399-
{
1400-
/* This trigger is on the PK table */
1401-
fkcon->pktable = stmt->relation;
1402-
if (stmt->constrrel)
1403-
atstmt->relation = stmt->constrrel;
1404-
else
1405-
{
1406-
/* Work around ancient pg_dump bug that omitted constrrel */
1407-
atstmt->relation = makeRangeVar(NULL, fk_table_name, -1);
1408-
}
1409-
}
1410-
atstmt->cmds = list_make1(atcmd);
1411-
atstmt->relkind = OBJECT_TABLE;
1412-
atcmd->subtype = AT_AddConstraint;
1413-
atcmd->def = (Node *) fkcon;
1414-
if (strcmp(constr_name, "<unnamed>") == 0)
1415-
fkcon->conname = NULL;
1416-
else
1417-
fkcon->conname = constr_name;
1418-
fkcon->fk_attrs = fk_attrs;
1419-
fkcon->pk_attrs = pk_attrs;
1420-
fkcon->fk_matchtype = fk_matchtype;
1421-
switch (info->funcoids[0])
1422-
{
1423-
case F_RI_FKEY_NOACTION_UPD:
1424-
fkcon->fk_upd_action = FKCONSTR_ACTION_NOACTION;
1425-
break;
1426-
case F_RI_FKEY_CASCADE_UPD:
1427-
fkcon->fk_upd_action = FKCONSTR_ACTION_CASCADE;
1428-
break;
1429-
case F_RI_FKEY_RESTRICT_UPD:
1430-
fkcon->fk_upd_action = FKCONSTR_ACTION_RESTRICT;
1431-
break;
1432-
case F_RI_FKEY_SETNULL_UPD:
1433-
fkcon->fk_upd_action = FKCONSTR_ACTION_SETNULL;
1434-
break;
1435-
case F_RI_FKEY_SETDEFAULT_UPD:
1436-
fkcon->fk_upd_action = FKCONSTR_ACTION_SETDEFAULT;
1437-
break;
1438-
default:
1439-
/* can't get here because of earlier checks */
1440-
elog(ERROR, "confused about RI update function");
1441-
}
1442-
switch (info->funcoids[1])
1443-
{
1444-
case F_RI_FKEY_NOACTION_DEL:
1445-
fkcon->fk_del_action = FKCONSTR_ACTION_NOACTION;
1446-
break;
1447-
case F_RI_FKEY_CASCADE_DEL:
1448-
fkcon->fk_del_action = FKCONSTR_ACTION_CASCADE;
1449-
break;
1450-
case F_RI_FKEY_RESTRICT_DEL:
1451-
fkcon->fk_del_action = FKCONSTR_ACTION_RESTRICT;
1452-
break;
1453-
case F_RI_FKEY_SETNULL_DEL:
1454-
fkcon->fk_del_action = FKCONSTR_ACTION_SETNULL;
1455-
break;
1456-
case F_RI_FKEY_SETDEFAULT_DEL:
1457-
fkcon->fk_del_action = FKCONSTR_ACTION_SETDEFAULT;
1458-
break;
1459-
default:
1460-
/* can't get here because of earlier checks */
1461-
elog(ERROR, "confused about RI delete function");
1462-
}
1463-
fkcon->deferrable = stmt->deferrable;
1464-
fkcon->initdeferred = stmt->initdeferred;
1465-
fkcon->skip_validation = false;
1466-
fkcon->initially_valid = true;
1467-
1468-
/* finally, wrap it in a dummy PlannedStmt */
1469-
wrapper->commandType = CMD_UTILITY;
1470-
wrapper->canSetTag = false;
1471-
wrapper->utilityStmt = (Node *) atstmt;
1472-
wrapper->stmt_location = -1;
1473-
wrapper->stmt_len = -1;
1474-
1475-
/* ... and execute it */
1476-
ProcessUtility(wrapper,
1477-
"(generated ALTER TABLE ADD FOREIGN KEY command)",
1478-
PROCESS_UTILITY_SUBCOMMAND, NULL, NULL,
1479-
None_Receiver, NULL);
1480-
1481-
/* Remove the matched item from the list */
1482-
info_list = list_delete_ptr(info_list, info);
1483-
pfree(info);
1484-
/* We leak the copied args ... not worth worrying about */
1485-
}
1486-
}
1487-
14881184
/*
14891185
* Guts of trigger deletion.
14901186
*/

0 commit comments

Comments
 (0)