mirror of
https://github.com/postgres/postgres.git
synced 2025-06-14 18:42:34 +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:
@ -394,6 +394,12 @@ static ObjectAddress ATExecAlterConstraint(Relation rel, AlterTableCmd *cmd,
|
|||||||
static bool ATExecAlterConstrRecurse(Constraint *cmdcon, Relation conrel, Relation tgrel,
|
static bool ATExecAlterConstrRecurse(Constraint *cmdcon, Relation conrel, Relation tgrel,
|
||||||
Relation rel, HeapTuple contuple, List **otherrelids,
|
Relation rel, HeapTuple contuple, List **otherrelids,
|
||||||
LOCKMODE lockmode);
|
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,
|
static ObjectAddress ATExecValidateConstraint(List **wqueue,
|
||||||
Relation rel, char *constrName,
|
Relation rel, char *constrName,
|
||||||
bool recurse, bool recursing, LOCKMODE lockmode);
|
bool recurse, bool recursing, LOCKMODE lockmode);
|
||||||
@ -11861,9 +11867,6 @@ ATExecAlterConstrRecurse(Constraint *cmdcon, Relation conrel, Relation tgrel,
|
|||||||
{
|
{
|
||||||
HeapTuple copyTuple;
|
HeapTuple copyTuple;
|
||||||
Form_pg_constraint copy_con;
|
Form_pg_constraint copy_con;
|
||||||
HeapTuple tgtuple;
|
|
||||||
ScanKeyData tgkey;
|
|
||||||
SysScanDesc tgscan;
|
|
||||||
|
|
||||||
copyTuple = heap_copytuple(contuple);
|
copyTuple = heap_copytuple(contuple);
|
||||||
copy_con = (Form_pg_constraint) GETSTRUCT(copyTuple);
|
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
|
* Now we need to update the multiple entries in pg_trigger that
|
||||||
* implement the constraint.
|
* implement the constraint.
|
||||||
*/
|
*/
|
||||||
ScanKeyInit(&tgkey,
|
AlterConstrTriggerDeferrability(conoid, tgrel, rel, cmdcon->deferrable,
|
||||||
Anum_pg_trigger_tgconstraint,
|
cmdcon->initdeferred, otherrelids);
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -11943,36 +11901,120 @@ ATExecAlterConstrRecurse(Constraint *cmdcon, Relation conrel, Relation tgrel,
|
|||||||
*/
|
*/
|
||||||
if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE ||
|
if (rel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE ||
|
||||||
get_rel_relkind(refrelid) == RELKIND_PARTITIONED_TABLE)
|
get_rel_relkind(refrelid) == RELKIND_PARTITIONED_TABLE)
|
||||||
{
|
ATExecAlterChildConstr(cmdcon, conrel, tgrel, rel, contuple,
|
||||||
ScanKeyData pkey;
|
otherrelids, lockmode);
|
||||||
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);
|
|
||||||
}
|
|
||||||
|
|
||||||
return changed;
|
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
|
* ALTER TABLE VALIDATE CONSTRAINT
|
||||||
*
|
*
|
||||||
|
Reference in New Issue
Block a user