我在具有相同函数名称的单个数据库中有两个类似的模式。 每个模式都由与模式名称相匹配的角色拥有。使用嵌套函数的PL/pgSQL函数名称解析
我有关于嵌套函数的函数名称解析的问题。 我在期待外层函数会调用同一模式中的内层函数,但它不会! 这个名字是在运行时基于search_path动态解析的,这使得一些敏感,但不是如我所愿。
这是一个测试用例。比方说,例如模式和角色被命名为test和prod,如下所示。
测试模式:CREATE ROLE test NOLOGIN;
CREATE SCHEMA test AUTHORIZATION test;
CREATE OR REPLACE FUNCTION test.inner_func() RETURNS TEXT
AS $BODY$
BEGIN
RETURN 'test function';
END
$BODY$ LANGUAGE 'plpgsql';
ALTER FUNCTION test.inner_func() OWNER TO test;
CREATE OR REPLACE FUNCTION test.outer_func() RETURNS SETOF TEXT
AS $BODY$
BEGIN
RETURN QUERY SELECT inner_func();
END
$BODY$ LANGUAGE 'plpgsql';
ALTER FUNCTION test.outer_func() OWNER TO test;
PROD模式:
CREATE ROLE prod NOLOGIN;
CREATE SCHEMA prod AUTHORIZATION prod;
CREATE OR REPLACE FUNCTION prod.inner_func() RETURNS TEXT
AS $BODY$
BEGIN
RETURN 'prod function';
END
$BODY$ LANGUAGE 'plpgsql';
ALTER FUNCTION prod.inner_func() OWNER TO prod;
CREATE OR REPLACE FUNCTION prod.outer_func() RETURNS SETOF TEXT
AS $BODY$
BEGIN
RETURN QUERY SELECT inner_func();
END
$BODY$ LANGUAGE 'plpgsql';
ALTER FUNCTION prod.outer_func() OWNER TO prod;
测试用例:
SET search_path=test,public;
SELECT outer_func();
> test function
SELECT prod.outer_func();
> test function <<<---- was expecting prod function
SET search_path=prod,public;
SELECT prod.outer_func();
> prod function
试验表明,功能名称解析动态基础上,search_path
在运行时。有一种方法可以在模式范围内绑定内部函数吗?
我可以通过使用SECURITY DEFINER
函数与动态SQL和CURRENT_USER
得到这样的行为,但我正在寻找更直接的东西。
您可以设置所需的搜索路径作为函数的属性(在函数定义中使用'SET')。 Btw:语言名称是一个标识符,不要把它放在单引号中。这是已被弃用的语法,将在未来被删除 –
@ a_horse_with_no_name好!工作得很好。请使用答案按钮而不是评论,以便我可以分配点并将问题设置为已回答。 – lessj
@a_horse_with_no_name是正确的。但是,我不确定为什么你在连接后不设置search_path。您在这里做的事听起来有点像很常见的多租户模式,您可以根据客户名称创建一系列相同的模式,然后在连接时将搜索路径设置为当前客户。将系统作为“测试”运行,在连接后设置search_path等。 –