|
|
|
|
@ -16447,54 +16447,6 @@ out: |
|
|
|
|
MemoryContextDelete(cxt); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* isPartitionTrigger |
|
|
|
|
* Subroutine for CloneRowTriggersToPartition: determine whether |
|
|
|
|
* the given trigger has been cloned from another one. |
|
|
|
|
* |
|
|
|
|
* We use pg_depend as a proxy for this, since we don't have any direct |
|
|
|
|
* evidence. This is an ugly hack to cope with a catalog deficiency. |
|
|
|
|
* Keep away from children. Do not stare with naked eyes. Do not propagate. |
|
|
|
|
*/ |
|
|
|
|
static bool |
|
|
|
|
isPartitionTrigger(Oid trigger_oid) |
|
|
|
|
{ |
|
|
|
|
Relation pg_depend; |
|
|
|
|
ScanKeyData key[2]; |
|
|
|
|
SysScanDesc scan; |
|
|
|
|
HeapTuple tup; |
|
|
|
|
bool found = false; |
|
|
|
|
|
|
|
|
|
pg_depend = table_open(DependRelationId, AccessShareLock); |
|
|
|
|
|
|
|
|
|
ScanKeyInit(&key[0], Anum_pg_depend_classid, |
|
|
|
|
BTEqualStrategyNumber, |
|
|
|
|
F_OIDEQ, |
|
|
|
|
ObjectIdGetDatum(TriggerRelationId)); |
|
|
|
|
ScanKeyInit(&key[1], Anum_pg_depend_objid, |
|
|
|
|
BTEqualStrategyNumber, |
|
|
|
|
F_OIDEQ, |
|
|
|
|
ObjectIdGetDatum(trigger_oid)); |
|
|
|
|
|
|
|
|
|
scan = systable_beginscan(pg_depend, DependDependerIndexId, |
|
|
|
|
true, NULL, 2, key); |
|
|
|
|
while ((tup = systable_getnext(scan)) != NULL) |
|
|
|
|
{ |
|
|
|
|
Form_pg_depend dep = (Form_pg_depend) GETSTRUCT(tup); |
|
|
|
|
|
|
|
|
|
if (dep->refclassid == TriggerRelationId) |
|
|
|
|
{ |
|
|
|
|
found = true; |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
systable_endscan(scan); |
|
|
|
|
table_close(pg_depend, AccessShareLock); |
|
|
|
|
|
|
|
|
|
return found; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* CloneRowTriggersToPartition |
|
|
|
|
* subroutine for ATExecAttachPartition/DefineRelation to create row |
|
|
|
|
@ -16537,11 +16489,10 @@ CloneRowTriggersToPartition(Relation parent, Relation partition) |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Internal triggers require careful examination. Ideally, we don't |
|
|
|
|
* clone them. |
|
|
|
|
* |
|
|
|
|
* However, if our parent is a partitioned relation, there might be |
|
|
|
|
* internal triggers that need cloning. In that case, we must skip |
|
|
|
|
* clone it if the trigger on parent depends on another trigger. |
|
|
|
|
* clone them. However, if our parent is itself a partition, there |
|
|
|
|
* might be internal triggers that must not be skipped; for example, |
|
|
|
|
* triggers on our parent that are in turn clones from its parent (our |
|
|
|
|
* grandparent) are marked internal, yet they are to be cloned. |
|
|
|
|
* |
|
|
|
|
* Note we dare not verify that the other trigger belongs to an |
|
|
|
|
* ancestor relation of our parent, because that creates deadlock |
|
|
|
|
@ -16549,7 +16500,7 @@ CloneRowTriggersToPartition(Relation parent, Relation partition) |
|
|
|
|
*/ |
|
|
|
|
if (trigForm->tgisinternal && |
|
|
|
|
(!parent->rd_rel->relispartition || |
|
|
|
|
!isPartitionTrigger(trigForm->oid))) |
|
|
|
|
!OidIsValid(trigForm->tgparentid))) |
|
|
|
|
continue; |
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
|