简体   繁体   English

PostgreSQL-使用连接提供的变量运行触发器

[英]Postgresql - Run trigger with variable supplied by connection

I need to create an audit table in postgresql, similar to what is described here . 我需要在postgresql中创建一个审核表,类似于此处所述。 However, the actual user making the change is not natively known to PostgreSQL - rather, my application maintains a connection pool (python using psycopg2), and individual users log into the application, not PostgreSQL. 但是,进行更改的实际用户不是PostgreSQL固有的-而是,我的应用程序维护一个连接池(使用psycopg2的python),并且单个用户登录到该应用程序,而不是PostgreSQL。 How can I let PostgreSQL know what user is making a change from my application? 如何让PostgreSQL知道哪个用户正在对我的应用程序进行更改? Or do I just need to put all the audit code app side? 还是只需要将所有审核代码应用程序放在一边?

I managed to solve this issue using temporary tables. 我设法使用临时表解决了这个问题。 What I ended up doing is the following. 我最终要做的是以下内容。 Note that this was written using python and psycopg2. 请注意,这是使用python和psycopg2编写的。

First, I set up my python code to use the with construct to obtain a database cursor from the psycopg2 connection pool. 首先,我设置python代码以使用with构造从psycopg2连接池中获取数据库游标。 This has the added benefit of automatically returning the connection to the pool, regardless of how the code block exits. 无论代码块如何退出,它还具有自动将连接返回到池的附加好处。 I then modified the class used in the with construct to create a temporary table containing whatever data I deem useful, specifically the username, before returning the cursor. 然后,我修改了with构造中使用的类with以创建一个临时表,其中包含我认为有用的任何数据,尤其是用户名,然后返回游标。 This table is created with the ON COMMIT DROP option so I know that when I return the connection to the pool the table will be dropped, preventing any conflict with future usage of the connection. 该表是使用ON COMMIT DROP选项创建的,因此我知道,当我将连接返回到池中时,该表将被删除,从而避免了与该连接的将来用法的任何冲突。

I then wrote my ON UPDATE trigger to pull the username from this temporary table. 然后,我编写了ON UPDATE触发器以从此临时表中提取用户名。 Since the trigger fires from within the same transaction as psycopg2 uses to run my SQL statements, it can see the temp table and SELECT the desired username from that. 由于触发器是从与psycopg2用于运行我的SQL语句的同一事务中触发的,因此它可以看到临时表并从中选择所需的用户名。 To handle the possibility that the temp table may not exist when the trigger is fired (such as if I make changes directly on the database), I wrapped the SELECT statement in the trigger in an exception handling block. 为了处理触发触发器时临时表可能不存在的可能性(例如,如果我直接在数据库上进行更改),我将SELECT语句包装在触发器中的异常处理块中。 If it gets an error trying to query the temporary table, it falls back to using the value of current_user instead. 如果在尝试查询临时表时遇到错误,则转而使用current_user的值。

Using this setup, I can pass not only the application user name, but any other client/app side information I want, such as client IP address, to the database, thereby enabling me to record values that otherwise wouldn't be accessible to PostgreSQL. 使用此设置,我不仅可以将应用程序用户名传递给数据库,还可以传递我想要的任何其他客户端/应用程序辅助信息(例如客户端IP地址)到数据库,从而使我能够记录PostgreSQL无法访问的值。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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