This is a trigger that is called by either an insert, update or a delete on a table. It is guaranteed the calling table has all the columns impacted and a deletes table also exists.
CREATE OR REPLACE FUNCTION sample_trigger_func() RETURNS TRIGGER AS $$
DECLARE
    operation_code char;
    table_name varchar(50);
    delete_table_name varchar(50);
    old_id integer; 
BEGIN
table_name = TG_TABLE_NAME;
delete_table_name = TG_TABLE_NAME || '_deletes';
SELECT SUBSTR(TG_OP, 1, 1)::CHAR INTO operation_code;
IF TG_OP = 'DELETE' THEN
    OLD.mod_op = operation_code;
    OLD.mod_date = now();
    RAISE INFO 'OLD: %', (OLD).name;
    EXECUTE format('INSERT INTO %s VALUES %s', delete_table_name, (OLD).*);
ELSE
    EXECUTE format('UPDATE TABLE %s SET mod_op = %s AND mod_date = %s'
                  , TG_TABLE_NAME, operation_code, now());
END IF;
RETURN NEW;
END;
$$ LANGUAGE plpgsql;
The ELSE branch triggers an endless loop. There may be more problems.
How to fix it?
 
     
    