Как изменить схему для рекурсивной функции - PullRequest
0 голосов
/ 18 июня 2019

В рамках процесса ETL я пытаюсь изменить схему рекурсивной функции. Нравится

CREATE FUNCTION some_recursive()
 RETURNS some_type
 LANGUAGE sql
AS $function$ 
 -- do stuff
 some_recursive()
 --do more
$function$
;

Я делаю это, используя

ALTER FUNCTION some_recursive() SET SCHEMA new_schema

Это правильно обновляет, например, зависимые представления, изменяя их с вызова some_recursive() на new_schema.some_recursive(). Но сама рекурсия (в теле функции) не обновляется, поэтому при вызове функции происходит сбой. То есть изменение пост-схемы определения функции выглядит так:

CREATE FUNCTION new_schema.some_recursive()
 RETURNS some_type
 LANGUAGE sql
AS $function$ 
 -- do stuff
 -- note the next line (no new_schema.-prefix)
 some_recursive()
 --do more
$function$
;

Есть ли способ изменить схему рекурсивной функции?

Если это не удастся, я смогу заставить сопровождающего функции изменить его реализацию. Есть ли способ заставить функцию вызывать что-то вроде «себя» (то есть неявно без указания собственного имени)?

1 Ответ

1 голос
/ 18 июня 2019

Search_path, используемый в функции, зависит от search_path, установленного в сеансе, который вызывает функцию.Вы можете изменить это по умолчанию для любого пользователя, вызывающего функцию, изменив пользователя:

ALTER USER some_user SET search_path TO new_schema,...;  -- you may also want public or others after new_schema

В качестве альтернативы, вы можете изменить search_path, используемый только в функции, слегка изменив код:

CREATE FUNCTION new_schema.some_recursive()
 RETURNS some_type
 LANGUAGE sql
 SET search_path TO new_schema -- this line changes search_path while inside the function.  It will be reset on function exit.
AS $function$ 
 -- do stuff
 -- note the next line (no new_schema.-prefix)
 some_recursive()
 --do more
$function$
;

Вы также можете использовать PG_CONTEXT, как указано здесь: https://stackoverflow.com/a/41889304/895640, но это немного глупо ...

CREATE OR REPLACE FUNCTION recursive_test() RETURNS int AS $$
DECLARE
  stack text;
  fcesig regprocedure;
BEGIN
  GET DIAGNOSTICS stack = PG_CONTEXT;
  RAISE NOTICE 'stack: %', stack;
  fcesig := substring(stack from 'function (.*?) line');
  EXECUTE 'SELECT ' || fcesig;
END;
$$ LANGUAGE plpgsql
;

CREATE SCHEMA test2;
alter function recursive_test set schema test2;
NOTICE:  stack: PL/pgSQL function test2.recursive_test() line 6 at GET DIAGNOSTICS
NOTICE:  stack: PL/pgSQL function test2.recursive_test() line 6 at GET DIAGNOSTICS
SQL statement "SELECT test2.recursive_test()"
PL/pgSQL function test2.recursive_test() line 9 at EXECUTE
NOTICE:  stack: PL/pgSQL function test2.recursive_test() line 6 at GET DIAGNOSTICS
SQL statement "SELECT test2.recursive_test()"
PL/pgSQL function test2.recursive_test() line 9 at EXECUTE
SQL statement "SELECT test2.recursive_test()"
PL/pgSQL function test2.recursive_test() line 9 at EXECUTE
NOTICE:  stack: PL/pgSQL function test2.recursive_test() line 6 at GET DIAGNOSTICS
SQL statement "SELECT test2.recursive_test()"
PL/pgSQL function test2.recursive_test() line 9 at EXECUTE
SQL statement "SELECT test2.recursive_test()"
PL/pgSQL function test2.recursive_test() line 9 at EXECUTE
...
...