Мы хранимые процедуры создаем в схеме public, и генерируем много
схем с одинаковыми наборами таблиц. Каждый пользователь попадает в свою схему. Для этого используем
DISCARD ALL, а затем SET SEARCH_PATH = 'название схемы', public.
Но оказалось, что вызов одной и той же хранимой процедуры в контексте различных схем, возвращает результат, основанный на схеме, в которой произошел ее первый вызов, т.е. search_path в этом случае игнорируется. Похоже Postgre где-то кэширует обращения к таблицам, используемым в хранимой процедуре. Проблема решается если продублировать хранимые процедуры в каждой схеме, но такое решение не выглядит хорошим. Кто встречался с подобной проблемой? Может мы что - то не понимаем?
Насколько я знаю, хранимая
Насколько я знаю, хранимая процедура КОМПИЛИРУЕТСЯ при её создании.
Могу предположить, что в этот момент в неё зашиваются все обращения к таблицам.
Попробуйте:
ALTER FUNCTION ... RESET ...
и
ALTER FUNCTION ... SET SCHEMA ...
может поможет
Если бы обращения
Если бы обращения формировались в момент компиляции то вызов функции всегда возвращал бы данные из схемы public, а в нашем случае возвращает данные из - той схемы, в контексте которой произошло обращение к функции.
Непонятно. Вы
Непонятно. Вы противоречите:
> Но оказалось, что вызов одной и той же хранимой процедуры в контексте различных схем, возвращает результат, основанный на схеме, в которой произошел ее первый вызов
и
> нашем случае возвращает данные из - той схемы, в контексте которой произошло обращение к функции.
Если последнее, то очевидно - это правильное поведение. Разумеется из какой схемы вызываете, та первой и будет
Нет происходит именно то что
Нет происходит именно то что запоминаются обращения к таблицам в контексте той схемы в которой произошел первый вызов хранимой процедуры, вызовы уже в контексте других схем результат не меняют.
ALTER FUNCTION ... RESET
ALTER FUNCTION ... RESET ...
и
ALTER FUNCTION ... SET SCHEMA ...
пробовали?
не пробовал, ибо мучает вопрос не будет ли вызов функции
с такой инструкцией существенно более дорогим? Ведь его придется делать перед каждым вызовом функции. Ясно, придется экспериментировать...
Я рассчитываю, что достаточно
Я рассчитываю, что достаточно ОДИН раз выполнить ALTER после переноса процедуры в схему, но разумеется я в этом не уверен и экспериментировать действительно придётся.
Проверили, одного alter оказалось недостаточно.
С горя попробовали делать alter на каждый вызов, стало хорошо. Попробовали делать в несколько потоков, получили ожидание на блокировках при выполнении alter function. Жаль, идея неплохая но не прокатило. Поискал на англоязычных форумах Postgre, оказалась проблема давно известная, решать пока не торопятся.
В паблике храним только
В паблике храним только иммутабл функции. Тогда без проблем. Иначе будет то, что у Вас. Выход - только EXECUTE command-string [ INTO [STRICT] target ] [ USING expression [, ... ] ]; с передачей имени схемы параметром или определение его в самой процедуре через переменные окружения. Не исключаю другие варианты решения, т.к. ПГ пользую недавно.
Сейчас мы проблему решили в лоб, просто в каждой схеме
дублируется описание функции. Процесс этот у нас автоматизирован, но не покидает ощущение, что все равно это некрасивое решение, однако, так работает.
Вообще-то странно. У меня
Вообще-то странно. У меня похожая схема таки работает.
CREATE OR REPLACE FUNCTION public.fmr_data_func(VARCHAR,VARCHAR,DATE) RETURNS REFCURSOR AS '
...
OPEN cursor_var FOR
SELECT owner,element,type_element,config
FROM form
WHERE ...
...
' LANGUAGE 'plpgsql' SECURITY DEFINER;
GRANT EXECUTE ON FUNCTION public.fmr_data_func(VARCHAR,VARCHAR,DATE)
TO PUBLIC;
есть пачка схем со своей таблицей `form` и все работает. В пределах сеанса разумеется. Если у Вас нужно переключать схемы в сеансе, то может сделать disconnect/connect?