aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2023-04-05 12:56:30 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2023-04-05 12:56:30 -0400
commit0a6aaf01166c5f8f94abba949b92b2003c7fe9b5 (patch)
treef84dffe06186af7995bff15cdb571c5aa662d280 /src
parent72e78727124ff2919b785e6a38719297bbbfa7f2 (diff)
downloadpostgresql-0a6aaf01166c5f8f94abba949b92b2003c7fe9b5.tar.gz
postgresql-0a6aaf01166c5f8f94abba949b92b2003c7fe9b5.zip
Fix another issue with ENABLE/DISABLE TRIGGER on partitioned tables.
In v13 and v14, the ENABLE/DISABLE TRIGGER USER variant malfunctioned on cloned triggers, failing to find the clones because it thought they were system triggers. Other variants of ENABLE/DISABLE TRIGGER would improperly apply a superuserness check. Fix by adjusting the is-it- a-system-trigger check to match reality in those branches. (As far as I can find, this is the only place that got it wrong.) There's no such bug in v15/HEAD, because we revised the catalog representation of system triggers to be what this code was expecting. However, add the test case to these branches anyway, because this area is visibly pretty fragile. Also remove an obsoleted comment. The recent v15/HEAD commit 6949b921d fixed a nearby bug. I now see that my commit message for that was inaccurate: the behavior of recursing to clone triggers is older than v15, but it didn't apply to the case in v13/v14 because in those branches parent partitioned tables have no pg_trigger entries for foreign-key triggers. But add the test case from that commit to v13/v14, just to show what is happening there. Per bug #17886 from DzmitryH. Discussion: https://postgr.es/m/17886-5406d5d828aa4aa3@postgresql.org
Diffstat (limited to 'src')
-rw-r--r--src/backend/commands/trigger.c2
-rw-r--r--src/test/regress/expected/triggers.out39
-rw-r--r--src/test/regress/sql/triggers.sql21
3 files changed, 61 insertions, 1 deletions
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index b19f3c8c6da..63fffb48e63 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -1589,7 +1589,7 @@ EnableDisableTriggerNew(Relation rel, const char *tgname,
{
Form_pg_trigger oldtrig = (Form_pg_trigger) GETSTRUCT(tuple);
- if (oldtrig->tgisinternal)
+ if (oldtrig->tgisinternal && !OidIsValid(oldtrig->tgparentid))
{
/* system trigger ... ok to process? */
if (skip_system)
diff --git a/src/test/regress/expected/triggers.out b/src/test/regress/expected/triggers.out
index d006b8cc631..45562bd35c4 100644
--- a/src/test/regress/expected/triggers.out
+++ b/src/test/regress/expected/triggers.out
@@ -2692,6 +2692,45 @@ select tgrelid::regclass, tgname, tgenabled from pg_trigger
parent | tg_stmt | A
(3 rows)
+-- This variant malfunctioned in some releases.
+alter table parent disable trigger user;
+select tgrelid::regclass, tgname, tgenabled from pg_trigger
+ where tgrelid in ('parent'::regclass, 'child1'::regclass)
+ order by tgrelid::regclass::text, tgname;
+ tgrelid | tgname | tgenabled
+---------+---------+-----------
+ child1 | tg | D
+ parent | tg | D
+ parent | tg_stmt | D
+(3 rows)
+
+drop table parent, child1;
+-- Check processing of foreign key triggers
+create table parent (a int primary key, f int references parent)
+ partition by list (a);
+create table child1 partition of parent for values in (1);
+select tgrelid::regclass, rtrim(tgname, '0123456789') as tgname,
+ tgfoid::regproc, tgenabled
+ from pg_trigger where tgrelid in ('parent'::regclass, 'child1'::regclass)
+ order by tgrelid::regclass::text, tgfoid;
+ tgrelid | tgname | tgfoid | tgenabled
+---------+-------------------------+---------------------+-----------
+ child1 | RI_ConstraintTrigger_c_ | "RI_FKey_check_ins" | O
+ child1 | RI_ConstraintTrigger_c_ | "RI_FKey_check_upd" | O
+(2 rows)
+
+-- Before v15, this has no effect because parent has no triggers:
+alter table parent disable trigger all;
+select tgrelid::regclass, rtrim(tgname, '0123456789') as tgname,
+ tgfoid::regproc, tgenabled
+ from pg_trigger where tgrelid in ('parent'::regclass, 'child1'::regclass)
+ order by tgrelid::regclass::text, tgfoid;
+ tgrelid | tgname | tgfoid | tgenabled
+---------+-------------------------+---------------------+-----------
+ child1 | RI_ConstraintTrigger_c_ | "RI_FKey_check_ins" | O
+ child1 | RI_ConstraintTrigger_c_ | "RI_FKey_check_upd" | O
+(2 rows)
+
drop table parent, child1;
-- Verify that firing state propagates correctly on creation, too
CREATE TABLE trgfire (i int) PARTITION BY RANGE (i);
diff --git a/src/test/regress/sql/triggers.sql b/src/test/regress/sql/triggers.sql
index dd5f0948b15..a1aa52521e7 100644
--- a/src/test/regress/sql/triggers.sql
+++ b/src/test/regress/sql/triggers.sql
@@ -1848,6 +1848,27 @@ alter table parent enable always trigger tg;
select tgrelid::regclass, tgname, tgenabled from pg_trigger
where tgrelid in ('parent'::regclass, 'child1'::regclass)
order by tgrelid::regclass::text, tgname;
+-- This variant malfunctioned in some releases.
+alter table parent disable trigger user;
+select tgrelid::regclass, tgname, tgenabled from pg_trigger
+ where tgrelid in ('parent'::regclass, 'child1'::regclass)
+ order by tgrelid::regclass::text, tgname;
+drop table parent, child1;
+
+-- Check processing of foreign key triggers
+create table parent (a int primary key, f int references parent)
+ partition by list (a);
+create table child1 partition of parent for values in (1);
+select tgrelid::regclass, rtrim(tgname, '0123456789') as tgname,
+ tgfoid::regproc, tgenabled
+ from pg_trigger where tgrelid in ('parent'::regclass, 'child1'::regclass)
+ order by tgrelid::regclass::text, tgfoid;
+-- Before v15, this has no effect because parent has no triggers:
+alter table parent disable trigger all;
+select tgrelid::regclass, rtrim(tgname, '0123456789') as tgname,
+ tgfoid::regproc, tgenabled
+ from pg_trigger where tgrelid in ('parent'::regclass, 'child1'::regclass)
+ order by tgrelid::regclass::text, tgfoid;
drop table parent, child1;
-- Verify that firing state propagates correctly on creation, too