I want to keep all changes of my tables. I have a working solution for making a trigger per table, but it seems silly to copy the code foreach table. Is there any way to create a single trigger function that does this?
Example of my working per-table trigger (including table definitions):
CREATE TABLE departments (
id bigserial Primary Key,
name varchar not null,
created bigint not null default date_part('epoch', NOW()),
created_by bigint references Employees (id) not null
);
create table Departments_hist ("action" varchar not null, change_date bigint not null, rev bigserial not null, like Departments);
CREATE OR REPLACE FUNCTION add_to_history_Departments() RETURNS TRIGGER AS $$
BEGIN
IF(TG_OP='INSERT' OR TG_OP='UPDATE') THEN
INSERT INTO Departments_hist values (TG_OP,date_part('epoch', NOW()),DEFAULT,NEW.*);
END IF;
IF (TG_OP='DELETE') THEN
INSERT INTO Departments_hist values (TG_OP,date_part('epoch', NOW()),DEFAULT,OLD.*);
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
CREATE TRIGGER trigger_history_Departments AFTER INSERT OR UPDATE OR DELETE ON Departments FOR EACH ROW EXECUTE PROCEDURE add_to_history_Departments();
I've tried to make it multi-table by concatenating '_hist' to TG_TABLE_NAME:
CREATE OR REPLACE FUNCTION add_to_hist_table() RETURNS TRIGGER AS $$
DECLARE
histTable text :=TG_TABLE_NAME || '_hist';
BEGIN
IF (TG_OP='INSERT' OR TG_OP='UPDATE') THEN
INSERT INTO histTable values (TG_OP,date_part('epoch', NOW()),DEFAULT,NEW.*);
ELSIF TG_OP='DELETE' THEN
INSERT INTO histTable values (TG_OP,date_part('epoch', NOW()),DEFAULT,OLD.*);
END IF;
RETURN null; --ignored since it is an AFTER triggger.
END;
$$ LANGUAGE plpgsql;
But I get an error:
ERROR: syntax error at or near "$1"
LINE 1: INSERT INTO $1 values ( $2 ,date_part('epoch', NOW()),DEFA...
^
QUERY: INSERT INTO $1 values ( $2 ,date_part('epoch', NOW()),DEFAULT, $3 .*)
CONTEXT: SQL statement in PL/PgSQL function "add_to_hist_table" near line 5
I guess it is a problem with variable substitution ( http://www.postgresql.org/docs/8.4/static/plpgsql-implementation.html ).
How can this functionality be achieved?
PS. I'm using postgresql 8.4 but will likely upgrade to 9.3 soon.