Re: Advice for generalizing trigger functions - Mailing list pgsql-sql

From Marcin Stępnicki
Subject Re: Advice for generalizing trigger functions
Date
Msg-id 1198894176.31628.9.camel@localhost
Whole thread Raw
In response to Advice for generalizing trigger functions  (Richard Broersma Jr <rabroersma@yahoo.com>)
List pgsql-sql
Dnia 25-12-2007, Wt o godzinie 16:20 -0800, Richard Broersma Jr pisze:
> I've created quite a few functions that log modifications to various history tables. 
> (the history table has the same name as the base table but is prefixed by the 'History.' schema.)
>  The only difference between functions I can find is the table name.
> 
> Is there any way to generalize these myriad of functions into one?
> 

Maybe just try http://pgfoundry.org/projects/audittrail2/ ?

Or there's something my friend wrote some time ago (I use audittrail
now, but I think that this function works with reasonably recent
PostgreSQL releases). Sorry for Polish comments, I've just taken it out
from old repository.


CREATE OR REPLACE FUNCTION create_history_table(text, text) RETURNS text AS
$BODY$
DECLARE   tabela ALIAS FOR $1;   query TEXT;   fields RECORD;   grupa ALIAS FOR $2;
BEGIN   query := '';

-- poczatek definicji zapytania tworzacego historie   query := 'CREATE TABLE "H' || tabela || '"(\r\n';

-- petelka wyciagajaca pola tabeli do ktorej tworzona jest historia   FOR fields IN        SELECT a.attname AS name,
         format_type(a.atttypid, a.atttypmod) AS type         FROM pg_attribute a         WHERE a.attrelid = ( SELECT
oidFROM pg_class WHERE relname = tabela )           AND a.attnum > 0       LOOP              query := query ||
fields.name|| ' ' || fields.type || ',\r\n';
 
   END LOOP; 

-- doklejenie pol dotyczacych historii   query := query || 'log_usename text default current_user, '
||'log_time timestamp default now(), '                  || 'log_event text default '''' '                  ||
');\r\n';

-- ustawienie uprawnien do zapisu i odczytu z tabeli historii   query := query || 'GRANT SELECT, INSERT ON "H' ||
tabela|| '" TO GROUP "' || grupa || '";\r\n';
 

--    EXECUTE query;
--    query := '';
-- definicja funkcji dla triggera historii   query := query || 'CREATE FUNCTION "H' || tabela || '"() RETURNS trigger
AS\r\n'                 || '$$\r\n'                  || 'begin\r\n'                  || 'if ( tg_op = ''INSERT'' )
then\r\n'                 || '    INSERT INTO "H' || tabela || '" (\r\n';
 
   FOR fields IN        SELECT a.attname AS name
--               format_type(a.atttypid, a.atttypmod) AS type         FROM pg_attribute a         WHERE a.attrelid = (
SELECToid FROM pg_class WHERE relname = tabela )           AND a.attnum > 0       LOOP              query := query || '
  ' || fields.name || ', \r\n';
 
   END LOOP; 
   query := query || '    log_event ) VALUES (\r\n';
   FOR fields IN        SELECT a.attname AS name
--               format_type(a.atttypid, a.atttypmod) AS type         FROM pg_attribute a         WHERE a.attrelid = (
SELECToid FROM pg_class WHERE relname = tabela )           AND a.attnum > 0       LOOP              query := query || '
  NEW.' || fields.name || ', \r\n';
 
   END LOOP; 
   query := query || '    ''I'');\r\n';
   query := query || 'end if;\r\n'                  || 'if tg_op = ''UPDATE'' then\r\n'                  || '    if
OLD.id!= NEW.id then\r\n'                  || '        UPDATE "H' || tabela || '" SET id = NEW.id WHERE id =
OLD.id;\r\n'                 || '    end if;\r\n'                  || '    INSERT INTO "H' || tabela || '"(\r\n';
 
   FOR fields IN        SELECT a.attname AS name
--               format_type(a.atttypid, a.atttypmod) AS type         FROM pg_attribute a         WHERE a.attrelid = (
SELECToid FROM pg_class WHERE relname = tabela )           AND a.attnum > 0       LOOP              query := query || '
  ' || fields.name || ', \r\n';
 
   END LOOP; 
   query := query || '    log_event ) VALUES (\r\n';
   FOR fields IN        SELECT a.attname AS name
--               format_type(a.atttypid, a.atttypmod) AS type         FROM pg_attribute a         WHERE a.attrelid = (
SELECToid FROM pg_class WHERE relname = tabela )           AND a.attnum > 0       LOOP              query := query || '
  NEW.' || fields.name || ', \r\n';
 
   END LOOP; 
   query := query || '    ''U'');\r\n';
   query := query || 'end if;\r\n'                  || 'if tg_op = ''DELETE'' then\r\n'                  || '    INSERT
INTO"H' || tabela || '"(';
 
   FOR fields IN        SELECT a.attname AS name
--               format_type(a.atttypid, a.atttypmod) AS type         FROM pg_attribute a         WHERE a.attrelid = (
SELECToid FROM pg_class WHERE relname = tabela )           AND a.attnum > 0       LOOP              query := query || '
  ' || fields.name || ', \r\n';
 
   END LOOP; 
   query := query || '    log_event ) VALUES (\r\n';
   FOR fields IN        SELECT a.attname AS name
--               format_type(a.atttypid, a.atttypmod) AS type         FROM pg_attribute a         WHERE a.attrelid = (
SELECToid FROM pg_class WHERE relname = tabela )           AND a.attnum > 0       LOOP              query := query || '
  OLD.' || fields.name || ', \r\n';
 
   END LOOP; 
   query := query || '    ''D'');\r\n';
   query := query || 'end if;\r\n'                  || 'return NEW;\r\n'                  || 'end;\r\n'
|| '$$ LANGUAGE ''PLPGSQL'';';
 
   query := query || 'CREATE TRIGGER "H' || tabela || '" AFTER INSERT OR UPDATE OR DELETE ON "' || tabela || '" FOR
EACHROW EXECUTE PROCEDURE "H' || tabela || '"()';
 
   EXECUTE query;   RETURN query;
END;$BODY$ LANGUAGE 'plpgsql';




pgsql-sql by date:

Previous
From: Erik Jones
Date:
Subject: Re: Advice for generalizing trigger functions
Next
From: "Daniel Myers"
Date:
Subject: PL/pgsql: function passing argument to IN operator