在没有前缀的 pg_temp 模式中调用函数

Posted

技术标签:

【中文标题】在没有前缀的 pg_temp 模式中调用函数【英文标题】:calling functions in pg_temp schema without prefix 【发布时间】:2016-07-12 13:12:21 【问题描述】:

在 postgres 中,pg_temp 模式默认位于搜索路径上。 正如 Tom Lane 所解释的那样,pg_temp 架构中的 here 函数默认情况下是不可调用的,因为安全原因没有前缀。

但是他指出,为了在不带前缀的情况下调用 pg_temp 架构中的函数,您必须将临时架构显式添加到搜索路径中。不幸的是,从 postgresql 9.4 开始,这似乎不再起作用了。

set search_path to pg_temp,public;
-- create function in the temp schema
create function test_fun() returns int as $$ select 1; $$ language sql;
-- results in "function test_fun() does not exist"
select test_fun();
-- works perfectly
select pg_temp.test_fun();

有没有什么方法可以调用 pg_temp 模式中的函数而不加前缀?

这对于开发新功能非常方便。

【问题讨论】:

只是一个提示,我正在使用我自己的架构temp,它不时被清空。 我也想过这个。这就引出了另一个问题。 pg_temp 模式的性能是否优于常规模式? 即便如此,差异也不是很重要,尤其是在测试期间。 【参考方案1】:

看起来 Tome Lane 不是 100% 精确的——我检查了从 9.2 到 9.5,在每一个中你都需要用pg_temp 来限定函数。设置search_path 是不够的。

查看 PostgreSQL 提交 aa27977fe21a7dfa4da4376ad66ae37cb8f0d0b5:

支持在 search_path 中显式放置临时表架构。 这是允许安全定义器功能设置真正安全的 search_path 的值。没有它,恶意用户可以使用临时对象 使用 security-definer 函数的权限执行代码。甚至 将临时模式推到搜索路径的后面不是很好 足够了,因为路径后面的函数或运算符可能仍然 由于具有更精确的数据类型,因此从更靠近前面的位置捕获控制 匹配。因此,完全禁用在临时模式中搜索函数和 运营商。

安全性:CVE-2007-2138

特别看FuncnameGetCandidates的变化:

@@ -549,12 +586,16 @@ FuncnameGetCandidates(List *names, int nargs)
        
        else
        
-           /* Consider only procs that are in the search path */
+           /*
+            * Consider only procs that are in the search path and are not
+            * in the temp namespace.
+            */
            ListCell   *nsp;

            foreach(nsp, activeSearchPath)
            
-               if (procform->pronamespace == lfirst_oid(nsp))
+               if (procform->pronamespace == lfirst_oid(nsp) &&
+                   procform->pronamespace != myTempNamespace)
                    break;
                pathpos++;
            

【讨论】:

请问你是怎么查的?您是否尝试过,甚至检查过代码?我只是想知道是否有一些选项可以更改默认行为。 我已经修改了答案以包含指向源的指针。 顺便说一句,我提交了一个补丁来修复我在查看时注意到的文档错误:postgresql.org/message-id/… 多么棒的详细答案啊!感谢您的努力!

以上是关于在没有前缀的 pg_temp 模式中调用函数的主要内容,如果未能解决你的问题,请参考以下文章

js中的4种函数调用模式

Swift中的函数调用

调用在另一个命名空间中定义的 PHP 函数,不带前缀

一个关于调用函数函参写void的错误error C2143 syntax error missing ')' before 'type'

如何在没有前缀的单独文件中使用python函数

2.工厂模式==》对象