如何更改递归函数的架构

时间:2019-06-18 18:31:28

标签: postgresql etl data-warehouse

作为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$
;

有没有办法改变递归函数的模式?

如果失败,我可以让功能维护者更改其实现。 有没有一种方法可以让函数调用类似“ self”的东西(即隐式地不指定其自身名称)?

1 个答案:

答案 0 :(得分:1)

该函数中使用的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 但这有点hacky ...

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
...