Reputation: 51
I'm using PostgreSQL 9.2.10
Suppose you have 2 PostgreSQL functions, 'called_function' and 'caller_function', second one is calling the first one. Exactly:
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;
Now, using SQL and knowing only function name, I would like to find out if 'caller_function' calls some other function. Or if 'called_function' is called by some other function. Is it possible?
I tried to get function's OID (let's say it is '123') and then I looked into pg_depend table:
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;
But it finds only pg_language and pg_namespace dependency. Nothing more.
Upvotes: 5
Views: 4189
Reputation: 202
Impossible in the general case; but a limited (restricted-domain) solution is perfectly doable --- and might prove adequate for your needs.
(The Most Obvious of the Many) Limitations
Sample Output
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;
How It Works
DISTINCT
to save trouble later on; SQL is case-insensitive apart from quoted identifiers which we are not bothering with anyway, so we just Lower()
to simplify comparison later.PG_Get_Functiondef()
fetches complete text of the CREATE FUNCTION
or CREATE PROCEDURE
command. Again, Lower()
.*?
quantifier: the usual *
quantifier, if used here, would remove the first single-line comment plus all subsequent lines!_
, with a space. Note the +
quantifier: it ensures that 2+ contiguous removed characters are replaced by just 1 space.INTERSECT
with routine names; result will consist of routine names only.CREATE FUNCTION f ...
command, extracted routine names will obviously contain f
itself; so we remove it with Array_Remove()
.(SQL tested with PostgreSQL 12.1)
Upvotes: 0
Reputation: 3737
I had same problem to define a function and because of dependency It didn't work. Then I solved my problem with adding this command before the commands
SET check_function_bodies = false;
hope to help someone else
Upvotes: 1
Reputation: 1399
Look at the table pg_proc for example :
select nspname,proname,prosrc from pg_proc join pg_namespace nsp on (pronamespace=nsp.oid) where prosrc like '%called_function%'
Upvotes: 0