Comment puis-je obtenir une liste de toutes les fonctions stockées dans la base de données d'un schéma particulier dans PostgreSQL?

135

Je veux pouvoir me connecter à une base de données PostgreSQL et trouver toutes les fonctions pour un schéma particulier.

Ma pensée était que je pourrais faire une requête à pg_catalog ou information_schema et obtenir une liste de toutes les fonctions, mais je ne peux pas comprendre où les noms et les paramètres sont stockés. Je recherche une requête qui me donnera le nom de la fonction et les types de paramètres qu'elle prend (et dans quel ordre elle les prend).

Y a-t-il un moyen de faire cela?

Rudd Zwolinski
la source

Réponses:

191
\df <schema>.*

in psqldonne les informations nécessaires.

Pour voir la requête utilisée en interne, connectez-vous à une base de données avec psqlet fournissez une option supplémentaire " -E" (ou " --echo-hidden"), puis exécutez la commande ci-dessus.

Milen A. Radev
la source
1
Pourriez-vous coller ce qu'est cette requête?
Rudd Zwolinski
3
SELECT n.nspname comme "Schema", p.proname comme "Name", pg_catalog.pg_get_function_result (p.oid) comme "Result data type", pg_catalog.pg_get_function_arguments (p.oid) comme "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 comme "Type" FROM pg_catalog.pg_proc p GAUCHE JOIN pg_catalog .pg_namespace n ON n.oid = p.pronamespace WHERE n.nspname ~ '^ (public) $' ORDER BY 1, 2, 4; Ci-dessus est la requête générée (à partir de \ set ECHO_HIDDEN 'on').
Simon D
90

Après quelques recherches, j'ai pu trouver la information_schema.routinestable et les information_schema.parameterstables. En utilisant ceux-ci, on peut construire une requête à cet effet. LEFT JOIN, au lieu de JOIN, est nécessaire pour récupérer des fonctions sans paramètres.

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
la source
2
Vous trouverez également oidvectortypestrès utile. Voir la nouvelle réponse: stackoverflow.com/a/24034604/398670
Craig Ringer
Le code ci-dessus n'affichera pas toutes les fonctions, vous avez besoin d'un LEFT JOIN au lieu de JOIN pour afficher également les fonctions sans paramètres d'entrée.
David
35

Si quelqu'un est intéressé, voici quelle requête est exécutée par psqlpostgres 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;

Vous pouvez obtenir ce qui psqlfonctionne pour une commande anti-slash en exécutant psqlavec l' -Eindicateur.

jb.
la source
Je viens de trouver votre réponse et j'ai essayé la requête sur Postgres 11.5. Il dit:ERROR: column p.proisagg does not exist
Christiaan Westerbeek
Merci pour cela; les deux réponses les plus votées n'ont pas montré ma fonction!
machineghost le
29

Il y a une fonction pratique oidvectortypes, qui rend cela beaucoup plus facile.

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

Nous remercions Leo Hsu et Regina Obe de Postgres Online pour l'avoir signalé oidvectortypes. J'ai écrit des fonctions similaires auparavant, mais j'ai utilisé des expressions imbriquées complexes dont cette fonction ne nécessite plus.

Voir la réponse associée .


(modifier en 2016)

Résumé des options de rapport typiques:

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

AVIS : utilisez p.proname||'_'||p.oid AS specific_name pour obtenir des noms uniques, ou pour JOIN avec des information_schematables - voir routineset parametersà la réponse de @ RuddZwolinski.


De la fonction OID (voir  pg_catalog.pg_proc) et de la fonction de specific_name (voir  information_schema.routines) sont les principales options de référence aux fonctions. Ci-dessous, quelques fonctions utiles dans le reporting et d'autres contextes.

--- --- --- --- ---
--- 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
la source
Le pronameest le nom, mais comment obtenir l'OID pour, par exemple. utiliser dans pg_catalog.pg_get_function_result(oid))?
Peter Krauss
1
@PeterKrauss La oidcolonne de pg_proc. C'est une colonne cachée.
Craig Ringer
1
Voir aussi stackoverflow.com/a/25388031/161040 pour savoir comment exclure les fonctions dépendant de l'extension (par exemple les fonctions de PostGIS).
Simon D
20

Exécutez sous la requête SQL pour créer une vue qui affichera toutes les fonctions:

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

Est-ce une bonne idée de nommer les fonctions avec l'alias commun sur les premiers mots pour filtre le nom avec LIKE Exemple avec schéma public dans Postgresql 9.4, assurez-vous de remplacer par son schéma

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

Exemple:

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
la source
5
Et en quoi est-ce différent de la réponse de Milen?
a_horse_with_no_name
3
Ce n'est pas une requête, c'est une commande de l' psqlinterface client Postgres. Cela ne fonctionnera que dans psqlet n'est pas techniquement une requête SQL.
GregT
3

Obtenir la liste du schéma_fonction et du nom_fonction ...


> 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
la source
2

Cette fonction renvoie toutes les routines définies par l'utilisateur dans la base de données actuelle.

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
la source