Skip to content

Commit b9b408c

Browse files
committed
Record parents of triggers
This let us get rid of a recently introduced ugly hack (commit 1fa846f). Author: Álvaro Herrera Reviewed-by: Amit Langote, Tom Lane Discussion: https://postgr.es/m/20200217215641.GA29784@alvherre.pgsql
1 parent c4b0edb commit b9b408c

File tree

7 files changed

+40
-54
lines changed

7 files changed

+40
-54
lines changed

doc/src/sgml/catalogs.sgml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6951,6 +6951,17 @@ SCRAM-SHA-256$<replaceable>&lt;iteration count&gt;</replaceable>:<replaceable>&l
69516951
<entry>The table this trigger is on</entry>
69526952
</row>
69536953

6954+
<row>
6955+
<entry><structfield>tgparentid</structfield></entry>
6956+
<entry><type>oid</type></entry>
6957+
<entry><literal><link linkend="catalog-pg-trigger"><structname>pg_trigger</structname></link>.oid</literal></entry>
6958+
<entry>
6959+
Parent trigger that this trigger is cloned from, zero if not a clone;
6960+
this happens when partitions are created or attached to a partitioned
6961+
table.
6962+
</entry>
6963+
</row>
6964+
69546965
<row>
69556966
<entry><structfield>tgname</structfield></entry>
69566967
<entry><type>name</type></entry>

src/backend/commands/tablecmds.c

Lines changed: 5 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -16447,54 +16447,6 @@ AttachPartitionEnsureIndexes(Relation rel, Relation attachrel)
1644716447
MemoryContextDelete(cxt);
1644816448
}
1644916449

16450-
/*
16451-
* isPartitionTrigger
16452-
* Subroutine for CloneRowTriggersToPartition: determine whether
16453-
* the given trigger has been cloned from another one.
16454-
*
16455-
* We use pg_depend as a proxy for this, since we don't have any direct
16456-
* evidence. This is an ugly hack to cope with a catalog deficiency.
16457-
* Keep away from children. Do not stare with naked eyes. Do not propagate.
16458-
*/
16459-
static bool
16460-
isPartitionTrigger(Oid trigger_oid)
16461-
{
16462-
Relation pg_depend;
16463-
ScanKeyData key[2];
16464-
SysScanDesc scan;
16465-
HeapTuple tup;
16466-
bool found = false;
16467-
16468-
pg_depend = table_open(DependRelationId, AccessShareLock);
16469-
16470-
ScanKeyInit(&key[0], Anum_pg_depend_classid,
16471-
BTEqualStrategyNumber,
16472-
F_OIDEQ,
16473-
ObjectIdGetDatum(TriggerRelationId));
16474-
ScanKeyInit(&key[1], Anum_pg_depend_objid,
16475-
BTEqualStrategyNumber,
16476-
F_OIDEQ,
16477-
ObjectIdGetDatum(trigger_oid));
16478-
16479-
scan = systable_beginscan(pg_depend, DependDependerIndexId,
16480-
true, NULL, 2, key);
16481-
while ((tup = systable_getnext(scan)) != NULL)
16482-
{
16483-
Form_pg_depend dep = (Form_pg_depend) GETSTRUCT(tup);
16484-
16485-
if (dep->refclassid == TriggerRelationId)
16486-
{
16487-
found = true;
16488-
break;
16489-
}
16490-
}
16491-
16492-
systable_endscan(scan);
16493-
table_close(pg_depend, AccessShareLock);
16494-
16495-
return found;
16496-
}
16497-
1649816450
/*
1649916451
* CloneRowTriggersToPartition
1650016452
* subroutine for ATExecAttachPartition/DefineRelation to create row
@@ -16537,19 +16489,18 @@ CloneRowTriggersToPartition(Relation parent, Relation partition)
1653716489

1653816490
/*
1653916491
* Internal triggers require careful examination. Ideally, we don't
16540-
* clone them.
16541-
*
16542-
* However, if our parent is a partitioned relation, there might be
16543-
* internal triggers that need cloning. In that case, we must skip
16544-
* clone it if the trigger on parent depends on another trigger.
16492+
* clone them. However, if our parent is itself a partition, there
16493+
* might be internal triggers that must not be skipped; for example,
16494+
* triggers on our parent that are in turn clones from its parent (our
16495+
* grandparent) are marked internal, yet they are to be cloned.
1654516496
*
1654616497
* Note we dare not verify that the other trigger belongs to an
1654716498
* ancestor relation of our parent, because that creates deadlock
1654816499
* opportunities.
1654916500
*/
1655016501
if (trigForm->tgisinternal &&
1655116502
(!parent->rd_rel->relispartition ||
16552-
!isPartitionTrigger(trigForm->oid)))
16503+
!OidIsValid(trigForm->tgparentid)))
1655316504
continue;
1655416505

