PostgreSQL: Como listar todas as funções armazenadas que acessam tabela específica

13

Introdução:

Banco de dados PostgreSQL com várias centenas de funções armazenadas, incluindo obsoletas, não usadas etc.

Problema

Preciso descobrir todas as funções armazenadas que tenham qualquer relação com a tabela X - pois quero alterar a estrutura da tabela. Alguns deles podem não ser usados, por isso não posso fazer isso apenas olhando o código.

A solução que eu tenho ATM está executando o psql \df+e o grepping output, mas eu preferiria uma solução mais semelhante ao banco de dados, ou seja, usando o esquema de informações. Definitivamente, essa será uma tarefa repetitiva e eu gostaria que fosse agradável e limpo.

Alguma sugestão?

Sergey Kudriavtsev
fonte

Respostas:

18

O corpo de uma função é apenas armazenado como string . Não há lista de objetos referenciados. (Isso é diferente das visualizações, por exemplo, onde os links reais para as tabelas referenciadas são salvos.)

Esta consulta para o Postgres 10 ou anterior usa a função de informações do catálogopg_get_functiondef() do sistema para reconstruir o CREATE FUNCTIONscript para funções relevantes e procura o nome da tabela com uma expressão regular que não diferencia maiúsculas de minúsculas:

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';

Deveria fazer o trabalho, mas obviamente não é à prova de balas. Pode falhar no SQL dinâmico, onde o nome da tabela é gerado dinamicamente e pode retornar qualquer número de falsos positivos - especialmente se o nome da tabela for uma palavra comum.

Funções agregadas e todas as funções dos esquemas do sistema são excluídas.

\me\M marque o início e o fim de uma palavra na expressão regular.

O catálogo do sistema pg_procalterado no Postgres 11. proisaggfoi substituído por prokind, procedimentos armazenados verdadeiros foram adicionados. Você precisa se adaptar. Palavras-chave:

Erwin Brandstetter
fonte
1
Sim ... não é totalmente robusto, no sentido de que não encontrará EXECUTEexpressões como 'mm_'||name_parameter, e não lidará corretamente com nomes citados como "my""table""ou com dobras de maiúsculas e minúsculas, mas fará o que a maioria das pessoas deseja .
Craig Ringer
@ CraigRinger: Sim, EXECUTEé quase impossível cobrir consultas dinâmicas com . Mas a dobra de caixa pode ser coberta com, em ~*vez de ~- ou qualquer outra correspondência de padrão que não diferencia maiúsculas de minúsculas.
Erwin Brandstetter
Desde que o operador não seja louco o suficiente para criar tabelas nomeadas "MyTable"e MyTable, pelo menos ... e honestamente, isso é um "bem, isso pode ser permitido, mas não é inteligente".
22813 Craig Ringer
Obrigado pela resposta! Na verdade, não uso a construção dinâmica de nomes de tabelas em nenhum lugar e todos os nomes de tabelas são minúsculos.
Sergey Kudriavtsev
1

Esta consulta é muito fácil de usar:

SELECT proname, proargnames, prosrc FROM pg_proc WHERE prosrc ILIKE '%Text to search%';
joao victor silva de oliveira
fonte