Question

I have a web application which currently only supports PostgreSQL as a backend and has it's own user management. Connection to the database is done using a generic user account using Postgres auth mechanisms. This application should now get a audit log for some created and changed data hopefully based on triggers and stored procedures only and for performance reasons it would be nice if everything works async and independent from the web application.

There is one main problem: We want to know which user of the web application made some changes or created data, but this piece of information is normally not available in stored procedures out of the box because we connect to Postgres using a generic account. What I would like to avoid doing is calling the stored procedures in the web application and provide user ids that way, as this would mean to add the relevant calls in may places in the web application. Besides that we make updates to the data model directly using the database without the web application, meaning we would need the triggers in any case.

Currently the web application is working with a transaction started on every request and committed on its end. Therefore I though of creating a temporary table within the transaction in every request which always gets the current user id of the request which should be available for the stored procedures executed by the triggers on created or changed data.

Some things I don't know are if the stored procedures executed can even access the current transaction of the database and therefore are able to retrieve the current user id from the temporary table? The table is not part of the changed data the trigger was created for. How would performance be affected if each request creates a temporary table to store just one Integer in the worst case? If the trigger is able to access the temporary table, the request may finish at any time because it's work is done or of errors. How would that affect a trigger which would have access to the temporary table which only exits within the transaction which gets committed or reverted as the stored procedures want to read the user id?

Is there any other way with which I can map a user id to some unique identifier of a transaction which the trigger has access to? Besides a temporary table, I could create a normal table in which I map user ids to transaction ids on start of every request but independent of the current transaction. If the trigger would now get the transaction id which was responsible for executing the trigger the stored procedures could use the transaction id to look up the user id which used the transaction.

Any thoughts? Thanks!

I've added a question about trigger lifetime and execution context which fits to this question:

execution context of database trigger in PostgreSQL

Was it helpful?

Solution

A temporary table seems overkill when you could just use a session setting.

Up to version 9.1, custom session variables needed to be declared in postgresql.conf through the custom_variable_classes parameter, which made it a bit cumbersome, deployment-wise.

Since 9.2, it's no longer necessary. So you could just issue at connect time:

SET myapp.myusername='foobar';

and then in a trigger or in fact anywhere within the session, SELECT current_setting('myapp.myusername'), or SHOW myapp.myusername would get back the value.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top