在 pg_temp 架构中调用函数而不带前缀

calling functions in pg_temp schema without prefix

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

但是他指出,为了在 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 架构中调用函数而不给它们添加前缀?

这将非常方便开发新功能。

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

查看 PostgreSQL 提交 aa27977fe21a7dfa4da4376ad66ae37cb8f0d0b5

Support explicit placement of the temporary-table schema within search_path. This is needed to allow a security-definer function to set a truly secure value of search_path. Without it, a malicious user can use temporary objects to execute code with the privileges of the security-definer function. Even pushing the temp schema to the back of the search path is not quite good enough, because a function or operator at the back of the path might still capture control from one nearer the front due to having a more exact datatype match. Hence, disable searching the temp schema altogether for functions and operators.

Security: 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++;
            }