@@ -394,6 +394,12 @@ static ObjectAddress ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd,
394
394
static bool ATExecAlterConstrRecurse(Constraint *cmdcon, Relation conrel, Relation tgrel,
395
395
Relation rel, HeapTuple contuple, List **otherrelids,
396
396
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);
397
403
static ObjectAddress ATExecValidateConstraint(List **wqueue,
398
404
Relation rel, char *constrName,
399
405
bool recurse, bool recursing, LOCKMODE lockmode);
@@ -11861,9 +11867,6 @@ ATExecAlterConstrRecurse(Constraint *cmdcon, Relation conrel, Relation tgrel,
11861
11867
{
11862
11868
HeapTuplecopyTuple;
11863
11869
Form_pg_constraint copy_con;
11864
- HeapTupletgtuple;
11865
- ScanKeyData tgkey;
11866
- SysScanDesc tgscan;
11867
11870
11868
11871
copyTuple = heap_copytuple(contuple);
11869
11872
copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple);
@@ -11884,53 +11887,8 @@ ATExecAlterConstrRecurse(Constraint *cmdcon, Relation conrel, Relation tgrel,
11884
11887
* Now we need to update the multiple entries in pg_trigger that
11885
11888
* implement the constraint.
11886
11889
*/
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
- HeapTupletgCopyTuple;
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);
11934
11892
}
11935
11893
11936
11894
/*
@@ -11943,34 +11901,118 @@ ATExecAlterConstrRecurse(Constraint *cmdcon, Relation conrel, Relation tgrel,
11943
11901
*/
11944
11902
if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE ||
11945
11903
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
+ HeapTupletgtuple;
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)))
11946
11933
{
11947
- ScanKeyData pkey ;
11948
- SysScanDesc pscan ;
11949
- HeapTuplechildtup ;
11934
+ Form_pg_trigger tgform = (Form_pg_trigger) GETSTRUCT(tgtuple) ;
11935
+ Form_pg_trigger copy_tg ;
11936
+ HeapTupletgCopyTuple ;
11950
11937
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);
11955
11947
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;
11958
11959
11959
- while (HeapTupleIsValid(childtup = systable_getnext(pscan)))
11960
- {
11961
- Form_pg_constraint childcon = (Form_pg_constraint) GETSTRUCT(childtup);
11962
- Relationchildrel;
11960
+ tgCopyTuple = heap_copytuple(tgtuple);
11961
+ copy_tg = (Form_pg_trigger) GETSTRUCT(tgCopyTuple);
11963
11962
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);
11969
11968
11970
- systable_endscan(pscan );
11969
+ heap_freetuple(tgCopyTuple );
11971
11970
}
11972
11971
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
+ Oidconoid;
11989
+ ScanKeyData pkey;
11990
+ SysScanDesc pscan;
11991
+ HeapTuplechildtup;
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
+ Relationchildrel;
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);
11974
12016
}
11975
12017
11976
12018
/*