PostgreSQL: Auflisten aller gespeicherten Funktionen, die auf eine bestimmte Tabelle zugreifen

13

Einführung:

PostgreSQL-Datenbank mit mehreren hundert gespeicherten Funktionen, einschließlich veralteter, nicht verwendeter usw.

Problem

Ich muss alle gespeicherten Funktionen herausfinden, die eine Beziehung zur Tabelle X haben - da ich die Tabellenstruktur ändern möchte. Einige von ihnen werden möglicherweise nicht verwendet, daher kann ich das nicht einfach durch Durchsuchen des Codes tun.

Die Lösung, die ich am Geldautomaten habe, besteht darin, psql \df+und Grepping-Ausgabe auszuführen, aber ich würde eine datenbankähnlichere Lösung bevorzugen, dh die Verwendung eines Informationsschemas. Dies wird definitiv eine sich wiederholende Aufgabe sein und ich würde es gerne schön sauber haben.

Irgendwelche Vorschläge?

Sergey Kudriavtsev
quelle

Antworten:

18

Der Hauptteil einer Funktion wird nur als Zeichenfolge gespeichert . Es gibt keine Liste der referenzierten Objekte. (Dies unterscheidet sich beispielsweise von Ansichten, in denen tatsächliche Links zu referenzierten Tabellen gespeichert werden.)

Diese Abfrage für Postgres 10 oder älter verwendet die Systemkataloginformationsfunktion,pg_get_functiondef() um das CREATE FUNCTIONSkript für relevante Funktionen zu rekonstruieren und nach dem Tabellennamen mit einem regulären Ausdruck ohne Berücksichtigung der Groß- und Kleinschreibung zu suchen:

SELECT n.nspname AS schema_name
     , p.proname AS function_name
     , pg_get_function_arguments(p.oid) AS args
     , pg_get_functiondef(p.oid) AS func_def
FROM   pg_proc p
JOIN   pg_namespace n ON n.oid = p.pronamespace
WHERE  NOT p.proisagg
AND    n.nspname NOT LIKE 'pg_%'
AND    n.nspname <> 'information_schema'
AND    pg_get_functiondef(p.oid) ~* '\mbig\M';

Es sollte den Job machen, aber es ist offensichtlich nicht kugelsicher. Es kann für dynamisches SQL fehlschlagen, bei dem der Tabellenname dynamisch generiert wird, und es kann eine beliebige Anzahl von Fehlalarmen zurückgeben - insbesondere, wenn der Tabellenname ein gebräuchliches Wort ist.

Aggregierte Funktionen und alle Funktionen aus Systemschemata sind ausgeschlossen.

\mund\M markieren Sie den Anfang und das Ende eines Wortes im regulären Ausdruck.

Der pg_procin Postgres 11 geänderte Systemkatalog proisaggwurde durch prokindechte gespeicherte Prozeduren ersetzt. Sie müssen sich anpassen. Verbunden:

Erwin Brandstetter
quelle
1
Ja ... es ist nicht ganz robust, in dem Sinne, dass es keine EXECUTEAusdrücke wie findet 'mm_'||name_parameter, und es wird nicht richtig mit zitierten Namen wie "my""table""oder mit Groß- und Kleinschreibung umgehen , aber es wird das meiste tun, was die meisten Leute wollen .
Craig Ringer
@CraigRinger: Ja, dynamische Abfragen mit EXECUTEsind fast unmöglich zu behandeln. Das Falten ~*von ~Groß- und Kleinschreibung kann jedoch anstelle von - oder einer anderen Musteranpassung ohne Berücksichtigung der Groß- und Kleinschreibung abgedeckt werden .
Erwin Brandstetter
Solange der Operator nicht verrückt genug ist, um tatsächlich benannte Tabellen zu erstellen, "MyTable"und MyTablezumindest ... und ehrlich gesagt, ist das ein "gut, das ist vielleicht erlaubt, aber es ist nicht klug" -Zug.
Craig Ringer
Danke für die Antwort! Ich verwende eigentlich nirgendwo eine dynamische Tabellennamenkonstruktion und alle Tabellennamen sind Kleinbuchstaben.
Sergey Kudriavtsev
1

Diese Abfrage ist ziemlich einfach zu verwenden:

SELECT proname, proargnames, prosrc FROM pg_proc WHERE prosrc ILIKE '%Text to search%';
Joao Victor Silva de Olivira
quelle