postgres函数中的未强制引用?

时间:2017-09-23 13:08:03

标签: sql database postgresql

在postgres中,当一个表/视图以一种破坏现有引用的方式更新(例如重命名)时,该引用也会被更新,或者初始更新请求将失败,并出现如下错误:

  

错误:无法删除表用户,因为其他对象依赖于它

哪个好极了!

但是,这些引用似乎并未在函数(或触发器)和表/视图之间强制执行。

所以这个过程:

  

(创建TabA)=> (创建TabB w / Ref to TabA)=> (将TabA重命名为TabC)=没有问题

但是

  

(创建TabA)=> (创建FuncA w / Ref to TabA)=> (将TabA重命名为TabC)=执行“FuncA”

时出现错误的悄悄破坏引用

因为FuncA仍然指向TabA

Postgres不允许使用不存在的引用创建新函数,因此它显然能够验证函数中的引用。

所以,

  • 何时强制执行参考?
  • 什么时候没有强制执行参考?
  • 有没有办法提高执法水平?
  • 有没有办法扫描整个数据库中是否有可能引入的错误引用?

编辑添加最小示例

    -- Create users table
    CREATE TABLE users
    (
        id integer NOT NULL,
        name text COLLATE pg_catalog."default" NOT NULL
    )

    -- Create function that references "users"
    create function myfunc(int)
        returns text
        language SQL
    AS 
        $BODY$
            select name 
            from users 
            where id = $1 
            limit 1
        $BODY$

    -- Test the function
    select myfunc(1)
    -- (SUCCESS: returns NULL)

    -- Rename users table
    alter table users rename to old_users

    -- Test the function
    select myfunc(1)
    -- (ERROR: relation "users" does not exists SQL state 42P01)

1 个答案:

答案 0 :(得分:2)

这里的根本问题是,当最初为PostgreSQL加载函数时,目前还没有真正的方法来总是知道它的依赖关系是什么。虽然这可能不会很难添加到SQL语言函数,即使在PL / PGSQL函数中使用动态SQL,这实际上也是不可能的。更进一步到C,PL / Perl,PL / Python等功能,你没有任何保证的希望。

所以功能是一个特例。值得注意的是,它们几乎总是规划不透明,实际上它们对PostgreSQL整体来说通常是不透明的。因此,您需要仔细考虑何时何地使用它们,如何测试等等。

幸运的是,有pg_TAP和其他测试框架可以让你检查功能是否仍然有效。