【问题标题】:Use a postgres extension as a non-privileged user以非特权用户身份使用 postgres 扩展
【发布时间】:2021-04-14 14:58:30
【问题描述】:

问题

我有以下使用moddatetime 扩展的触发函数:

/* BEFORE UPDATE trigger - Updates "entity_version.updated_on", setting it to the current UTC time. */
CREATE EXTENSION IF NOT EXISTS moddatetime;  -- Needs superuser privileges!

DROP TRIGGER IF EXISTS trig_entity_version_before_update
ON entity_version;

CREATE TRIGGER trig_entity_version_before_update
    BEFORE UPDATE
    ON entity_version
    FOR EACH ROW EXECUTE PROCEDURE moddatetime(updated_on);  -- updated_on is TIMESTAMP type

触发器工作得很好,但问题是第一行 (CREATE EXTENSION) 需要超级用户权限。由于这些数据库将由用户(通过脚本)创建,我不希望他们成为创建这些数据库和触发器的用户拥有超级用户访问权限。

我尝试过的

作为第一步,以超级用户身份运行脚本可以正常工作,正如您所期望的那样。

当然,下一步是将作为超级用户创建扩展程序与触发器创建脚本分开。但是这样做,如果我在没有CREATE EXTENSION 行的情况下运行上述脚本,我会收到以下错误:

function moddatetime() does not exist

鉴于脚本从不声明moddatetime,我认为这是有道理的,但我无法在文档中的任何地方找到如何在不使用CREATE EXTENSION 的情况下将扩展定义为可用。当然必须有一种方法来导入或使用扩展而无需创建它?类似于:

USING EXTENSION moddatetime;  -- Does something like this exist?

... rest of the trigger script ...

【问题讨论】:

    标签: postgresql postgresql-11


    【解决方案1】:

    如果你想使用它,你需要安装扩展。

    PostgreSQL v13 引入了受信任扩展的概念,它可以由数据库上具有CREATE 权限的非超级用户安装,但此扩展不在其中。所以升级不会解决问题。

    您可以以超级用户身份连接到template1 并在那里创建扩展。然后它会自动出现在所有新创建的数据库中。

    但坦率地说,我不明白这一点。您可以使用常规的 PL/pgSQL 触发器做同样的事情——只是性能不会那么好。

    【讨论】:

    • 我想写一个小触发函数没什么大不了的,我只是觉得很烦我不能将扩展用于我认为很正常的用例。我将使用自定义触发器解决方案并将其作为辅助答案发布。
    • 您可以使用 pgsql-hackers 邮件列表来处理它 - 乍一看,我认为没有理由不相信扩展程序。
    【解决方案2】:

    根据@laurenz-albe 他的建议,我刚刚停止使用此特定用例的扩展程序。幸运的是,编写一个函数来完成扩展所做的事情相对来说是微不足道的。我会将它包含在此处以供参考,以防有人专门替换 moddatetime

    DROP FUNCTION IF EXISTS fn_entity_version_before_update() CASCADE;
    
    CREATE FUNCTION fn_entity_version_before_update() RETURNS TRIGGER LANGUAGE PLPGSQL AS
    $fn_body$
    BEGIN
        NEW.updated_on = NOW() AT TIME ZONE 'utc';
        RETURN NEW;
    END;
    $fn_body$;
    
    DROP TRIGGER IF EXISTS trig_entity_version_before_update
    ON entity_version;
    
    CREATE TRIGGER trig_entity_version_before_update
        BEFORE UPDATE
        ON entity_version
        FOR EACH ROW EXECUTE PROCEDURE fn_entity_version_before_update();
    

    【讨论】:

      猜你喜欢
      • 2015-08-28
      • 1970-01-01
      • 2013-06-28
      • 1970-01-01
      • 1970-01-01
      • 2016-10-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多