1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-13 07:41:39 +03:00

refactor: split ATExecAlterConstrRecurse()

This splits out a couple of subroutines from
ATExecAlterConstrRecurse().  This makes the main function a bit
smaller, and a future patch (NOT ENFORCED foreign-key constraints)
will also want to call some of the pieces separately.

Author: Amul Sul <amul.sul@enterprisedb.com>
Reviewed-by: jian he <jian.universality@gmail.com>
Discussion: https://www.postgresql.org/message-id/flat/CAAJ_b962c5AcYW9KUt_R_ER5qs3fUGbe4az-SP-vuwPS-w-AGA%40mail.gmail.com
This commit is contained in:
Peter Eisentraut
2025-01-16 13:22:01 +01:00
parent d278541be4
commit 7a947ed25b

View File

@ -394,6 +394,12 @@ static ObjectAddress ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd,
static bool ATExecAlterConstrRecurse(Constraint *cmdcon, Relation conrel, Relation tgrel,
Relation rel, HeapTuple contuple, List **otherrelids,
LOCKMODE lockmode);
static void AlterConstrTriggerDeferrability(Oid conoid, Relation tgrel, Relation rel,
bool deferrable, bool initdeferred,
List **otherrelids);
static void ATExecAlterChildConstr(Constraint *cmdcon, Relation conrel, Relation tgrel,
Relation rel, HeapTuple contuple, List **otherrelids,
LOCKMODE lockmode);
static ObjectAddress ATExecValidateConstraint(List **wqueue,
Relation rel, char *constrName,
bool recurse, bool recursing, LOCKMODE lockmode);
@ -11861,9 +11867,6 @@ ATExecAlterConstrRecurse(Constraint *cmdcon, Relation conrel, Relation tgrel,
{
HeapTuple copyTuple;
Form_pg_constraint copy_con;
HeapTuple tgtuple;
ScanKeyData tgkey;
SysScanDesc tgscan;
copyTuple = heap_copytuple(contuple);
copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple);
@ -11884,53 +11887,8 @@ ATExecAlterConstrRecurse(Constraint *cmdcon, Relation conrel, Relation tgrel,
* Now we need to update the multiple entries in pg_trigger that
* implement the constraint.
*/
ScanKeyInit(&tgkey,
Anum_pg_trigger_tgconstraint,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(conoid));
tgscan = systable_beginscan(tgrel, TriggerConstraintIndexId, true,
NULL, 1, &tgkey);
while (HeapTupleIsValid(tgtuple = systable_getnext(tgscan)))
{
Form_pg_trigger tgform = (Form_pg_trigger) GETSTRUCT(tgtuple);
Form_pg_trigger copy_tg;
HeapTuple tgCopyTuple;
/*
* Remember OIDs of other relation(s) involved in FK constraint.
* (Note: it's likely that we could skip forcing a relcache inval
* for other rels that don't have a trigger whose properties
* change, but let's be conservative.)
*/
if (tgform->tgrelid != RelationGetRelid(rel))
*otherrelids = list_append_unique_oid(*otherrelids,
tgform->tgrelid);
/*
* Update deferrability of RI_FKey_noaction_del,
* RI_FKey_noaction_upd, RI_FKey_check_ins and RI_FKey_check_upd
* triggers, but not others; see createForeignKeyActionTriggers
* and CreateFKCheckTrigger.
*/
if (tgform->tgfoid != F_RI_FKEY_NOACTION_DEL &&
tgform->tgfoid != F_RI_FKEY_NOACTION_UPD &&
tgform->tgfoid != F_RI_FKEY_CHECK_INS &&
tgform->tgfoid != F_RI_FKEY_CHECK_UPD)
continue;
tgCopyTuple = heap_copytuple(tgtuple);
copy_tg = (Form_pg_trigger) GETSTRUCT(tgCopyTuple);
copy_tg->tgdeferrable = cmdcon->deferrable;
copy_tg->tginitdeferred = cmdcon->initdeferred;
CatalogTupleUpdate(tgrel, &tgCopyTuple->t_self, tgCopyTuple);
InvokeObjectPostAlterHook(TriggerRelationId, tgform->oid, 0);
heap_freetuple(tgCopyTuple);
}
systable_endscan(tgscan);
AlterConstrTriggerDeferrability(conoid, tgrel, rel, cmdcon->deferrable,
cmdcon->initdeferred, otherrelids);
}
/*
@ -11943,36 +11901,120 @@ ATExecAlterConstrRecurse(Constraint *cmdcon, Relation conrel, Relation tgrel,
*/
if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE ||
get_rel_relkind(refrelid) == RELKIND_PARTITIONED_TABLE)
{
ScanKeyData pkey;
SysScanDesc pscan;
HeapTuple childtup;
ScanKeyInit(&pkey,
Anum_pg_constraint_conparentid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(conoid));
pscan = systable_beginscan(conrel, ConstraintParentIndexId,
true, NULL, 1, &pkey);
while (HeapTupleIsValid(childtup = systable_getnext(pscan)))
{
Form_pg_constraint childcon = (Form_pg_constraint) GETSTRUCT(childtup);
Relation childrel;
childrel = table_open(childcon->conrelid, lockmode);
ATExecAlterConstrRecurse(cmdcon, conrel, tgrel, childrel, childtup,
otherrelids, lockmode);
table_close(childrel, NoLock);
}
systable_endscan(pscan);
}
ATExecAlterChildConstr(cmdcon, conrel, tgrel, rel, contuple,
otherrelids, lockmode);
return changed;
}
/*
* A subroutine of ATExecAlterConstrRecurse that updated constraint trigger's
* deferrability.
*
* The arguments to this function have the same meaning as the arguments to
* ATExecAlterConstrRecurse.
*/
static void
AlterConstrTriggerDeferrability(Oid conoid, Relation tgrel, Relation rel,
bool deferrable, bool initdeferred,
List **otherrelids)
{
HeapTuple tgtuple;
ScanKeyData tgkey;
SysScanDesc tgscan;
ScanKeyInit(&tgkey,
Anum_pg_trigger_tgconstraint,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(conoid));
tgscan = systable_beginscan(tgrel, TriggerConstraintIndexId, true,
NULL, 1, &tgkey);
while (HeapTupleIsValid(tgtuple = systable_getnext(tgscan)))
{
Form_pg_trigger tgform = (Form_pg_trigger) GETSTRUCT(tgtuple);
Form_pg_trigger copy_tg;
HeapTuple tgCopyTuple;
/*
* Remember OIDs of other relation(s) involved in FK constraint.
* (Note: it's likely that we could skip forcing a relcache inval for
* other rels that don't have a trigger whose properties change, but
* let's be conservative.)
*/
if (tgform->tgrelid != RelationGetRelid(rel))
*otherrelids = list_append_unique_oid(*otherrelids,
tgform->tgrelid);
/*
* Update enable status and deferrability of RI_FKey_noaction_del,
* RI_FKey_noaction_upd, RI_FKey_check_ins and RI_FKey_check_upd
* triggers, but not others; see createForeignKeyActionTriggers and
* CreateFKCheckTrigger.
*/
if (tgform->tgfoid != F_RI_FKEY_NOACTION_DEL &&
tgform->tgfoid != F_RI_FKEY_NOACTION_UPD &&
tgform->tgfoid != F_RI_FKEY_CHECK_INS &&
tgform->tgfoid != F_RI_FKEY_CHECK_UPD)
continue;
tgCopyTuple = heap_copytuple(tgtuple);
copy_tg = (Form_pg_trigger) GETSTRUCT(tgCopyTuple);
copy_tg->tgdeferrable = deferrable;
copy_tg->tginitdeferred = initdeferred;
CatalogTupleUpdate(tgrel, &tgCopyTuple->t_self, tgCopyTuple);
InvokeObjectPostAlterHook(TriggerRelationId, tgform->oid, 0);
heap_freetuple(tgCopyTuple);
}
systable_endscan(tgscan);
}
/*
* Invokes ATExecAlterConstrRecurse for each constraint that is a child of the
* specified constraint.
*
* The arguments to this function have the same meaning as the arguments to
* ATExecAlterConstrRecurse.
*/
static void
ATExecAlterChildConstr(Constraint *cmdcon, Relation conrel, Relation tgrel,
Relation rel, HeapTuple contuple, List **otherrelids,
LOCKMODE lockmode)
{
Form_pg_constraint currcon;
Oid conoid;
ScanKeyData pkey;
SysScanDesc pscan;
HeapTuple childtup;
currcon = (Form_pg_constraint) GETSTRUCT(contuple);
conoid = currcon->oid;
ScanKeyInit(&pkey,
Anum_pg_constraint_conparentid,
BTEqualStrategyNumber, F_OIDEQ,
ObjectIdGetDatum(conoid));
pscan = systable_beginscan(conrel, ConstraintParentIndexId,
true, NULL, 1, &pkey);
while (HeapTupleIsValid(childtup = systable_getnext(pscan)))
{
Form_pg_constraint childcon = (Form_pg_constraint) GETSTRUCT(childtup);
Relation childrel;
childrel = table_open(childcon->conrelid, lockmode);
ATExecAlterConstrRecurse(cmdcon, conrel, tgrel, childrel, childtup,
otherrelids, lockmode);
table_close(childrel, NoLock);
}
systable_endscan(pscan);
}
/*
* ALTER TABLE VALIDATE CONSTRAINT
*