Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit1d26c2d

Browse files
committed
refactor: Split tryAttachPartitionForeignKey()
Split tryAttachPartitionForeignKey() into three functions:AttachPartitionForeignKey(), RemoveInheritedConstraint(), andDropForeignKeyConstraintTriggers(), so they can be reused in somesubsequent patches for the NOT ENFORCED feature.Author: Amul Sul <amul.sul@enterprisedb.com>Reviewed-by: Alexandra Wang <alexandra.wang.oss@gmail.com>Discussion:https://www.postgresql.org/message-id/flat/CAAJ_b962c5AcYW9KUt_R_ER5qs3fUGbe4az-SP-vuwPS-w-AGA%40mail.gmail.com
1 parent64224a8 commit1d26c2d

File tree

1 file changed

+204
-115
lines changed

1 file changed

+204
-115
lines changed

‎src/backend/commands/tablecmds.c

Lines changed: 204 additions & 115 deletions
Original file line numberDiff line numberDiff line change
@@ -585,6 +585,14 @@ static bool tryAttachPartitionForeignKey(List **wqueue,
585585
Oid parentInsTrigger,
586586
Oid parentUpdTrigger,
587587
Relation trigrel);
588+
static void AttachPartitionForeignKey(List **wqueue, Relation partition,
589+
Oid partConstrOid, Oid parentConstrOid,
590+
Oid parentInsTrigger, Oid parentUpdTrigger,
591+
Relation trigrel);
592+
static void RemoveInheritedConstraint(Relation conrel, Relation trigrel,
593+
Oid conoid, Oid conrelid);
594+
static void DropForeignKeyConstraintTriggers(Relation trigrel, Oid conoid,
595+
Oid confrelid, Oid conrelid);
588596
static void GetForeignKeyActionTriggers(Relation trigrel,
589597
Oid conoid, Oid confrelid, Oid conrelid,
590598
Oid *deleteTriggerOid,
@@ -11467,12 +11475,6 @@ tryAttachPartitionForeignKey(List **wqueue,
1146711475
Form_pg_constraint parentConstr;
1146811476
HeapTuplepartcontup;
1146911477
Form_pg_constraint partConstr;
11470-
boolqueueValidation;
11471-
ScanKeyData key;
11472-
SysScanDesc scan;
11473-
HeapTupletrigtup;
11474-
OidinsertTriggerOid,
11475-
updateTriggerOid;
1147611478

1147711479
parentConstrTup = SearchSysCache1(CONSTROID,
1147811480
ObjectIdGetDatum(parentConstrOid));
@@ -11517,6 +11519,59 @@ tryAttachPartitionForeignKey(List **wqueue,
1151711519
return false;
1151811520
}
1151911521

11522+
ReleaseSysCache(parentConstrTup);
11523+
ReleaseSysCache(partcontup);
11524+
11525+
/* Looks good! Attach this constraint. */
11526+
AttachPartitionForeignKey(wqueue, partition, fk->conoid,
11527+
parentConstrOid, parentInsTrigger,
11528+
parentUpdTrigger, trigrel);
11529+
11530+
return true;
11531+
}
11532+
11533+
/*
11534+
* AttachPartitionForeignKey
11535+
*
11536+
* The subroutine for tryAttachPartitionForeignKey performs the final tasks of
11537+
* attaching the constraint, removing redundant triggers and entries from
11538+
* pg_constraint, and setting the constraint's parent.
11539+
*/
11540+
static void
11541+
AttachPartitionForeignKey(List **wqueue,
11542+
Relation partition,
11543+
Oid partConstrOid,
11544+
Oid parentConstrOid,
11545+
Oid parentInsTrigger,
11546+
Oid parentUpdTrigger,
11547+
Relation trigrel)
11548+
{
11549+
HeapTupleparentConstrTup;
11550+
Form_pg_constraint parentConstr;
11551+
HeapTuplepartcontup;
11552+
Form_pg_constraint partConstr;
11553+
boolqueueValidation;
11554+
OidpartConstrFrelid;
11555+
OidpartConstrRelid;
11556+
OidinsertTriggerOid,
11557+
updateTriggerOid;
11558+
11559+
/* Fetch the parent constraint tuple */
11560+
parentConstrTup = SearchSysCache1(CONSTROID,
11561+
ObjectIdGetDatum(parentConstrOid));
11562+
if (!HeapTupleIsValid(parentConstrTup))
11563+
elog(ERROR, "cache lookup failed for constraint %u", parentConstrOid);
11564+
parentConstr = (Form_pg_constraint) GETSTRUCT(parentConstrTup);
11565+
11566+
/* Fetch the child constraint tuple */
11567+
partcontup = SearchSysCache1(CONSTROID,
11568+
ObjectIdGetDatum(partConstrOid));
11569+
if (!HeapTupleIsValid(partcontup))
11570+
elog(ERROR, "cache lookup failed for constraint %u", partConstrOid);
11571+
partConstr = (Form_pg_constraint) GETSTRUCT(partcontup);
11572+
partConstrFrelid = partConstr->confrelid;
11573+
partConstrRelid = partConstr->conrelid;
11574+
1152011575
/*
1152111576
* Will we need to validate this constraint? A valid parent constraint
1152211577
* implies that all child constraints have been validated, so if this one
@@ -11528,58 +11583,23 @@ tryAttachPartitionForeignKey(List **wqueue,
1152811583
ReleaseSysCache(parentConstrTup);
1152911584

1153011585
/*
11531-
* Looks good! Attach this constraint. The action triggers in the new
11532-
* partition become redundant -- the parent table already has equivalent
11533-
* ones, and those will be able to reach the partition. Remove the ones
11534-
* in the partition. We identify them because they have our constraint
11535-
* OID, as well as being on the referenced rel.
11586+
* The action triggers in the new partition become redundant -- the parent
11587+
* table already has equivalent ones, and those will be able to reach the
11588+
* partition. Remove the ones in the partition. We identify them because
11589+
* they have our constraint OID, as well as being on the referenced rel.
1153611590
*/
11537-
ScanKeyInit(&key,
11538-
Anum_pg_trigger_tgconstraint,
11539-
BTEqualStrategyNumber, F_OIDEQ,
11540-
ObjectIdGetDatum(fk->conoid));
11541-
scan = systable_beginscan(trigrel, TriggerConstraintIndexId, true,
11542-
NULL, 1, &key);
11543-
while ((trigtup = systable_getnext(scan)) != NULL)
11544-
{
11545-
Form_pg_trigger trgform = (Form_pg_trigger) GETSTRUCT(trigtup);
11546-
ObjectAddress trigger;
11591+
DropForeignKeyConstraintTriggers(trigrel, partConstrOid, partConstrFrelid,
11592+
partConstrRelid);
1154711593

11548-
if (trgform->tgconstrrelid != fk->conrelid)
11549-
continue;
11550-
if (trgform->tgrelid != fk->confrelid)
11551-
continue;
11552-
11553-
/*
11554-
* The constraint is originally set up to contain this trigger as an
11555-
* implementation object, so there's a dependency record that links
11556-
* the two; however, since the trigger is no longer needed, we remove
11557-
* the dependency link in order to be able to drop the trigger while
11558-
* keeping the constraint intact.
11559-
*/
11560-
deleteDependencyRecordsFor(TriggerRelationId,
11561-
trgform->oid,
11562-
false);
11563-
/* make dependency deletion visible to performDeletion */
11564-
CommandCounterIncrement();
11565-
ObjectAddressSet(trigger, TriggerRelationId,
11566-
trgform->oid);
11567-
performDeletion(&trigger, DROP_RESTRICT, 0);
11568-
/* make trigger drop visible, in case the loop iterates */
11569-
CommandCounterIncrement();
11570-
}
11571-
11572-
systable_endscan(scan);
11573-
11574-
ConstraintSetParentConstraint(fk->conoid, parentConstrOid,
11594+
ConstraintSetParentConstraint(partConstrOid, parentConstrOid,
1157511595
RelationGetRelid(partition));
1157611596

1157711597
/*
1157811598
* Like the constraint, attach partition's "check" triggers to the
1157911599
* corresponding parent triggers.
1158011600
*/
1158111601
GetForeignKeyCheckTriggers(trigrel,
11582-
fk->conoid, fk->confrelid, fk->conrelid,
11602+
partConstrOid, partConstrFrelid, partConstrRelid,
1158311603
&insertTriggerOid, &updateTriggerOid);
1158411604
Assert(OidIsValid(insertTriggerOid) && OidIsValid(parentInsTrigger));
1158511605
TriggerSetParentTrigger(trigrel, insertTriggerOid, parentInsTrigger,
@@ -11593,72 +11613,12 @@ tryAttachPartitionForeignKey(List **wqueue,
1159311613
* attaching now has extra pg_constraint rows and action triggers that are
1159411614
* no longer needed. Remove those.
1159511615
*/
11596-
if (get_rel_relkind(fk->confrelid) == RELKIND_PARTITIONED_TABLE)
11616+
if (get_rel_relkind(partConstrFrelid) == RELKIND_PARTITIONED_TABLE)
1159711617
{
1159811618
Relationpg_constraint = table_open(ConstraintRelationId, RowShareLock);
11599-
ObjectAddresses *objs;
11600-
HeapTupleconsttup;
11601-
11602-
ScanKeyInit(&key,
11603-
Anum_pg_constraint_conrelid,
11604-
BTEqualStrategyNumber, F_OIDEQ,
11605-
ObjectIdGetDatum(fk->conrelid));
11606-
11607-
scan = systable_beginscan(pg_constraint,
11608-
ConstraintRelidTypidNameIndexId,
11609-
true, NULL, 1, &key);
11610-
objs = new_object_addresses();
11611-
while ((consttup = systable_getnext(scan)) != NULL)
11612-
{
11613-
Form_pg_constraint conform = (Form_pg_constraint) GETSTRUCT(consttup);
11614-
11615-
if (conform->conparentid != fk->conoid)
11616-
continue;
11617-
else
11618-
{
11619-
ObjectAddress addr;
11620-
SysScanDesc scan2;
11621-
ScanKeyData key2;
11622-
intn PG_USED_FOR_ASSERTS_ONLY;
1162311619

11624-
ObjectAddressSet(addr, ConstraintRelationId, conform->oid);
11625-
add_exact_object_address(&addr, objs);
11626-
11627-
/*
11628-
* First we must delete the dependency record that binds the
11629-
* constraint records together.
11630-
*/
11631-
n = deleteDependencyRecordsForSpecific(ConstraintRelationId,
11632-
conform->oid,
11633-
DEPENDENCY_INTERNAL,
11634-
ConstraintRelationId,
11635-
fk->conoid);
11636-
Assert(n == 1); /* actually only one is expected */
11637-
11638-
/*
11639-
* Now search for the triggers for this constraint and set
11640-
* them up for deletion too
11641-
*/
11642-
ScanKeyInit(&key2,
11643-
Anum_pg_trigger_tgconstraint,
11644-
BTEqualStrategyNumber, F_OIDEQ,
11645-
ObjectIdGetDatum(conform->oid));
11646-
scan2 = systable_beginscan(trigrel, TriggerConstraintIndexId,
11647-
true, NULL, 1, &key2);
11648-
while ((trigtup = systable_getnext(scan2)) != NULL)
11649-
{
11650-
ObjectAddressSet(addr, TriggerRelationId,
11651-
((Form_pg_trigger) GETSTRUCT(trigtup))->oid);
11652-
add_exact_object_address(&addr, objs);
11653-
}
11654-
systable_endscan(scan2);
11655-
}
11656-
}
11657-
/* make the dependency deletions visible */
11658-
CommandCounterIncrement();
11659-
performMultipleDeletions(objs, DROP_RESTRICT,
11660-
PERFORM_DELETION_INTERNAL);
11661-
systable_endscan(scan);
11620+
RemoveInheritedConstraint(pg_constraint, trigrel, partConstrOid,
11621+
partConstrRelid);
1166211622

1166311623
table_close(pg_constraint, RowShareLock);
1166411624
}
@@ -11679,18 +11639,147 @@ tryAttachPartitionForeignKey(List **wqueue,
1167911639
Relationconrel;
1168011640

1168111641
conrel = table_open(ConstraintRelationId, RowExclusiveLock);
11682-
partcontup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(fk->conoid));
11642+
11643+
partcontup = SearchSysCache1(CONSTROID, ObjectIdGetDatum(partConstrOid));
1168311644
if (!HeapTupleIsValid(partcontup))
11684-
elog(ERROR, "cache lookup failed for constraint %u",fk->conoid);
11645+
elog(ERROR, "cache lookup failed for constraint %u",partConstrOid);
1168511646

1168611647
/* Use the same lock as for AT_ValidateConstraint */
1168711648
QueueFKConstraintValidation(wqueue, conrel, partition, partcontup,
1168811649
ShareUpdateExclusiveLock);
1168911650
ReleaseSysCache(partcontup);
1169011651
table_close(conrel, RowExclusiveLock);
1169111652
}
11653+
}
1169211654

11693-
return true;
11655+
/*
11656+
* RemoveInheritedConstraint
11657+
*
11658+
* Removes the constraint and its associated trigger from the specified
11659+
* relation, which inherited the given constraint.
11660+
*/
11661+
static void
11662+
RemoveInheritedConstraint(Relation conrel, Relation trigrel, Oid conoid,
11663+
Oid conrelid)
11664+
{
11665+
ObjectAddresses *objs;
11666+
HeapTupleconsttup;
11667+
ScanKeyData key;
11668+
SysScanDesc scan;
11669+
HeapTupletrigtup;
11670+
11671+
ScanKeyInit(&key,
11672+
Anum_pg_constraint_conrelid,
11673+
BTEqualStrategyNumber, F_OIDEQ,
11674+
ObjectIdGetDatum(conrelid));
11675+
11676+
scan = systable_beginscan(conrel,
11677+
ConstraintRelidTypidNameIndexId,
11678+
true, NULL, 1, &key);
11679+
objs = new_object_addresses();
11680+
while ((consttup = systable_getnext(scan)) != NULL)
11681+
{
11682+
Form_pg_constraint conform = (Form_pg_constraint) GETSTRUCT(consttup);
11683+
11684+
if (conform->conparentid != conoid)
11685+
continue;
11686+
else
11687+
{
11688+
ObjectAddress addr;
11689+
SysScanDesc scan2;
11690+
ScanKeyData key2;
11691+
intn PG_USED_FOR_ASSERTS_ONLY;
11692+
11693+
ObjectAddressSet(addr, ConstraintRelationId, conform->oid);
11694+
add_exact_object_address(&addr, objs);
11695+
11696+
/*
11697+
* First we must delete the dependency record that binds the
11698+
* constraint records together.
11699+
*/
11700+
n = deleteDependencyRecordsForSpecific(ConstraintRelationId,
11701+
conform->oid,
11702+
DEPENDENCY_INTERNAL,
11703+
ConstraintRelationId,
11704+
conoid);
11705+
Assert(n == 1);/* actually only one is expected */
11706+
11707+
/*
11708+
* Now search for the triggers for this constraint and set them up
11709+
* for deletion too
11710+
*/
11711+
ScanKeyInit(&key2,
11712+
Anum_pg_trigger_tgconstraint,
11713+
BTEqualStrategyNumber, F_OIDEQ,
11714+
ObjectIdGetDatum(conform->oid));
11715+
scan2 = systable_beginscan(trigrel, TriggerConstraintIndexId,
11716+
true, NULL, 1, &key2);
11717+
while ((trigtup = systable_getnext(scan2)) != NULL)
11718+
{
11719+
ObjectAddressSet(addr, TriggerRelationId,
11720+
((Form_pg_trigger) GETSTRUCT(trigtup))->oid);
11721+
add_exact_object_address(&addr, objs);
11722+
}
11723+
systable_endscan(scan2);
11724+
}
11725+
}
11726+
/* make the dependency deletions visible */
11727+
CommandCounterIncrement();
11728+
performMultipleDeletions(objs, DROP_RESTRICT,
11729+
PERFORM_DELETION_INTERNAL);
11730+
systable_endscan(scan);
11731+
}
11732+
11733+
/*
11734+
* DropForeignKeyConstraintTriggers
11735+
*
11736+
* The subroutine for tryAttachPartitionForeignKey handles the deletion of
11737+
* action triggers for the foreign key constraint.
11738+
*/
11739+
static void
11740+
DropForeignKeyConstraintTriggers(Relation trigrel, Oid conoid, Oid confrelid,
11741+
Oid conrelid)
11742+
{
11743+
ScanKeyData key;
11744+
SysScanDesc scan;
11745+
HeapTupletrigtup;
11746+
11747+
ScanKeyInit(&key,
11748+
Anum_pg_trigger_tgconstraint,
11749+
BTEqualStrategyNumber, F_OIDEQ,
11750+
ObjectIdGetDatum(conoid));
11751+
scan = systable_beginscan(trigrel, TriggerConstraintIndexId, true,
11752+
NULL, 1, &key);
11753+
while ((trigtup = systable_getnext(scan)) != NULL)
11754+
{
11755+
Form_pg_trigger trgform = (Form_pg_trigger) GETSTRUCT(trigtup);
11756+
ObjectAddress trigger;
11757+
11758+
if (trgform->tgconstrrelid != conrelid)
11759+
continue;
11760+
if (trgform->tgrelid != confrelid)
11761+
continue;
11762+
11763+
/*
11764+
* The constraint is originally set up to contain this trigger as an
11765+
* implementation object, so there's a dependency record that links
11766+
* the two; however, since the trigger is no longer needed, we remove
11767+
* the dependency link in order to be able to drop the trigger while
11768+
* keeping the constraint intact.
11769+
*/
11770+
deleteDependencyRecordsFor(TriggerRelationId,
11771+
trgform->oid,
11772+
false);
11773+
/* make dependency deletion visible to performDeletion */
11774+
CommandCounterIncrement();
11775+
ObjectAddressSet(trigger, TriggerRelationId,
11776+
trgform->oid);
11777+
performDeletion(&trigger, DROP_RESTRICT, 0);
11778+
/* make trigger drop visible, in case the loop iterates */
11779+
CommandCounterIncrement();
11780+
}
11781+
11782+
systable_endscan(scan);
1169411783
}
1169511784

1169611785
/*

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp