Системные каталоги изменены в Postgres 11 !(prokind
вместо proisagg
) См .:
Можетвыглядеть следующим образом:
CREATE OR REPLACE FUNCTION public.f_delfunc(_schema text, _del text = '')
RETURNS text AS
$func$
DECLARE
_sql text;
_ct text;
BEGIN
SELECT INTO _sql, _ct
string_agg('DROP '
|| CASE p.proisagg WHEN true THEN 'AGGREGATE '
ELSE 'FUNCTION ' END
|| quote_ident(n.nspname) || '.' || quote_ident(p.proname)
|| '('
|| pg_catalog.pg_get_function_identity_arguments(p.oid)
|| ')'
, E'\n'
)
,count(*)::text
FROM pg_catalog.pg_proc p
LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
WHERE n.nspname = _schema;
-- AND p.proname ~~* 'f_%'; -- Only selected funcs?
-- AND pg_catalog.pg_function_is_visible(p.oid) -- Only visible funcs?
IF _ct = '0' THEN
RETURN 'Found 0 functions to delete';
ELSIF lower(_del) = 'del' THEN -- Actually delete!
EXECUTE _sql;
RETURN _ct || E' functions deleted:\n' || _sql;
ELSE -- Else only show SQL.
RETURN _ct || E' functions to delete:\n' || _sql;
END IF;
END
$func$ LANGUAGE plpgsql;
Позвонить, чтобы показать:
SELECT f_delfunc('public'); -- 2nd parameter is covered by default.
Позвонить, чтобы удалить:
SELECT f_delfunc('public','del');
Основные точки
Для этого вам нужен динамический SQL.Используйте функцию plpgsql или оператор DO (PostgreSQL 9.0+) с EXECUTE
.
Обратите внимание на использование функции pg_get_function_identity_arguments()
и pg_function_is_visible
.Последнее может быть опущено.Это защита, поэтому вы не можете удалять функции за пределами текущего пользователя search_path
.
Я добавил «безопасный режим».Удалить только если $2 = 'del'
.Иначе только показывать сгенерированный SQL.
Имейте в виду, что функция сама удалит , если она будет жить в схеме, из которой вы удаляете.
Я также добавил quote_ident()
для защиты от SQLi .Примите во внимание следующее:
CREATE FUNCTION "; DELETE FROM users;"()
RETURNS int AS
'SELECT 1'
LANGUAGE sql;
- Это не работает, если есть зависимости от какой-либо задействованной функции.Можно решить, добавив
CASCADE
, но я здесь этого не делал, поскольку это делает функцию еще более опасной.
Связано: