Como posso obter uma lista de todas as funções armazenadas no banco de dados de um esquema específico no PostgreSQL?

135

Quero poder conectar-me a um banco de dados PostgreSQL e encontrar todas as funções de um esquema específico.

Meu pensamento era que eu poderia fazer alguma consulta para pg_catalog ou information_schema e obter uma lista de todas as funções, mas não consigo descobrir onde os nomes e parâmetros estão armazenados. Estou procurando uma consulta que me forneça o nome da função e os tipos de parâmetros necessários (e em que ordem eles são recebidos).

Existe uma maneira de fazer isso?

Rudd Zwolinski
fonte

Respostas:

191
\df <schema>.*

in psqlfornece as informações necessárias.

Para ver a consulta usada internamente, conecte-se a um banco de dados psqle forneça uma opção " -E" (ou " --echo-hidden") extra e, em seguida, execute o comando acima.

Milen A. Radev
fonte
1
Você pode colar o que é essa consulta?
Rudd Zwolinski 28/08/09
3
SELECT n.nspname como "Esquema", p.pronome como "Name", pg_catalog.pg_get_function_result (p.oid) como "Result data type", pg_catalog.pg_get_function_arguments (p.oid) como "Argument data types", CASE WHEN p .proisagg THEN 'agg' WHEN p.proiswindow THEN 'window' WHEN p.prorettype = 'pg_catalog.trigger' :: pg_catalog.trtyger ':: pg_catalog.regtype THEN' trigger 'ELSE' normal 'END como "Digite" FROM pg_catalog.pg_proc p ESQUERDA JOIN pg_catalog.pg_proc .pg_namespace n ON n.oid = p.pronamespace WHERE n.nspname ~ '^ (public) $' ORDER BY 1, 2, 4; Acima é a consulta gerada (de \ set ECHO_HIDDEN 'on').
Simon D
90

Após algumas pesquisas, consegui encontrar a information_schema.routinesmesa e as information_schema.parametersmesas. Usando esses, pode-se construir uma consulta para esse fim. LEFT JOIN, em vez de JOIN, é necessário para recuperar funções sem parâmetros.

SELECT routines.routine_name, parameters.data_type, parameters.ordinal_position
FROM information_schema.routines
    LEFT JOIN information_schema.parameters ON routines.specific_name=parameters.specific_name
WHERE routines.specific_schema='my_specified_schema_name'
ORDER BY routines.routine_name, parameters.ordinal_position;
Rudd Zwolinski
fonte
2
Você achará oidvectortypesrealmente útil também. Veja a nova resposta: stackoverflow.com/a/24034604/398670
Craig Ringer
O código acima não mostrará todas as funções. Você precisa de LEFT JOIN em vez de JOIN para também mostrar funções sem parâmetros de entrada.
David
35

Se alguém estiver interessado aqui, qual é a consulta executada psqlno postgres 9.1:

SELECT n.nspname as "Schema",
  p.proname as "Name",
  pg_catalog.pg_get_function_result(p.oid) as "Result data type",
  pg_catalog.pg_get_function_arguments(p.oid) as "Argument data types",
 CASE
  WHEN p.proisagg THEN 'agg'
  WHEN p.proiswindow THEN 'window'
  WHEN p.prorettype = 'pg_catalog.trigger'::pg_catalog.regtype THEN 'trigger'
  ELSE 'normal'
 END as "Type"
FROM pg_catalog.pg_proc p
     LEFT JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
WHERE pg_catalog.pg_function_is_visible(p.oid)
      AND n.nspname <> 'pg_catalog'
      AND n.nspname <> 'information_schema'
ORDER BY 1, 2, 4;

Você pode obter o que psqlé executado para um comando de barra invertida executando psqlcom o -Esinalizador

jb.
fonte
Acabei de encontrar sua resposta e tentei a consulta no Postgres 11.5. Diz:ERROR: column p.proisagg does not exist
Christiaan Westerbeek em
Obrigado por isso; as duas respostas mais votadas não mostraram minha função!
machineghost
29

Há uma função útil oidvectortypes, que facilita muito isso.

SELECT format('%I.%I(%s)', ns.nspname, p.proname, oidvectortypes(p.proargtypes)) 
FROM pg_proc p INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
WHERE ns.nspname = 'my_namespace';

Agradecemos a Leo Hsu e Regina Obe, do Postgres Online, por apontarem oidvectortypes. Eu escrevi funções semelhantes antes, mas usei expressões aninhadas complexas das quais essa função se livra da necessidade.

Veja a resposta relacionada .


(editar em 2016)

Resumindo opções de relatório típicas:

-- Compact:
SELECT format('%I.%I(%s)', ns.nspname, p.proname, oidvectortypes(p.proargtypes))

-- With result data type: 
SELECT format(
       '%I.%I(%s)=%s', 
       ns.nspname, p.proname, oidvectortypes(p.proargtypes),
       pg_get_function_result(p.oid)
)

-- With complete argument description: 
SELECT format('%I.%I(%s)', ns.nspname, p.proname, pg_get_function_arguments(p.oid))

