PostgreSQL: Cara mendaftar semua fungsi tersimpan yang mengakses tabel tertentu

13

Pengantar:

Basis data PostgreSQL dengan beberapa ratus fungsi tersimpan, termasuk usang, tidak digunakan dll.

Masalah

Saya perlu mengetahui semua fungsi tersimpan yang memiliki hubungan dengan tabel X - karena saya ingin mengubah struktur tabel. Beberapa dari mereka mungkin tidak digunakan, jadi saya tidak bisa melakukan itu hanya dengan melihat-lihat kode.

Solusi yang saya miliki ATM adalah menjalankan psql \df+dan output grepping, tapi saya lebih suka solusi seperti database, yaitu dengan menggunakan skema informasi. Ini pasti akan menjadi tugas yang berulang dan saya ingin membuatnya bagus dan bersih.

Ada saran?

Sergey Kudriavtsev
sumber

Jawaban:

18

Tubuh fungsi hanya disimpan sebagai string . Tidak ada daftar objek yang direferensikan. (Itu berbeda dari tampilan, misalnya, di mana tautan sebenarnya ke tabel referensi disimpan.)

Permintaan untuk Postgres 10 atau lebih lama ini menggunakan fungsi informasi katalog sistempg_get_functiondef() untuk merekonstruksi CREATE FUNCTIONskrip untuk fungsi-fungsi yang relevan dan mencari nama tabel dengan ekspresi reguler yang tidak peka huruf besar-kecil:

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

Seharusnya melakukan pekerjaan, tetapi jelas tidak tahan peluru. Ini bisa gagal untuk SQL dinamis di mana nama tabel dihasilkan secara dinamis dan dapat mengembalikan sejumlah positif palsu - terutama jika nama tabel adalah kata yang umum.

Fungsi agregat dan semua fungsi dari skema sistem dikecualikan.

\mdan\M tandai awal dan akhir kata dalam ekspresi reguler.

Katalog sistem pg_procdiubah dalam Postgres 11. proisaggdigantikan oleh prokind, prosedur tersimpan yang sebenarnya ditambahkan. Anda perlu beradaptasi. Terkait:

Erwin Brandstetter
sumber
1
Yap ... itu tidak sepenuhnya kuat, dalam arti bahwa itu tidak akan menemukan EXECUTEekspresi seperti 'mm_'||name_parameter, dan itu tidak akan mengatasi dengan benar dengan nama-nama yang dikutip seperti "my""table""atau dengan case-folding, tetapi itu akan melakukan sebagian besar apa yang diinginkan kebanyakan orang .
Craig Ringer
@CraigRinger: Ya, pertanyaan dinamis dengan EXECUTEhampir tidak mungkin untuk dibahas. Tetapi case-folding dapat ditutup dengan ~*bukan ~- atau pencocokan pola case-insensitive lainnya.
Erwin Brandstetter
Selama operator tidak cukup gila untuk benar-benar membuat tabel bernama "MyTable"dan MyTable, setidaknya ... dan jujur, itu adalah "well, itu mungkin diizinkan tetapi itu tidak pintar" bergerak.
Craig Ringer
Terima kasih atas jawabannya! Saya sebenarnya tidak menggunakan konstruksi nama tabel dinamis di mana saja dan semua nama tabel adalah huruf kecil.
Sergey Kudriavtsev
1

Permintaan ini cukup mudah digunakan:

SELECT proname, proargnames, prosrc FROM pg_proc WHERE prosrc ILIKE '%Text to search%';
joao victor silva de oliveira
sumber