Like detailed in my first question I have a Postgres 9.1 database with multiple tables that have the exact same column names, they only vary in their column values:
tbl_log_a
tbl_log_b
tbl_log_c
...
26 tables (from a to z). Each table has a trigger that calls a trigger function named trfn_tbl_log_%letter%
(from a
to z
) which does the exact same thing:
CREATE OR REPLACE FUNCTION trfn_tbl_log_a_timetypespan()
RETURNS trigger AS
$BODY$
DECLARE
v_timetype character varying;
v_timestmp_timetype timestamp without time zone;
v_timetypespan_resume interval;
v_stmtserial real;
v_sumtimetypespan_fnname interval;
BEGIN
IF NEW.timetype = 'lap' THEN
SELECT timetype, timestmp, timetypespan FROM tbl_log_a WHERE fnname = NEW.fnname AND (timetype = 'start' OR timetype = 'resume') ORDER BY stmtserial DESC LIMIT 1 INTO v_timetype, v_timestmp_timetype, v_timetypespan_resume;
IF v_timetype = 'start' THEN
NEW.timetypespan := age(NEW.timestmp, v_timestmp_timetype);
ELSIF v_timetype = 'resume' THEN
SELECT timestmp FROM tbl_log_a WHERE fnname = NEW.fnname AND timetype = 'start' ORDER BY stmtserial DESC LIMIT 1 INTO v_timestmp_timetype;
NEW.timetypespan := age(NEW.timestmp, v_timestmp_timetype) - v_timetypespan_resume;
ELSE
RAISE EXCEPTION USING MESSAGE = 'There is not any previous row...';
END IF;
ELSIF NEW.timetype = 'resume' THEN
SELECT timestmp FROM tbl_log_a WHERE fnname = NEW.fnname AND (timetype = 'start' OR timetype = 'lap') ORDER BY stmtserial DESC LIMIT 1 INTO v_timestmp_timetype;
IF FOUND THEN
NEW.timetypespan := age(NEW.timestmp, v_timestmp_timetype);
ELSE
RAISE EXCEPTION USING MESSAGE = 'There is not any previous row...';
END IF;
ELSIF NEW.timetype = 'total' THEN
SELECT stmtserial FROM tbl_log_a WHERE fnname = NEW.fnname AND timetype = 'total' ORDER BY stmtserial DESC LIMIT 1 INTO v_stmtserial;
SELECT SUM(timetypespan) FROM (SELECT DISTINCT ON (floor(timeidx)::int) floor(timeidx)::int timeidx, timetypespan
FROM tbl_log_a WHERE fnname = NEW.fnname AND timetype = 'lap' AND stmtserial > coalesce(v_stmtserial, 0) ORDER BY 1, 2 DESC) a INTO v_sumtimetypespan_fnname;
IF v_sumtimetypespan_fnname NOTNULL THEN
NEW.timetypespan := v_sumtimetypespan_fnname;
ELSE
RAISE EXCEPTION USING MESSAGE = 'There is not any previous row...';
END IF;
END IF;
return NEW;
END
$BODY$
LANGUAGE plpgsql VOLATILE;
Trigger definition:
CREATE TRIGGER trfn_tbl_log_a_timetypespan
BEFORE INSERT ON tbl_log_a
FOR EACH ROW EXECUTE PROCEDURE trfn_tbl_log_a_timetypespan();
So I have to create 26 trigger functions, one for each tbl_log_%letter%
. I am trying to replace all of them with a single, generic trigger function.
We worked out a solution with dynamic SQL under my previous question with a simplified function. Can the same technique be extended to this more complex scenario?
EXECUTE format($$...