У меня есть две аналогичные схемы в одной базе данных с теми же именами функций. Каждая схема принадлежит роли, которая соответствует имени схемы.Разрешение имени функции 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 Nice! работайте так хорошо. Пожалуйста, используйте кнопку ответа вместо комментария, чтобы я мог назначать точки и задавать вопрос в соответствии с ответом. – lessj
@a_horse_with_no_name верное. Но я не уверен, почему вы просто не устанавливаете путь search_path после подключения. То, что вы здесь делаете, похоже на довольно распространенный шаблон с несколькими арендаторами, где вы создаете серию идентичной схемы на основе имени клиента, а затем, когда вы подключаетесь, вы устанавливаете путь поиска к текущему клиенту. Запуск системы как «тест» устанавливает путь поиска после подключения и т. Д. –