简体   繁体   中英

How can I set a username for a Postgresql audit trigger?

I am using a trigger in PostgreSQL 8.2 to audit changes to a table:

CREATE OR REPLACE FUNCTION update_issue_history() RETURNS trigger as $trig$
BEGIN
        INSERT INTO issue_history (username, issueid)
               VALUES ('fixed-username', OLD.issueid);
        RETURN NULL;
END;
$trig$ LANGUAGE plpgsql;

CREATE TRIGGER update_issue_history_trigger
AFTER UPDATE ON issue
      FOR EACH ROW EXECUTE PROCEDURE update_issue_history();

What I want to do is have some way to provide the value of fixed-username at the time that I execute the update. Is this possible? If so, how do I accomplish it?

Try something like this:

CREATE OR REPLACE FUNCTION update_issue_history() 
RETURNS trigger as $trig$
DECLARE
      arg_username varchar;
BEGIN
      arg_username := TG_ARGV[0];
      INSERT INTO issue_history (username, issueid)
             VALUES (arg_username, OLD.issueid);
      RETURN NULL;
END;
$trig$ LANGUAGE plpgsql;

CREATE TRIGGER update_issue_history_trigger
AFTER UPDATE ON issue
      FOR EACH ROW EXECUTE PROCEDURE update_issue_history('my username value');

I don't see a way to do this other than to create temp tables and use EXECUTE in your trigger. This will have performance consequences though. A better option might be to tie into another table somewhere and log in who logs in/out by session id and back-end PID, and reference that?

Note you don't have any other way of getting the information into the update statement. Keep in mind that the trigger can only see what is available in the API or in the database. If you want a trigger to work transparently, you can't expect to pass information to it at runtime that it would not have access to otherwise.

The basic question you have to ask is "How does the db know what to put there?" Once you decide on a method there the answer should be straight-forward but there are no free lunches.

Update

In the past when I have had to do something like this when the login to the db is with an application role, the way I have done it is to create a temporary table and then access that table from the stored procedures. Currently stored procedures can handle temporary tables in this way but in the past we had to use EXECUTE.

There are two huge limitations with this approach. The first is that it creates a lot of tables and this leads eventually to the possibility of oid wraparound.

These days I much prefer to have the logins to the db being user logins. This makes this far easier to manage and you can just access via the value SESSION_USER (a newbie mistake is to use CURRENT_USER which shows you the current security context rather than the login of the user.

Neither of these approaches work well with connection pooling. In the first case you can't do connection pooling because your temporary tables will get misinterpreted or clobbered. In the second, you can't do it because the login roles are different.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM