Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to track changes in any function in PostgreSQL

I want track changes in any function in PostgreSQL.

Example - Suppose, i have function fun_name() in postgesql database and i am doing modifications in function.

Now, i want to track records like

DateTime,Schema_name,Function_name,old_func_text,new_func_text

Please suggest the best possible way to achieve this in postgresql.

I am studying event triggers in https://www.postgresql.org/docs/9.3/static/sql-createeventtrigger.html

Thanks.

like image 345
Tajinder Avatar asked Jan 05 '23 11:01

Tajinder


1 Answers

In Postgres 9.5 there is a function pg_event_trigger_ddl_commands() which can be used in an event trigger to get an oid of inserted/altered object.

Log table:

create table function_log (
    datetime timestamp, 
    schema_name text, 
    function_name text, 
    tag text, 
    function_body text);

Event function and trigger:

create or replace function public.on_function_event()
    returns event_trigger
    language plpgsql
as $function$
begin
    insert into function_log
    select now(), nspname, proname, command_tag, prosrc
    from pg_event_trigger_ddl_commands() e
    join pg_proc p on p.oid = e.objid
    join pg_namespace n on n.oid = pronamespace;
end
$function$;

create event trigger on_function_event
on ddl_command_end 
when tag in ('CREATE FUNCTION', 'ALTER FUNCTION')
execute procedure on_function_event();

Example:

create or replace function test()
returns int as $$ select 1; $$ language sql;

create or replace function test()
returns int as $$ select 2; $$ language sql;

alter function test() immutable;

select *
from function_log;

          datetime          | schema_name | function_name |       tag       | function_body 
----------------------------+-------------+---------------+-----------------+---------------
 2017-02-26 13:05:15.353879 | public      | test          | CREATE FUNCTION |  select 1; 
 2017-02-26 13:05:15.353879 | public      | test          | CREATE FUNCTION |  select 2; 
 2017-02-26 13:05:15.353879 | public      | test          | ALTER FUNCTION  |  select 2; 
(3 rows)

You can add DROP FUNCTION command tag to the trigger and then use the function pg_event_trigger_dropped_objects() in analogous way to pg_event_trigger_ddl_commands().

Unfortunately, there is no pg_event_trigger_ddl_commands() in Postgres 9.4. You could try to get an inserted/altered object using current_query() or write a trigger function in C. I think the easier way would be to upgrade Postgres to 9.5+.

like image 86
klin Avatar answered Jan 08 '23 11:01

klin