Jak mogę uzyskać listę wszystkich funkcji przechowywanych w bazie danych określonego schematu w PostgreSQL?

135

Chcę mieć możliwość połączenia się z bazą danych PostgreSQL i znalezienia wszystkich funkcji dla określonego schematu.

Pomyślałem, że mógłbym wykonać zapytanie do pg_catalog lub information_schema i uzyskać listę wszystkich funkcji, ale nie mogę dowiedzieć się, gdzie są przechowywane nazwy i parametry. Szukam zapytania, które poda nazwę funkcji i typy parametrów, które przyjmuje (i kolejność, w jakiej je przyjmuje).

Czy jest na to sposób?

Rudd Zwolinski
źródło

Odpowiedzi:

191
\df <schema>.*

w psqlzawiera niezbędne informacje.

Aby zobaczyć zapytanie, które jest używane wewnętrznie, połącz się z bazą danych psqli podaj dodatkową opcję „ -E” (lub „ --echo-hidden”), a następnie wykonaj powyższe polecenie.

Milen A. Radev
źródło
1
Czy możesz wkleić to zapytanie?
Rudd Zwolinski
3
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 TO 'trigger' ELSE 'normal' END as "Type" Z pg_catalog.pg_proc p LEFT JOIN pg_catalog .pg_namespace n ON n.oid = p.pronamespace WHERE n.nspname ~ '^ (public) $' ORDER BY 1, 2, 4; Powyżej jest wygenerowane zapytanie (z \ set ECHO_HIDDEN „on”).
Simon D,
90

Po kilku poszukiwaniach udało mi się znaleźć information_schema.routinesstół i information_schema.parametersstoły. Korzystając z nich, można w tym celu skonstruować zapytanie. LEFT JOIN, zamiast JOIN, jest konieczne do pobierania funkcji bez parametrów.

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
źródło
2
Znajdziesz też oidvectortypesnaprawdę przydatne. Zobacz nową odpowiedź: stackoverflow.com/a/24034604/398670
Craig Ringer
Powyższy kod nie pokaże wszystkich funkcji, potrzebujesz LEFT JOIN zamiast JOIN, aby wyświetlać również funkcje bez parametrów wejściowych.
David
35

Jeśli ktoś jest zainteresowany, oto jakie zapytanie jest wykonywane psqlna 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;

Możesz uzyskać to, co psqldziała dla polecenia z ukośnikiem odwrotnym, uruchamiając psqlz -Eflagą.

jb.
źródło
Właśnie znalazłem twoją odpowiedź i spróbowałem zapytać na Postgres 11.5. Mówi:ERROR: column p.proisagg does not exist
Christiaan Westerbeek
Dzięki za to; dwie najwyżej ocenione odpowiedzi nie pokazały mojej funkcji!
machineghost
29

Jest przydatna funkcja oidvectortypes, która znacznie to ułatwia.

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

Podziękowania dla Leo Hsu i Reginy Obe z Postgres Online za wskazanie oidvectortypes. Pisałem wcześniej podobne funkcje, ale używałem złożonych wyrażeń zagnieżdżonych, których ta funkcja eliminuje potrzebę.

Zobacz powiązaną odpowiedź .


(edytuj w 2016)

Podsumowując typowe opcje raportu:

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

UWAGA : użyj, p.proname||'_'||p.oid AS specific_name aby uzyskać unikalne nazwy, lub DOŁĄCZ do information_schematabel - patrz routinesi parametersprzy odpowiedzi @ RuddZwolinski.


Z funkcji OID (patrz  pg_catalog.pg_proc), a funkcja jest specific_name (zobacz  information_schema.routines) to główne opcje odniesienie do funkcji. Poniżej kilka przydatnych funkcji w raportowaniu i innych kontekstach.

--- --- --- --- ---
--- 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
źródło
To pronamejest nazwa, ale jak zdobyć OID np. używać w pg_catalog.pg_get_function_result(oid))?
Peter Krauss
1
@PeterKrauss oidKolumna pg_proc. To ukryta kolumna.
Craig Ringer
1
Zobacz także stackoverflow.com/a/25388031/161040, aby dowiedzieć się, jak wykluczyć funkcje zależne od rozszerzeń (np. Funkcje z PostGIS).
Simon D
20

Uruchom poniżej zapytanie SQL, aby utworzyć widok, który pokaże wszystkie funkcje:

CREATE OR REPLACE VIEW show_functions AS
    SELECT routine_name FROM information_schema.routines 
        WHERE routine_type='FUNCTION' AND specific_schema='public';
laudarch
źródło
10

Czy dobrym pomysłem jest nazwanie funkcji z aliasami komunikacyjnymi na pierwszych słowach, aby odfiltrować nazwę z LIKE Przykładem ze schematem publicznym w Postgresql 9.4, należy zamienić na jego schemat

SELECT routine_name 
FROM information_schema.routines 
WHERE routine_type='FUNCTION' 
  AND specific_schema='public'
  AND routine_name LIKE 'aliasmyfunctions%';
Alberto Morales Fernández
źródło
4

Przykład:

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
źródło
5
Czym to się różni od odpowiedzi Milena?
a_horse_with_no_name
3
To nie jest zapytanie, to polecenie psqlinterfejsu klienta Postgres. Działa to tylko w programie psqli nie jest technicznie zapytaniem SQL.
GregT
3

Pobierz listę schematu_funkcji i nazwa_funkcji ...


> 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;
szalony
źródło
2

Ta funkcja zwraca wszystkie procedury zdefiniowane przez użytkownika w bieżącej bazie danych.

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
źródło