2023-04-26

PostgreSQL select data in JSON format

SELECT audit_log.id,
    audit_log.event_time,
    audit_log.client_addr,
    audit_log.application_name,
    audit_log.username,
    audit_log.table_name,
    audit_log.operation,
    audit_log.after_value -> 'exterior'::text AS after_value_in_json
   FROM audit.audit_log
  WHERE 1 = 1 
  AND (audit_log.after_value ->> 'exterior'::text) ~~ '%sCrIpT%'::text
  ORDER BY audit_log.event_time DESC;
/
  
SELECT 
id,
event_time,
client_addr,
application_name,
username,
table_name,
operation,
after_value -> 'exterior'as after_value_in_JSON
FROM audit.audit_log
where 1=1
and after_value ->> 'exterior' like '%sCrIpT%'
LIMIT 20;
/

PostgreSQL Audit with Trigger - "Value-based Auditing (VA)"

1/ Creating a table for Trigger Data:
-- SEQUENCE: audit.audit_log_id_seq
-- DROP SEQUENCE IF EXISTS audit.audit_log_id_seq;
CREATE SEQUENCE IF NOT EXISTS audit.audit_log_id_seq
    INCREMENT 1
    START 1
    MINVALUE 1
    MAXVALUE 9223372036854775807
    CACHE 1;
ALTER SEQUENCE audit.audit_log_id_seq OWNER TO postgres;
GRANT ALL ON SEQUENCE audit.audit_log_id_seq TO postgres;
/
-- Table: audit.audit_log
-- DROP TABLE IF EXISTS audit.audit_log;
CREATE TABLE IF NOT EXISTS audit.audit_log
(
    id bigint NOT NULL
DEFAULT nextval('audit.audit_log_id_seq'::regclass),
    event_time text COLLATE pg_catalog."default",
    client_addr inet,
    application_name text COLLATE pg_catalog."default",
    username text COLLATE pg_catalog."default",
    table_name text COLLATE pg_catalog."default",
    operation text COLLATE pg_catalog."default",
    before_value json,
    after_value json,
    CONSTRAINT audit_log_pkey PRIMARY KEY (id)
)
WITH (
    OIDS = FALSE
)
TABLESPACE pg_default;

ALTER TABLE IF EXISTS audit.audit_log OWNER to postgres;
GRANT ALL ON TABLE audit.audit_log TO postgres;


------------------------------ 2/ Creating a Audit Trigger:
-- FUNCTION: audit.audit_trigger()
-- DROP FUNCTION IF EXISTS audit.audit_trigger();
CREATE OR REPLACE FUNCTION audit.audit_trigger()
    RETURNS trigger
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE NOT LEAKPROOF
AS $BODY$
DECLARE
    old_row json := NULL;
    new_row json := NULL;
BEGIN
    IF TG_OP IN ('UPDATE','DELETE') THEN
        old_row = row_to_json(OLD);
    END IF;
    IF TG_OP IN ('INSERT','UPDATE') THEN
        new_row = row_to_json(NEW);
    END IF;
    INSERT INTO audit.audit_log(
        client_addr,
        application_name,
        username,
        event_time,
        table_name,
        operation,
        before_value,
        after_value
    ) VALUES (
        inet_client_addr(),
        current_setting('application_name'),
        session_user,
        current_timestamp,
        TG_TABLE_SCHEMA ||  '.' || TG_TABLE_NAME,
        TG_OP,
        old_row,
        new_row
    );
    RETURN NEW;
END;
$BODY$;
ALTER FUNCTION audit.audit_trigger() OWNER TO postgres;
GRANT EXECUTE ON FUNCTION audit.audit_trigger() TO postgres;

------------------ 3/ Insert Trigger to Table "public.salons":
-- Trigger: audit_log__public_salons
-- DROP TRIGGER IF EXISTS audit_log__public_salons ON public.salons;
CREATE TRIGGER audit_log__public_salons
    AFTER INSERT OR DELETE OR UPDATE
    ON public.salons
    FOR EACH ROW
    EXECUTE PROCEDURE audit.audit_trigger();
------------------
4/ Result: SELECT * FROM audit.audit_log ORDER BY id ASC LIMIT 100