@@ -394,6 +394,12 @@ static ObjectAddress ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd,
394394static bool ATExecAlterConstrRecurse(Constraint *cmdcon, Relation conrel, Relation tgrel,
395395 Relation rel, HeapTuple contuple, List **otherrelids,
396396 LOCKMODE lockmode);
397+ static void AlterConstrTriggerDeferrability(Oid conoid, Relation tgrel, Relation rel,
398+ bool deferrable, bool initdeferred,
399+ List **otherrelids);
400+ static void ATExecAlterChildConstr(Constraint *cmdcon, Relation conrel, Relation tgrel,
401+ Relation rel, HeapTuple contuple, List **otherrelids,
402+ LOCKMODE lockmode);
397403static ObjectAddress ATExecValidateConstraint(List **wqueue,
398404 Relation rel, char *constrName,
399405 bool recurse, bool recursing, LOCKMODE lockmode);
@@ -11861,9 +11867,6 @@ ATExecAlterConstrRecurse(Constraint *cmdcon, Relation conrel, Relation tgrel,
1186111867 {
1186211868 HeapTuple copyTuple;
1186311869 Form_pg_constraint copy_con;
11864- HeapTuple tgtuple;
11865- ScanKeyData tgkey;
11866- SysScanDesc tgscan;
1186711870
1186811871 copyTuple = heap_copytuple(contuple);
1186911872 copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple);
@@ -11884,53 +11887,8 @@ ATExecAlterConstrRecurse(Constraint *cmdcon, Relation conrel, Relation tgrel,
1188411887 * Now we need to update the multiple entries in pg_trigger that
1188511888 * implement the constraint.
1188611889 */
11887- ScanKeyInit(&tgkey,
11888- Anum_pg_trigger_tgconstraint,
11889- BTEqualStrategyNumber, F_OIDEQ,
11890- ObjectIdGetDatum(conoid));
11891- tgscan = systable_beginscan(tgrel, TriggerConstraintIndexId, true,
11892- NULL, 1, &tgkey);
11893- while (HeapTupleIsValid(tgtuple = systable_getnext(tgscan)))
11894- {
11895- Form_pg_trigger tgform = (Form_pg_trigger) GETSTRUCT(tgtuple);
11896- Form_pg_trigger copy_tg;
11897- HeapTuple tgCopyTuple;
11898-
11899- /*
11900- * Remember OIDs of other relation(s) involved in FK constraint.
11901- * (Note: it's likely that we could skip forcing a relcache inval
11902- * for other rels that don't have a trigger whose properties
11903- * change, but let's be conservative.)
11904- */
11905- if (tgform->tgrelid != RelationGetRelid(rel))
11906- *otherrelids = list_append_unique_oid(*otherrelids,
11907- tgform->tgrelid);
11908-
11909- /*
11910- * Update deferrability of RI_FKey_noaction_del,
11911- * RI_FKey_noaction_upd, RI_FKey_check_ins and RI_FKey_check_upd
11912- * triggers, but not others; see createForeignKeyActionTriggers
11913- * and CreateFKCheckTrigger.
11914- */
11915- if (tgform->tgfoid != F_RI_FKEY_NOACTION_DEL &&
11916- tgform->tgfoid != F_RI_FKEY_NOACTION_UPD &&
11917- tgform->tgfoid != F_RI_FKEY_CHECK_INS &&
11918- tgform->tgfoid != F_RI_FKEY_CHECK_UPD)
11919- continue;
11920-
11921- tgCopyTuple = heap_copytuple(tgtuple);
11922- copy_tg = (Form_pg_trigger) GETSTRUCT(tgCopyTuple);
11923-
11924- copy_tg->tgdeferrable = cmdcon->deferrable;
11925- copy_tg->tginitdeferred = cmdcon->initdeferred;
11926- CatalogTupleUpdate(tgrel, &tgCopyTuple->t_self, tgCopyTuple);
11927-
11928- InvokeObjectPostAlterHook(TriggerRelationId, tgform->oid, 0);
11929-
11930- heap_freetuple(tgCopyTuple);
11931- }
11932-
11933- systable_endscan(tgscan);
11890+ AlterConstrTriggerDeferrability(conoid, tgrel, rel, cmdcon->deferrable,
11891+ cmdcon->initdeferred, otherrelids);
1193411892 }
1193511893
1193611894 /*
@@ -11943,34 +11901,118 @@ ATExecAlterConstrRecurse(Constraint *cmdcon, Relation conrel, Relation tgrel,
1194311901 */
1194411902 if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE ||
1194511903 get_rel_relkind(refrelid) == RELKIND_PARTITIONED_TABLE)
11904+ ATExecAlterChildConstr(cmdcon, conrel, tgrel, rel, contuple,
11905+ otherrelids, lockmode);
11906+
11907+ return changed;
11908+ }
11909+
11910+ /*
11911+ * A subroutine of ATExecAlterConstrRecurse that updated constraint trigger's
11912+ * deferrability.
11913+ *
11914+ * The arguments to this function have the same meaning as the arguments to
11915+ * ATExecAlterConstrRecurse.
11916+ */
11917+ static void
11918+ AlterConstrTriggerDeferrability(Oid conoid, Relation tgrel, Relation rel,
11919+ bool deferrable, bool initdeferred,
11920+ List **otherrelids)
11921+ {
11922+ HeapTuple tgtuple;
11923+ ScanKeyData tgkey;
11924+ SysScanDesc tgscan;
11925+
11926+ ScanKeyInit(&tgkey,
11927+ Anum_pg_trigger_tgconstraint,
11928+ BTEqualStrategyNumber, F_OIDEQ,
11929+ ObjectIdGetDatum(conoid));
11930+ tgscan = systable_beginscan(tgrel, TriggerConstraintIndexId, true,
11931+ NULL, 1, &tgkey);
11932+ while (HeapTupleIsValid(tgtuple = systable_getnext(tgscan)))
1194611933 {
11947- ScanKeyData pkey ;
11948- SysScanDesc pscan ;
11949- HeapTuple childtup ;
11934+ Form_pg_trigger tgform = (Form_pg_trigger) GETSTRUCT(tgtuple) ;
11935+ Form_pg_trigger copy_tg ;
11936+ HeapTuple tgCopyTuple ;
1195011937
11951- ScanKeyInit(&pkey,
11952- Anum_pg_constraint_conparentid,
11953- BTEqualStrategyNumber, F_OIDEQ,
11954- ObjectIdGetDatum(conoid));
11938+ /*
11939+ * Remember OIDs of other relation(s) involved in FK constraint.
11940+ * (Note: it's likely that we could skip forcing a relcache inval for
11941+ * other rels that don't have a trigger whose properties change, but
11942+ * let's be conservative.)
11943+ */
11944+ if (tgform->tgrelid != RelationGetRelid(rel))
11945+ *otherrelids = list_append_unique_oid(*otherrelids,
11946+ tgform->tgrelid);
1195511947
11956- pscan = systable_beginscan(conrel, ConstraintParentIndexId,
11957- true, NULL, 1, &pkey);
11948+ /*
11949+ * Update enable status and deferrability of RI_FKey_noaction_del,
11950+ * RI_FKey_noaction_upd, RI_FKey_check_ins and RI_FKey_check_upd
11951+ * triggers, but not others; see createForeignKeyActionTriggers and
11952+ * CreateFKCheckTrigger.
11953+ */
11954+ if (tgform->tgfoid != F_RI_FKEY_NOACTION_DEL &&
11955+ tgform->tgfoid != F_RI_FKEY_NOACTION_UPD &&
11956+ tgform->tgfoid != F_RI_FKEY_CHECK_INS &&
11957+ tgform->tgfoid != F_RI_FKEY_CHECK_UPD)
11958+ continue;
1195811959
11959- while (HeapTupleIsValid(childtup = systable_getnext(pscan)))
11960- {
11961- Form_pg_constraint childcon = (Form_pg_constraint) GETSTRUCT(childtup);
11962- Relation childrel;
11960+ tgCopyTuple = heap_copytuple(tgtuple);
11961+ copy_tg = (Form_pg_trigger) GETSTRUCT(tgCopyTuple);
1196311962
11964- childrel = table_open(childcon->conrelid, lockmode) ;
11965- ATExecAlterConstrRecurse(cmdcon, conrel, tgrel, childrel, childtup,
11966- otherrelids, lockmode );
11967- table_close(childrel, NoLock);
11968- }
11963+ copy_tg->tgdeferrable = deferrable ;
11964+ copy_tg->tginitdeferred = initdeferred;
11965+ CatalogTupleUpdate(tgrel, &tgCopyTuple->t_self, tgCopyTuple );
11966+
11967+ InvokeObjectPostAlterHook(TriggerRelationId, tgform->oid, 0);
1196911968
11970- systable_endscan(pscan );
11969+ heap_freetuple(tgCopyTuple );
1197111970 }
1197211971
11973- return changed;
11972+ systable_endscan(tgscan);
11973+ }
11974+
11975+ /*
11976+ * Invokes ATExecAlterConstrRecurse for each constraint that is a child of the
11977+ * specified constraint.
11978+ *
11979+ * The arguments to this function have the same meaning as the arguments to
11980+ * ATExecAlterConstrRecurse.
11981+ */
11982+ static void
11983+ ATExecAlterChildConstr(Constraint *cmdcon, Relation conrel, Relation tgrel,
11984+ Relation rel, HeapTuple contuple, List **otherrelids,
11985+ LOCKMODE lockmode)
11986+ {
11987+ Form_pg_constraint currcon;
11988+ Oid conoid;
11989+ ScanKeyData pkey;
11990+ SysScanDesc pscan;
11991+ HeapTuple childtup;
11992+
11993+ currcon = (Form_pg_constraint) GETSTRUCT(contuple);
11994+ conoid = currcon->oid;
11995+
11996+ ScanKeyInit(&pkey,
11997+ Anum_pg_constraint_conparentid,
11998+ BTEqualStrategyNumber, F_OIDEQ,
11999+ ObjectIdGetDatum(conoid));
12000+
12001+ pscan = systable_beginscan(conrel, ConstraintParentIndexId,
12002+ true, NULL, 1, &pkey);
12003+
12004+ while (HeapTupleIsValid(childtup = systable_getnext(pscan)))
12005+ {
12006+ Form_pg_constraint childcon = (Form_pg_constraint) GETSTRUCT(childtup);
12007+ Relation childrel;
12008+
12009+ childrel = table_open(childcon->conrelid, lockmode);
12010+ ATExecAlterConstrRecurse(cmdcon, conrel, tgrel, childrel, childtup,
12011+ otherrelids, lockmode);
12012+ table_close(childrel, NoLock);
12013+ }
12014+
12015+ systable_endscan(pscan);
1197412016}
1197512017
1197612018/*
0 commit comments