1655516506
/*

src/backend/commands/trigger.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -847,6 +847,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString,
847847

848848
values[Anum_pg_trigger_oid - 1] = ObjectIdGetDatum(trigoid);
849849
values[Anum_pg_trigger_tgrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel));
850+
values[Anum_pg_trigger_tgparentid - 1] = ObjectIdGetDatum(parentTriggerOid);
850851
values[Anum_pg_trigger_tgname - 1] = DirectFunctionCall1(namein,
851852
CStringGetDatum(trigname));
852853
values[Anum_pg_trigger_tgfoid - 1] = ObjectIdGetDatum(funcoid);

src/include/catalog/pg_trigger.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ CATALOG(pg_trigger,2620,TriggerRelationId)
3535
{
3636
Oid oid; /* oid */
3737
Oid tgrelid; /* relation trigger is attached to */
38+
Oid tgparentid; /* OID of parent trigger, if any */
3839
NameData tgname; /* trigger's name */
3940
Oid tgfoid; /* OID of function to be called */
4041
int16 tgtype; /* BEFORE/AFTER/INSTEAD, UPDATE/DELETE/INSERT,

src/test/regress/expected/sanity_check.out

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,9 @@ timestamp_tbl|f
208208
timestamptz_tbl|f
209209
timetz_tbl|f
210210
tmp|f
211+
trigger_parted|t
212+
trigger_parted_p1|t
213+
trigger_parted_p1_1|t
211214
varchar_tbl|f
212215
view_base_table|t
213216
-- restore normal output mode

src/test/regress/expected/triggers.out

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2928,3 +2928,12 @@ drop table self_ref;
29282928
drop function dump_insert();
29292929
drop function dump_update();
29302930
drop function dump_delete();
2931+
-- Leave around some objects for other tests
2932+
create table trigger_parted (a int primary key) partition by list (a);
2933+
create function trigger_parted_trigfunc() returns trigger language plpgsql as
2934+
$$ begin end; $$;
2935+
create trigger aft_row after insert or update on trigger_parted
2936+
for each row execute function trigger_parted_trigfunc();
2937+
create table trigger_parted_p1 partition of trigger_parted for values in (1)
2938+
partition by list (a);
2939+
create table trigger_parted_p1_1 partition of trigger_parted_p1 for values in (1);

src/test/regress/sql/triggers.sql

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2213,3 +2213,13 @@ drop table self_ref;
22132213
drop function dump_insert();
22142214
drop function dump_update();
22152215
drop function dump_delete();
2216+
2217+
-- Leave around some objects for other tests
2218+
create table trigger_parted (a int primary key) partition by list (a);
2219+
create function trigger_parted_trigfunc() returns trigger language plpgsql as
2220+
$$ begin end; $$;
2221+
create trigger aft_row after insert or update on trigger_parted
2222+
for each row execute function trigger_parted_trigfunc();
2223+
create table trigger_parted_p1 partition of trigger_parted for values in (1)
2224+
partition by list (a);
2225+
create table trigger_parted_p1_1 partition of trigger_parted_p1 for values in (1);

0 commit comments

Comments
 (0)