aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFujii Masao <fujii@postgresql.org>2022-07-12 09:18:02 +0900
committerFujii Masao <fujii@postgresql.org>2022-07-12 09:18:02 +0900
commit3b00a944a9b3847fb02dae7c9ea62fe0b211b396 (patch)
treea2abdd3d3fe79c4ac2133d2933f01d9ecc0d5bfa
parent14168d3c62fa90f1ec447f873f0e4df16a57a717 (diff)
downloadpostgresql-3b00a944a9b3847fb02dae7c9ea62fe0b211b396.tar.gz
postgresql-3b00a944a9b3847fb02dae7c9ea62fe0b211b396.zip
Support TRUNCATE triggers on foreign tables.
Now some foreign data wrappers support TRUNCATE command. So it's useful to support TRUNCATE triggers on foreign tables for audit logging or for preventing undesired truncation. Author: Yugo Nagata Reviewed-by: Fujii Masao, Ian Lawrence Barwick Discussion: https://postgr.es/m/20220630193848.5b02e0d6076b86617a915682@sraoss.co.jp
-rw-r--r--contrib/postgres_fdw/expected/postgres_fdw.out9
-rw-r--r--contrib/postgres_fdw/sql/postgres_fdw.sql5
-rw-r--r--doc/src/sgml/ref/create_trigger.sgml4
-rw-r--r--src/backend/commands/trigger.c7
4 files changed, 11 insertions, 14 deletions
diff --git a/contrib/postgres_fdw/expected/postgres_fdw.out b/contrib/postgres_fdw/expected/postgres_fdw.out
index 44457f930c2..5f2ef88cf38 100644
--- a/contrib/postgres_fdw/expected/postgres_fdw.out
+++ b/contrib/postgres_fdw/expected/postgres_fdw.out
@@ -6732,9 +6732,9 @@ BEGIN
TG_ARGV[0], TG_OP, TG_WHEN, TG_LEVEL;
RETURN NULL;
END;$$;
-CREATE TRIGGER trig_stmt_before BEFORE DELETE OR INSERT OR UPDATE ON rem1
+CREATE TRIGGER trig_stmt_before BEFORE DELETE OR INSERT OR UPDATE OR TRUNCATE ON rem1
FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
-CREATE TRIGGER trig_stmt_after AFTER DELETE OR INSERT OR UPDATE ON rem1
+CREATE TRIGGER trig_stmt_after AFTER DELETE OR INSERT OR UPDATE OR TRUNCATE ON rem1
FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
CREATE OR REPLACE FUNCTION trigger_data() RETURNS trigger
LANGUAGE plpgsql AS $$
@@ -6821,6 +6821,9 @@ NOTICE: OLD: (1,update),NEW: (1,updateupdate)
NOTICE: trig_row_after(23, skidoo) AFTER ROW UPDATE ON rem1
NOTICE: OLD: (1,update),NEW: (1,updateupdate)
NOTICE: trigger_func(<NULL>) called: action = UPDATE, when = AFTER, level = STATEMENT
+truncate rem1;
+NOTICE: trigger_func(<NULL>) called: action = TRUNCATE, when = BEFORE, level = STATEMENT
+NOTICE: trigger_func(<NULL>) called: action = TRUNCATE, when = AFTER, level = STATEMENT
-- cleanup
DROP TRIGGER trig_row_before ON rem1;
DROP TRIGGER trig_row_after ON rem1;
@@ -7087,7 +7090,7 @@ NOTICE: trig_row_after(23, skidoo) AFTER ROW INSERT ON rem1
NOTICE: NEW: (13,"test triggered !")
ctid
--------
- (0,32)
+ (0,25)
(1 row)
-- cleanup
diff --git a/contrib/postgres_fdw/sql/postgres_fdw.sql b/contrib/postgres_fdw/sql/postgres_fdw.sql
index 92d12120272..ae1fc8f58be 100644
--- a/contrib/postgres_fdw/sql/postgres_fdw.sql
+++ b/contrib/postgres_fdw/sql/postgres_fdw.sql
@@ -1595,9 +1595,9 @@ BEGIN
RETURN NULL;
END;$$;
-CREATE TRIGGER trig_stmt_before BEFORE DELETE OR INSERT OR UPDATE ON rem1
+CREATE TRIGGER trig_stmt_before BEFORE DELETE OR INSERT OR UPDATE OR TRUNCATE ON rem1
FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
-CREATE TRIGGER trig_stmt_after AFTER DELETE OR INSERT OR UPDATE ON rem1
+CREATE TRIGGER trig_stmt_after AFTER DELETE OR INSERT OR UPDATE OR TRUNCATE ON rem1
FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
CREATE OR REPLACE FUNCTION trigger_data() RETURNS trigger
@@ -1652,6 +1652,7 @@ delete from rem1;
insert into rem1 values(1,'insert');
update rem1 set f2 = 'update' where f1 = 1;
update rem1 set f2 = f2 || f2;
+truncate rem1;
-- cleanup
diff --git a/doc/src/sgml/ref/create_trigger.sgml b/doc/src/sgml/ref/create_trigger.sgml
index ee42f413e96..982ab6f3ee4 100644
--- a/doc/src/sgml/ref/create_trigger.sgml
+++ b/doc/src/sgml/ref/create_trigger.sgml
@@ -131,7 +131,7 @@ CREATE [ OR REPLACE ] [ CONSTRAINT ] TRIGGER <replaceable class="parameter">name
<row>
<entry align="center"><command>TRUNCATE</command></entry>
<entry align="center">&mdash;</entry>
- <entry align="center">Tables</entry>
+ <entry align="center">Tables and foreign tables</entry>
</row>
<row>
<entry align="center" morerows="1"><literal>AFTER</literal></entry>
@@ -142,7 +142,7 @@ CREATE [ OR REPLACE ] [ CONSTRAINT ] TRIGGER <replaceable class="parameter">name
<row>
<entry align="center"><command>TRUNCATE</command></entry>
<entry align="center">&mdash;</entry>
- <entry align="center">Tables</entry>
+ <entry align="center">Tables and foreign tables</entry>
</row>
<row>
<entry align="center" morerows="1"><literal>INSTEAD OF</literal></entry>
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 13cb516752b..b8db53b66de 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -295,13 +295,6 @@ CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString,
RelationGetRelationName(rel)),
errdetail("Foreign tables cannot have INSTEAD OF triggers.")));
- if (TRIGGER_FOR_TRUNCATE(stmt->events))
- ereport(ERROR,
- (errcode(ERRCODE_WRONG_OBJECT_TYPE),
- errmsg("\"%s\" is a foreign table",
- RelationGetRelationName(rel)),
- errdetail("Foreign tables cannot have TRUNCATE triggers.")));
-
/*
* We disallow constraint triggers to protect the assumption that
* triggers on FKs can't be deferred. See notes with AfterTriggers