@@ -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 );
8483static void SetTriggerFlags (TriggerDesc * trigdesc , Trigger * trigger );
8584static 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 */
161156ObjectAddress
162157CreateTrigger (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