I keep all my functions in a text file with \'CREATE OR REPLACE FUNCTION somefunction\'
.
So if I add or change some function I just feed the file to psql.
This query creates all necessary DDL statements. Later simplified with a cast to regprocedure, which displays as function with argument types, schema-qualified and/or double-quoted where necessary. Exactly what we need:
SELECT 'DROP FUNCTION ' || oid::regprocedure
FROM pg_proc
WHERE proname = 'my_function_name' -- name without schema-qualification
AND pg_function_is_visible(oid); -- restrict to current search_path ..
-- .. you may or may not want this
Output:
DROP FUNCTION my_function_name(string text, form text, maxlen integer);
DROP FUNCTION my_function_name(string text, form text);
DROP FUNCTION my_function_name(string text);
Execute the commands (after a plausibility check).
The function name is case-sensitive and with no added double-quotes when passed as text
parameter to match against pg_proc.proname
.
The cast to the object identifier type regprocedure
(oid::regprocedure
) makes all identifiers safe against SQL injection (by way of maliciously malformed identifiers). When converting to text
, the function name is double-quoted and schema-qualified according to the current search_path automatically where needed.
pg_function_is_visible(oid) restricts the selection to functions in the current search_path. You may or may not want that. With the condition pg_function_is_visible(oid)
in place, the function is guaranteed to be visible.
If you have multiple functions of the same name in multiple schemas, or overloaded functions with various function arguments, all of those will be listed separately. You may want to restrict to specific schema(s) or specific function parameter(s) after all.
Related:
You can build a plpgsql
function around this to execute the statements immediately with EXECUTE. For Postgres 9.1 or later:
Careful! It drops your functions!
CREATE OR REPLACE FUNCTION f_delfunc(_name text, OUT func_dropped int) AS
$func$
DECLARE
_sql text;
BEGIN
SELECT count(*)::int
, 'DROP FUNCTION ' || string_agg(oid::regprocedure::text, '; DROP FUNCTION ')
FROM pg_proc
WHERE proname = _name
AND pg_function_is_visible(oid)
INTO func_dropped, _sql; -- only returned if trailing DROPs succeed
IF func_dropped > 0 THEN -- only if function(s) found
EXECUTE _sql;
END IF;
END
$func$ LANGUAGE plpgsql;
Call:
SELECT * FROM f_delfunc('my_function_name');
Or just:
SELECT f_delfunc('my_function_name');
This way you don't get the column name func_dropped
for the result column. May not matter.
The function returns the number of functions found and dropped (no exception raised) - 0
if none were found.
It assumes a (default) search_path
where pg_catalog
has not been moved around. See:
For Postgres versions older than 9.1 or older variants of the function using regproc
and pg_get_function_identity_arguments(oid)
check the edit history of this answer.