diff options
-rw-r--r-- | doc/src/sgml/catalogs.sgml | 11 | ||||
-rw-r--r-- | src/backend/commands/tablecmds.c | 59 | ||||
-rw-r--r-- | src/backend/commands/trigger.c | 1 | ||||
-rw-r--r-- | src/include/catalog/pg_trigger.h | 1 | ||||
-rw-r--r-- | src/test/regress/expected/sanity_check.out | 3 | ||||
-rw-r--r-- | src/test/regress/expected/triggers.out | 9 | ||||
-rw-r--r-- | src/test/regress/sql/triggers.sql | 10 |
7 files changed, 40 insertions, 54 deletions
diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index a10b66569b9..34bc0d05266 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -6952,6 +6952,17 @@ SCRAM-SHA-256$<replaceable><iteration count></replaceable>:<replaceable>&l </row> <row> + <entry><structfield>tgparentid</structfield></entry> + <entry><type>oid</type></entry> + <entry><literal><link linkend="catalog-pg-trigger"><structname>pg_trigger</structname></link>.oid</literal></entry> + <entry> + Parent trigger that this trigger is cloned from, zero if not a clone; + this happens when partitions are created or attached to a partitioned + table. + </entry> + </row> + + <row> <entry><structfield>tgname</structfield></entry> <entry><type>name</type></entry> <entry></entry> diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index b7c8d663fc4..02a7c04fdb7 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -16448,54 +16448,6 @@ out: } /* - * 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 * triggers on partitions @@ -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; /* diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c index b9b1262e300..6e8b7223fe5 100644 --- a/src/backend/commands/trigger.c +++ b/src/backend/commands/trigger.c @@ -847,6 +847,7 @@ CreateTrigger(CreateTrigStmt *stmt, const char *queryString, values[Anum_pg_trigger_oid - 1] = ObjectIdGetDatum(trigoid); values[Anum_pg_trigger_tgrelid - 1] = ObjectIdGetDatum(RelationGetRelid(rel)); + values[Anum_pg_trigger_tgparentid - 1] = ObjectIdGetDatum(parentTriggerOid); values[Anum_pg_trigger_tgname - 1] = DirectFunctionCall1(namein, CStringGetDatum(trigname)); values[Anum_pg_trigger_tgfoid - 1] = ObjectIdGetDatum(funcoid); diff --git a/src/include/catalog/pg_trigger.h b/src/include/catalog/pg_trigger.h index 2f30c7c2f94..9612b9bdd65 100644 --- a/src/include/catalog/pg_trigger.h +++ b/src/include/catalog/pg_trigger.h @@ -35,6 +35,7 @@ CATALOG(pg_trigger,2620,TriggerRelationId) { Oid oid; /* oid */ Oid tgrelid; /* relation trigger is attached to */ + Oid tgparentid; /* OID of parent trigger, if any */ NameData tgname; /* trigger's name */ Oid tgfoid; /* OID of function to be called */ int16 tgtype; /* BEFORE/AFTER/INSTEAD, UPDATE/DELETE/INSERT, diff --git a/src/test/regress/expected/sanity_check.out b/src/test/regress/expected/sanity_check.out index 45b421b747a..192445878d2 100644 --- a/src/test/regress/expected/sanity_check.out +++ b/src/test/regress/expected/sanity_check.out @@ -208,6 +208,9 @@ timestamp_tbl|f timestamptz_tbl|f timetz_tbl|f tmp|f +trigger_parted|t +trigger_parted_p1|t +trigger_parted_p1_1|t varchar_tbl|f view_base_table|t -- restore normal output mode diff --git a/src/test/regress/expected/triggers.out b/src/test/regress/expected/triggers.out index b91fbd06481..22e65cc1ece 100644 --- a/src/test/regress/expected/triggers.out +++ b/src/test/regress/expected/triggers.out @@ -2928,3 +2928,12 @@ drop table self_ref; drop function dump_insert(); drop function dump_update(); drop function dump_delete(); +-- Leave around some objects for other tests +create table trigger_parted (a int primary key) partition by list (a); +create function trigger_parted_trigfunc() returns trigger language plpgsql as + $$ begin end; $$; +create trigger aft_row after insert or update on trigger_parted + for each row execute function trigger_parted_trigfunc(); +create table trigger_parted_p1 partition of trigger_parted for values in (1) + partition by list (a); +create table trigger_parted_p1_1 partition of trigger_parted_p1 for values in (1); diff --git a/src/test/regress/sql/triggers.sql b/src/test/regress/sql/triggers.sql index 7cd835449c5..0f61fdf0ea2 100644 --- a/src/test/regress/sql/triggers.sql +++ b/src/test/regress/sql/triggers.sql @@ -2213,3 +2213,13 @@ drop table self_ref; drop function dump_insert(); drop function dump_update(); drop function dump_delete(); + +-- Leave around some objects for other tests +create table trigger_parted (a int primary key) partition by list (a); +create function trigger_parted_trigfunc() returns trigger language plpgsql as + $$ begin end; $$; +create trigger aft_row after insert or update on trigger_parted + for each row execute function trigger_parted_trigfunc(); +create table trigger_parted_p1 partition of trigger_parted for values in (1) + partition by list (a); +create table trigger_parted_p1_1 partition of trigger_parted_p1 for values in (1); |