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
This commit is contained in:
parent
14168d3c62
commit
3b00a944a9
@ -6732,9 +6732,9 @@ BEGIN
|
|||||||
TG_ARGV[0], TG_OP, TG_WHEN, TG_LEVEL;
|
TG_ARGV[0], TG_OP, TG_WHEN, TG_LEVEL;
|
||||||
RETURN NULL;
|
RETURN NULL;
|
||||||
END;$$;
|
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();
|
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();
|
FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
|
||||||
CREATE OR REPLACE FUNCTION trigger_data() RETURNS trigger
|
CREATE OR REPLACE FUNCTION trigger_data() RETURNS trigger
|
||||||
LANGUAGE plpgsql AS $$
|
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: trig_row_after(23, skidoo) AFTER ROW UPDATE ON rem1
|
||||||
NOTICE: OLD: (1,update),NEW: (1,updateupdate)
|
NOTICE: OLD: (1,update),NEW: (1,updateupdate)
|
||||||
NOTICE: trigger_func(<NULL>) called: action = UPDATE, when = AFTER, level = STATEMENT
|
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
|
-- cleanup
|
||||||
DROP TRIGGER trig_row_before ON rem1;
|
DROP TRIGGER trig_row_before ON rem1;
|
||||||
DROP TRIGGER trig_row_after 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 !")
|
NOTICE: NEW: (13,"test triggered !")
|
||||||
ctid
|
ctid
|
||||||
--------
|
--------
|
||||||
(0,32)
|
(0,25)
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
-- cleanup
|
-- cleanup
|
||||||
|
@ -1595,9 +1595,9 @@ BEGIN
|
|||||||
RETURN NULL;
|
RETURN NULL;
|
||||||
END;$$;
|
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();
|
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();
|
FOR EACH STATEMENT EXECUTE PROCEDURE trigger_func();
|
||||||
|
|
||||||
CREATE OR REPLACE FUNCTION trigger_data() RETURNS trigger
|
CREATE OR REPLACE FUNCTION trigger_data() RETURNS trigger
|
||||||
@ -1652,6 +1652,7 @@ delete from rem1;
|
|||||||
insert into rem1 values(1,'insert');
|
insert into rem1 values(1,'insert');
|
||||||
update rem1 set f2 = 'update' where f1 = 1;
|
update rem1 set f2 = 'update' where f1 = 1;
|
||||||
update rem1 set f2 = f2 || f2;
|
update rem1 set f2 = f2 || f2;
|
||||||
|
truncate rem1;
|
||||||
|
|
||||||
|
|
||||||
-- cleanup
|
-- cleanup
|
||||||
|
@ -131,7 +131,7 @@ CREATE [ OR REPLACE ] [ CONSTRAINT ] TRIGGER <replaceable class="parameter">name
|
|||||||
<row>
|
<row>
|
||||||
<entry align="center"><command>TRUNCATE</command></entry>
|
<entry align="center"><command>TRUNCATE</command></entry>
|
||||||
<entry align="center">—</entry>
|
<entry align="center">—</entry>
|
||||||
<entry align="center">Tables</entry>
|
<entry align="center">Tables and foreign tables</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry align="center" morerows="1"><literal>AFTER</literal></entry>
|
<entry align="center" morerows="1"><literal>AFTER</literal></entry>
|
||||||
@ -142,7 +142,7 @@ CREATE [ OR REPLACE ] [ CONSTRAINT ] TRIGGER <replaceable class="parameter">name
|
|||||||
<row>
|
<row>
|
||||||
<entry align="center"><command>TRUNCATE</command></entry>
|
<entry align="center"><command>TRUNCATE</command></entry>
|
||||||
<entry align="center">—</entry>
|
<entry align="center">—</entry>
|
||||||
<entry align="center">Tables</entry>
|
<entry align="center">Tables and foreign tables</entry>
|
||||||
</row>
|
</row>
|
||||||
<row>
|
<row>
|
||||||
<entry align="center" morerows="1"><literal>INSTEAD OF</literal></entry>
|
<entry align="center" morerows="1"><literal>INSTEAD OF</literal></entry>
|
||||||
|
@ -295,13 +295,6 @@ CreateTriggerFiringOn(CreateTrigStmt *stmt, const char *queryString,
|
|||||||
RelationGetRelationName(rel)),
|
RelationGetRelationName(rel)),
|
||||||
errdetail("Foreign tables cannot have INSTEAD OF triggers.")));
|
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
|
* We disallow constraint triggers to protect the assumption that
|
||||||
* triggers on FKs can't be deferred. See notes with AfterTriggers
|
* triggers on FKs can't be deferred. See notes with AfterTriggers
|
||||||
|
Loading…
x
Reference in New Issue
Block a user