是否可以找到PostgreSQL函数之间的依赖关系?
我正在使用PostgreSQL9.2.10 假设您有两个PostgreSQL函数,“called_function”和“caller_function”,第二个函数调用第一个函数。确切地说:是否可以找到PostgreSQL函数之间的依赖关系?,sql,postgresql,Sql,Postgresql,我正在使用PostgreSQL9.2.10 假设您有两个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
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\u 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_语言和pg_名称空间依赖项。仅此而已。查看表格pg_proc,例如:
select nspname,proname,prosrc from pg_proc join pg_namespace nsp on (pronamespace=nsp.oid) where prosrc like '%called_function%'
我在定义一个函数时遇到了同样的问题,但由于依赖关系,它无法工作。然后,我解决了在命令之前添加此命令的问题
SET check_function_bodies = false;
希望帮助别人一般情况下不可能;但是一个有限的(受限域)解决方案是完全可行的——并且可能被证明足以满足您的需求 (众多限制中最明显的一个)限制
- 如果被调用方(要调用的函数)的名称被指定为带引号的标识符,则失败(假阴性)
- 如果被调用方的名称作为参数传递,则失败(假阴性)
- 如果在运行时从关系中读取被调用方的名称,则失败(假阴性)
- 如果被调用方的名称是从令牌组装而来,则失败(假阴性)
- 若被调用方的名称与文字相同,则失败(误报)
- 如果多行注释中存在被调用方的名称,则失败(误报)
- 不考虑函数重载
- 不考虑通过触发器调用的函数
- 不考虑根据查询重写规则调用的函数
- 不考虑查询重写规则的影响
- 对用C等非解释PLs编写的函数一无所知
您的日常工作…|。。。调用这些例程:
--------------------------------------+------------------------------------
create_silo_index{get_config_f_l_ea_silo,subst_silo_id}
demux\uuu id\u创建线程{}
grow\uuu sensor\u thu124;{containing\uh\uu t\u begin}
SQL 它的工作原理
- #0收集可能是调用者和/或被调用者的所有例程的名称。无论如何,我们都无法正确处理重载函数,因此只需
,以避免以后的麻烦;SQL是不区分大小写的,除了带引号的标识符之外,我们无论如何都不会去处理它们,所以我们只是DISTINCT
来简化后面的比较Lower()
- #1
获取PG_Get_Functiondef()
或创建函数
命令的完整文本。同样,创建过程
Lower()
- #2去除单行注释。注意懒惰(非贪婪)
量词:通常的*?
量词,如果在这里使用,将删除第一行注释和所有后续行李>*
- #3将字母和数字以外的所有字符和
替换为空格。请注意
量词:它确保2个以上连续删除的字符仅替换为1个空格+
- #4按空格分割成一个数组;这个数组包含一些SQL语法、文字、数字和标识符,包括例程名称
- #5将数组卸载到行集中
- #6
;结果将仅由例程名称组成与例程名称相交
- #7将行集转换为数组
- #8由于输入是
命令的完整文本,因此提取的例程名称显然包含创建函数f…
本身;因此,我们使用f
删除它Array\u remove()
(用PostgreSQL 12.1测试SQL)我认为这是不可能的。此外,postgres支持不同的语言,包括C语言,在这些语言中查找依赖项并不容易。我可以想到plpgsql和sql函数的一种解决方法:您可以搜索pg_proc表,例如:
select oid,proname from pg_proc,prosrc不为null,prosrc类似“%”
。但这不是一个非常可靠的方法!我猜答案是否定的,Postgress不跟踪函数依赖关系,这就是为什么你可以创建一个依赖于另一个不存在的函数的函数。。。因为它在运行时会爆炸#悲哀的
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;