在 Postgres 触发器中访问事务上下文

Accessing transaction context in a Postgres trigger

我有一个 Postgres 11.3 数据库,上面有很多触发器。这些触发器是通过 SQLAlchemy 通过一些元编程自动生成的,并且基本上将每个 CREATE/UPDATE/DELETE 操作包装在每条记录上,存储它的 "version"。这个过程是完全自动的,不需要最终用户的任何努力。

我希望能够将 user_id 外键添加到我的 versions table。这是应用程序用户中的 user_id 不是 正在执行事务的已连接 postgres/system。该字段将需要由应用程序调用方法提供。

我最初的尝试涉及为每个 table 自动生成一组存储的 procedures/postgres 函数。这可行,但我想不出从当前事务访问 context 的方法。下面是一些伪代码来演示:

CREATE OR REPLACE FUNCTION delete_address(resource_id INTEGER, user_id INTEGER)
    RETURNS INTEGER as
    $BODY$
        DECLARE
            context USER_ID INTEGER; // something like this magical context keyword
        BEGIN
            USER_ID = user_id;

            DELETE FROM address WHERE id = resource_id;

            RETURN 1;
        END;
    $BODY$
    LANGUAGE plpgsql;

在这个 table 的 DELETE 触发器中:

CREATE OR REPLACE FUNCTION update_address_history_on_delete()
    RETURNS trigger AS
    $BODY$
    BEGIN
        UPDATE "versions"
        SET 
          date_archived = now()::timestamp,
          user_id = context USER_ID  // theres that magical context keyword again
        WHERE
            resource_id = OLD.id;
        RETURN OLD;
    END
    $BODY$
    LANGUAGE plpgsql

您会看到,在这个假设中,我正在尝试访问本质上是词法 scoped/closure 值的值,位于单个事务的上下文中。

这可能吗,或者有其他方法可以解决这样的问题吗?

干杯!

您可以使用本地交易 custom configuration variable

在您的 delete_address() 函数中分配变量:

PERFORM set_config('my_vars.user_id', user_id, true);

...并使用以下方法检索触发器中的值:

current_setting('my_vars.user_id')