Je veux pouvoir me connecter à une base de données PostgreSQL et trouver toutes les fonctions d'un schéma particulier.
Mon idée était que je pouvais interroger pg_catalog ou information_schema et obtenir une liste de toutes les fonctions, mais je ne peux pas savoir où les noms et les paramètres sont stockés. Je cherche une requête qui me donnera le nom de la fonction et les types de paramètres requis (et l'ordre dans lequel ils sont pris).
Y a-t-il un moyen de faire cela?
Après quelques recherches, j'ai pu trouver le information_schema.routines
table et le information_schema.parameters
tables. En utilisant ceux-ci, on peut construire une requête à cette fin. 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;
\df <schema>.*
in psql
donne les informations nécessaires.
Pour voir la requête utilisée en interne, connectez-vous à une base de données avec psql
et fournissez un extra "-E
" (ou "--echo-hidden
"), puis exécutez la commande ci-dessus.
Si quelqu'un est intéressé, voici quelle requête est exécutée par psql
sur 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;
Vous pouvez obtenir ce que psql
exécute pour une commande de barre oblique inverse en exécutant psql
avec le -E
drapeau.
Il y a une fonction pratique, oidvectortypes
, qui facilite beaucoup cela.
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 avoir signalé oidvectortypes
. J'avais écrit des fonctions similaires auparavant, mais j'utilisais des expressions complexes imbriquées pour lesquelles cette fonction supprime la nécessité.
(éditer 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 information_schema
tables - voir routines
et parameters
à la réponse de @ RuddZwolinski.
La fonction [~ # ~] oid [~ # ~] (voir pg_catalog.pg_proc
) et la fonction nom_spécifique (voir information_schema.routines
) sont les principales options de référence pour les fonctions. Ci-dessous, quelques fonctions utiles dans les rapports et dans 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;
Exécutez la requête SQL ci-dessous 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';
C'est une bonne idée de nommer les fonctions avec alias commun sur les premiers mots pour filtrer le nom avec LIKE
Exemple avec schéma public dans Postgresql 9.4, assurez-vous de le 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%';
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)