我正在使用PostgreSQL 9.2.10
假设您有2个PostgreSQL函数,'called_function'和'caller_function',第二个调用第一个函数。恰好:
CREATE FUNCTION called_function () RETURNS varchar AS
$BODY$
BEGIN
RETURN 'something';
END;
CREATE FUNCTION caller_function () RETURNS varchar AS
$BODY$
BEGIN
RETURN called_function ();
END;
现在,使用SQL并只知道函数名称,我想知道'caller_function'是否调用了其他函数。或者,如果某个其他函数调用了'called_function'。有可能吗?
我试图获取函数的OID(假设它是'123')然后我查看 pg_depend 表:
SELECT * FROM pg_catalog.pg_depend dep WHERE dep.objid = 123 OR dep.objsubid = 123 OR dep.refobjid = 123 OR dep.refobjsubid = 123 OR dep.refobjsubid = 123;
但它只找到 pg_language 和 pg_namespace 依赖项。没什么。
答案 0 :(得分:0)
请查看表格pg_proc,例如:
select nspname,proname,prosrc from pg_proc join pg_namespace nsp on (pronamespace=nsp.oid) where prosrc like '%called_function%'
答案 1 :(得分:0)
我在定义函数时遇到了同样的问题,并且由于依赖关系,它不起作用。然后我通过在命令之前添加此命令解决了我的问题
SET check_function_bodies = false;
希望能帮助别人
答案 2 :(得分:0)
在一般情况下是不可能的;但是受限(受限域)解决方案是完全可行的---并可能足以满足您的需求。
(其中最明显的)局限性
样本输出
Your routine... | ...calls these routines:
---------------------------------+-------------------------------------------------
create_silo_indexes | {get_config__f_l__ea_silo,subst_silo_id}
demux__id_creat_thread | {}
grow__sensor_thhourly | {containing_hhour_t_begin}
SQL
WITH routine_names AS (
SELECT DISTINCT(Lower(proname)) AS name --#0
FROM pg_proc
WHERE proowner = To_Regrole(current_role)
)
SELECT
name AS "Your routine...",
Array_Remove( --#8
Array( --#7
SELECT Unnest( --#5
String_To_Array( --#4
Regexp_Replace( --#3
Regexp_Replace( --#2
Lower(PG_Get_Functiondef(To_Regproc(name))) --#1
, '--.*?\n', '', 'g'
)
, '\W+', ' ', 'g'
)
, ' '
)
)
INTERSECT --#6
SELECT name FROM routine_names
ORDER BY 1
)
, name
) AS "...calls these routines:"
FROM
routine_names;
工作原理
DISTINCT
即可避免以后的麻烦; SQL除了区分引号的标识符外,不区分大小写,而引号标识符我们也不会打扰,因此我们只使用Lower()
来简化以后的比较。PG_Get_Functiondef()
提取CREATE FUNCTION
或CREATE PROCEDURE
命令的完整文本。同样,Lower()
。*?
量词:常用的*
量词(如果在此处使用)将删除所有后续行中的第一个单行注释 plus !_
以外的所有字符。请注意+
量词:它确保2个以上连续的已删除字符被1个空格代替。INTERSECT
,带有例程名称;结果将仅包含例程名称。CREATE FUNCTION f ...
命令的完整文本,因此提取的例程名称显然将包含f
本身;因此我们用Array_Remove()
将其删除。(SQL已在PostgreSQL 12.1上测试)