¿Cómo puedo obtener una lista de todas las funciones almacenadas en la base de datos de un esquema particular en PostgreSQL?

135

Quiero poder conectarme a una base de datos PostgreSQL y encontrar todas las funciones para un esquema particular.

Pensé que podría hacer alguna consulta a pg_catalog o information_schema y obtener una lista de todas las funciones, pero no puedo entender dónde están almacenados los nombres y parámetros. Estoy buscando una consulta que me dé el nombre de la función y los tipos de parámetros que toma (y en qué orden los toma).

¿Hay alguna forma de hacer esto?

Rudd Zwolinski
fuente

Respuestas:

191
\df <schema>.*

en psqlda la información necesaria.

Para ver la consulta que se usa internamente, conéctese a una base de datos psqly proporcione una opción " -E" (o " --echo-hidden") adicional y luego ejecute el comando anterior.

Milen A. Radev
fuente
1
¿Podrías pegar en qué consiste esa consulta?
Rudd Zwolinski
3
SELECT n.nspname como "Schema", p.proname 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 ENTONCES 'agg' CUANDO p.proiswindow ENTONCES 'ventana' CUANDO p.prorettype = 'pg_catalog.trigger' :: pg_catalog.regtype ENTONCES 'disparar' ELSE 'normal' FINALIZAR como "Tipo" DESDE pg_catalog.pg_proc p IZQUIERDA UNIR pg_catalog .pg_namespace n ON n.oid = p.pronamespace DONDE n.nspname ~ '^ (public) $' ORDER BY 1, 2, 4; Arriba está la consulta generada (desde \ set ECHO_HIDDEN 'on').
Simon D
90

Después de buscar un poco, pude encontrar la information_schema.routinesmesa y las information_schema.parametersmesas. Utilizándolos, se puede construir una consulta para este propósito. LEFT JOIN, en lugar de JOIN, es necesario para recuperar funciones sin 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
fuente
2
Encontrará oidvectortypesrealmente útil también. Ver nueva respuesta: stackoverflow.com/a/24034604/398670
Craig Ringer
El código anterior no mostrará todas las funciones. Necesita una IZQUIERDA IZQUIERDA en lugar de UNIRSE para mostrar también funciones sin parámetros de entrada.
David
35

Si alguien está interesado aquí es qué consulta se ejecuta psqlen 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;

Puede obtener lo que se psqlejecuta para un comando de barra diagonal inversa ejecutando psqlcon el -Eindicador.

jb.
fuente
Acabo de encontrar su respuesta y probé la consulta en Postgres 11.5. Dice:ERROR: column p.proisagg does not exist
Christiaan Westerbeek
Gracias por esto; ¡Las dos respuestas mejor votadas no mostraron mi función!
Machineghost
29

Hay una función útil, oidvectortypes que hace que esto sea mucho más fácil.

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

Gracias a Leo Hsu y Regina Obe en Postgres Online por señalaroidvectortypes . Escribí funciones similares antes, pero usé expresiones anidadas complejas que esta función elimina la necesidad de.

Ver respuesta relacionada .


(editar en 2016)

Resumiendo las opciones de informe 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 : utilícelo p.proname||'_'||p.oid AS specific_name para obtener nombres únicos o para UNIRSE a information_schematablas; consulte routinesy parametersen la respuesta de @ RuddZwolinski.


La función del OID (ver  pg_catalog.pg_proc) y de la función nombre_específico (ver  information_schema.routines) son las principales opciones de referencia a funciones. A continuación, algunas funciones útiles en informes y otros 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
fuente
El pronamees el nombre, pero cómo obtener el OID para, por ejemplo. utilizar en pg_catalog.pg_get_function_result(oid))?
Peter Krauss
1
@PeterKrauss La oidcolumna de pg_proc. Es una columna oculta.
Craig Ringer
1
Consulte también stackoverflow.com/a/25388031/161040 para saber cómo excluir funciones dependientes de extensiones (por ejemplo, funciones de PostGIS).
Simon D
20

Ejecute debajo de la consulta SQL para crear una vista que muestre todas las funciones:

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

Es una buena idea nombrar las funciones con alias comun en las primeras palabras para filtrar el nombre con LIKE Ejemplo con esquema público en Postgresql 9.4, asegúrese de reemplazar con su 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
fuente
4

Ejemplo:

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
fuente
55
¿Y cómo es eso diferente a la respuesta de Milen?
a_horse_with_no_name
3
Esto no es una consulta, es un comando de la psqlinterfaz del cliente de Postgres. Esto solo funcionará psqly técnicamente no es una consulta SQL.
GregT
3

Obtener la lista de function_schema y 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;
maddy
fuente
2

Esta función devuelve todas las rutinas definidas por el usuario en la base de datos actual.

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
fuente