PostgreSQL: как составить список всех хранимых функций, которые обращаются к определенной таблице

13

Введение:

База данных PostgreSQL с несколькими сотнями хранимых функций, включая устаревшие, неиспользуемые и т. Д.

проблема

Мне нужно выяснить все хранимые функции, которые имеют какое-либо отношение к таблице X - так как я хочу изменить структуру таблицы. Некоторые из них могут быть не использованы, поэтому я не могу сделать это, просто просматривая код.

У меня есть решение ATM, которое использует psql \df+и grepping output, но я бы предпочел решение, похожее на базу данных, то есть с использованием информационной схемы. Это определенно будет повторяющимся заданием, и мне бы хотелось, чтобы оно было красивым и чистым.

Какие-либо предложения?

Сергей Кудрявцев
источник

Ответы:

18

Тело функции просто хранится в виде строки . Нет списка объектов, на которые есть ссылки. (Это отличается от представлений, например, где сохраняются фактические ссылки на ссылочные таблицы.)

Этот запрос для Postgres 10 или более ранней версии использует информационную функцию системного каталога,pg_get_functiondef() чтобы восстановить CREATE FUNCTIONсценарий для соответствующих функций и ищет имя таблицы с регулярным выражением без учета регистра:

SELECT n.nspname AS schema_name
     , p.proname AS function_name
     , pg_get_function_arguments(p.oid) AS args
     , pg_get_functiondef(p.oid) AS func_def
FROM   pg_proc p
JOIN   pg_namespace n ON n.oid = p.pronamespace
WHERE  NOT p.proisagg
AND    n.nspname NOT LIKE 'pg_%'
AND    n.nspname <> 'information_schema'
AND    pg_get_functiondef(p.oid) ~* '\mbig\M';

Это должно сделать работу, но это явно не пуленепробиваемый. Может произойти сбой для динамического SQL, где имя таблицы генерируется динамически, и может возвращать любое количество ложных срабатываний, особенно если имя таблицы является общим словом.

Агрегатные функции и все функции из системных схем исключаются.

\mи\M отметьте начало и конец слова в регулярном выражении.

Системный каталог pg_procизменен в Postgres 11. proisaggбыл заменен, добавлены prokindистинные хранимые процедуры. Вам нужно адаптироваться. Связанные с:

Эрвин Брандштеттер
источник
1
Да ... это не совсем надежно, в том смысле, что он не найдет EXECUTEтакие выражения, как 'mm_'||name_parameter, и он не будет корректно работать с именами в кавычках, такими как "my""table""или со сложением регистра, но он будет делать большую часть того, что захочет большинство людей ,
Крейг Рингер
@CraigRinger: Да, динамические запросы EXECUTEпрактически невозможно охватить. Но сворачивание в регистр может быть выполнено ~*вместо ~- или любого другого нечувствительного к регистру сопоставления с образцом.
Эрвин Брандштеттер
Пока оператор не настолько сумасшедший, чтобы фактически создавать именованные таблицы "MyTable"и MyTable, по крайней мере ... и, честно говоря, это "хорошо, это может быть разрешено, но это не разумно".
Крейг Рингер
Спасибо за ответ! Я фактически нигде не использую динамическое построение имен таблиц, и все имена таблиц строчные.
Сергей Кудрявцев
1

Этот запрос довольно прост в использовании:

SELECT proname, proargnames, prosrc FROM pg_proc WHERE prosrc ILIKE '%Text to search%';
Жоао Виктор Сильва де Оливейра
источник