-- ... and mixing it.

-- All with the same FROM clause:
FROM pg_proc p INNER JOIN pg_namespace ns ON (p.pronamespace = ns.oid)
WHERE ns.nspname = 'my_namespace';

AVISO : use p.proname||'_'||p.oid AS specific_name para obter nomes exclusivos ou para se juntar a information_schematabelas - consulte routinese parametersna resposta de @ RuddZwolinski.


OID da função (consulte  pg_catalog.pg_proc) e nome específico da função (consulte  information_schema.routines) são as principais opções de referência para funções. Abaixo, algumas funções úteis nos relatórios e em outros contextos.

--- --- --- --- ---
--- Useful overloads: 

CREATE FUNCTION oidvectortypes(p_oid int) RETURNS text AS $$
    SELECT oidvectortypes(proargtypes) FROM pg_proc WHERE oid=$1;
$$ LANGUAGE SQL IMMUTABLE;

CREATE FUNCTION oidvectortypes(p_specific_name text) RETURNS text AS $$
    -- Extract OID from specific_name and use it in oidvectortypes(oid).
    SELECT oidvectortypes(proargtypes) 
    FROM pg_proc WHERE oid=regexp_replace($1, '^.+?([^_]+)$', '\1')::int;
$$ LANGUAGE SQL IMMUTABLE;

CREATE FUNCTION pg_get_function_arguments(p_specific_name text) RETURNS text AS $$
    -- Extract OID from specific_name and use it in pg_get_function_arguments.
    SELECT pg_get_function_arguments(regexp_replace($1, '^.+?([^_]+)$', '\1')::int)
$$ LANGUAGE SQL IMMUTABLE;

--- --- --- --- ---
--- User customization: 

CREATE FUNCTION pg_get_function_arguments2(p_specific_name text) RETURNS text AS $$
    -- Example of "special layout" version.
    SELECT trim(array_agg( op||'-'||dt )::text,'{}') 
    FROM (
        SELECT data_type::text as dt, ordinal_position as op
        FROM information_schema.parameters 
        WHERE specific_name = p_specific_name 
        ORDER BY ordinal_position
    ) t
$$ LANGUAGE SQL IMMUTABLE;
Craig Ringer
fonte
O pronameé o nome, mas como obter o OID, por exemplo. usar em pg_catalog.pg_get_function_result(oid))?
Peter Krauss
1
@PeterKrauss A oidcoluna de pg_proc. É uma coluna oculta.
Craig Ringer
1
Consulte também stackoverflow.com/a/25388031/161040 para saber como excluir funções dependentes de extensão (por exemplo, funções do PostGIS).
Simon D
20

Execute a consulta SQL abaixo para criar uma exibição que mostrará todas as funções:

CREATE OR REPLACE VIEW show_functions AS
    SELECT routine_name FROM information_schema.routines 
        WHERE routine_type='FUNCTION' AND specific_schema='public';
laudarch
fonte
10

É uma boa idéia nomear as funções com alias commun nas primeiras palavras para filtrar o nome com LIKE Exemplo com esquema público no Postgresql 9.4, certifique-se de substituir por seu esquema

SELECT routine_name 
FROM information_schema.routines 
WHERE routine_type='FUNCTION' 
  AND specific_schema='public'
  AND routine_name LIKE 'aliasmyfunctions%';
Alberto Morales Fernández
fonte
4

Exemplo:

perfdb-# \df information_schema.*;

List of functions
        Schema      |        Name        | Result data type | Argument data types |  Type  
 information_schema | _pg_char_max_length   | integer | typid oid, typmod integer | normal
 information_schema | _pg_char_octet_length | integer | typid oid, typmod integer | normal
 information_schema | _pg_datetime_precision| integer | typid oid, typmod integer | normal
 .....
 information_schema | _pg_numeric_scale     | integer | typid oid, typmod integer | normal
 information_schema | _pg_truetypid         | oid     | pg_attribute, pg_type     | normal
 information_schema | _pg_truetypmod        | integer | pg_attribute, pg_type     | normal
(11 rows)
Ritu
fonte
5
E como isso é diferente da resposta de Milen?
A_horse_with_no_name 24/09
3
Esta não é uma consulta, é um comando da psqlinterface do cliente do Postgres. Isso funcionará apenas psqle não é tecnicamente uma consulta SQL.
precisa saber é o seguinte
3

Obter Lista de function_schema e function_name ...


> select n.nspname as function_schema,
> 
> p.proname as function_name
> 
> from pg_proc p
> 
> left join pg_namespace n on p.pronamespace = n.oid
> 
> where n.nspname not in ('pg_catalog', 'information_schema')
> 
> order by function_schema, function_name;
louco
fonte
2

Esta função retorna todas as rotinas definidas pelo usuário no banco de dados atual.

SELECT pg_get_functiondef(p.oid) FROM pg_proc p
INNER JOIN pg_namespace ns ON p.pronamespace = ns.oid
WHERE ns.nspname = 'public';
Alex
fonte