Auditoria com PostgreSQL
Dados Abertos, Modelagem, PostgreSQL
Ás vezes precisamos vigiar todas as alterações que acontecem em nossas tabelas para fim de auditoria. Abaixo segue uma função que pode ser colocada para fazer tal trabalho. Usaremos a extensão hstore para nos ajudar.
CREATE EXTENSION hstore;
--Tabela de Auditoria
CREATE TABLE auditoria(
id bigserial,
tabela text,
data date default current_date,
hora time WITHOUT TIME ZONE default CURRENT_TIME,
type char(1),
usuario text,
estacao text,
ip_estacao text,
ordem text,
campos hstore);
Criamos a extensão e a tabela que armazenará as alterações feitas nas tabelas.
--FUNCTION
CREATE OR REPLACE FUNCTION fn_auditoria()
RETURNS trigger
LANGUAGE plpgsql
AS $function$
DECLARE
v_new text[];
v_old text[];
v_fields hstore;
v_fields_old hstore;
pk_field record;
BEGIN
CASE TG_OP
WHEN 'INSERT' THEN
v_fields = hstore(NEW);
WHEN 'UPDATE' THEN
v_fields = hstore(array[]::text[]);
v_fields_old = hstore(array[]::text[]);
v_new = hstore_to_matrix(hstore(NEW));
v_old = hstore_to_matrix(hstore(OLD));
FOR i IN 1..array_upper(v_new, 1) LOOP
RAISE NOTICE 'Value of % is %', v_new[i][1], v_new[i][2];
IF (v_new[i][2] <> v_old[i][2]) THEN
v_fields = v_fields || hstore(v_new[i][1], v_new[i][2]);
v_fields_old = v_fields_old || hstore(v_old[i][1], v_old[i][2]);
ELSE
FOR pk_field IN (SELECT kcu.column_name
FROM INFORMATION_SCHEMA.TABLES t
LEFT JOIN INFORMATION_SCHEMA.TABLE_CONSTRAINTS tc
ON tc.table_catalog = t.table_catalog
AND tc.table_schema = t.table_schema
AND tc.table_name = t.table_name
AND tc.constraint_type = 'PRIMARY KEY'
LEFT JOIN INFORMATION_SCHEMA.KEY_COLUMN_USAGE kcu
ON kcu.table_catalog = tc.table_catalog
AND kcu.table_schema = tc.table_schema
AND kcu.table_name = tc.table_name
AND kcu.constraint_name = tc.constraint_name
WHERE t.table_schema = TG_TABLE_SCHEMA AND t.table_name = TG_TABLE_NAME
ORDER BY t.table_catalog,
t.table_schema,
t.table_name,
kcu.constraint_name,
kcu.ordinal_position) LOOP
IF (v_new[i][1] = pk_field.column_name) THEN
v_fields = v_fields || hstore(v_new[i][1], v_new[i][2]);
v_fields_old = v_fields_old || hstore(v_old[i][1], v_old[i][2]);
END IF;
END LOOP;
END IF;
END LOOP;
WHEN 'DELETE' THEN
v_fields_old = hstore(old);
END CASE;
IF (TG_OP = 'INSERT') OR (TG_OP = 'UPDATE') THEN
INSERT INTO auditoria(
tabela,
type,
usuario,
estacao,
ip_estacao,
ordem,
campos)
VALUES(
TG_TABLE_NAME,
substr(TG_OP, 1, 1),
current_setting('app.usuario'),
current_setting('app.estacao'),
current_setting('app.ip_estacao'),
'NOVO',
v_fields);
END IF;
IF (TG_OP = 'DELETE') OR (TG_OP = 'UPDATE') THEN
INSERT INTO auditoria(
tabela,
type,
usuario,
estacao,
ip_estacao,
ordem,
campos)
VALUES(
TG_TABLE_NAME,
substr(TG_OP, 1, 1),
current_setting('app.usuario'),
current_setting('app.estacao'),
current_setting('app.ip_estacao'),
'ANTIGO',
v_fields_old);
END IF;
RETURN NULL;
END;
$function$;
Com a função criada, basta criar a trigger nas tabelas que deseja monitorar as alterações.
CREATE TRIGGER tg_produtos
AFTER INSERT OR DELETE OR UPDATE ON nome_tabela
FOR EACH ROW EXECUTE PROCEDURE fn_auditoria();
Lembre-se que alguns valores devem ser definidos na aplicação, ou podem ser passados diretamente no Postgresql com o comando SET.
set app.usuario to 'NOME';
set app.estacao to 'PC';
set app.ip_estacao to '192.168.0.1';
Desta forma os registros criados, deletados ou alterados nas tabelas, serão inseridos como registro na tabela auditoria.
Related
Tags In
aquino.vale
Para saber sobre mim, acesse meu linkedin: https://www.linkedin.com/in/aquinovale
Categorias
- AI (1)
- Big Data (18)
- Cloud (3)
- Dados Abertos (2)
- Devops (7)
- Liderança (6)
- Linux (13)
- Modelagem (6)
- MongoDB (1)
- NoSQL (11)
- PostgreSQL (26)
- Sem categoria (1)