Fungsi untuk mendokumentasikan database PostgreSQL. Bagian tiga

Ini adalah bagian ketiga dari artikel yang menjelaskan fungsi yang ditentukan pengguna untuk bekerja dengan direktori sistem: pg_class, pg_attribute, pg_constraints, dll.

Bagian artikel ini membahas fungsi yang mengembalikan karakteristik urutan, tabel yang diwarisi , dan karakteristik khusus atribut tabel .

Lihat juga
Fungsi untuk mendokumentasikan database PostgreSQL. Bagian satu ;
Fungsi untuk mendokumentasikan database PostgreSQL. Bagian dua ;
Fungsi untuk mendokumentasikan database PostgreSQL. Akhir (bagian empat) .

Paruh pertama artikel memberikan komentar tentang implementasi fungsi. Yang kedua adalah kode sumber fungsi. Bagi pembaca yang hanya tertarik pada teks sumber, kami sarankan segera melanjutkan ke Lampiran .

Struktur fungsi yang mengembalikan daftar karakteristik urutan tabel



Fig. 2. Fungsi yang bergantung pada fungsi admtf_Table_Sequences

Tabel 11. Tujuan fungsi.

Tidak.JudulJanji temu
1admtf_Sequence_FeaturesFungsi mengembalikan daftar karakteristik urutan tabel.
2admtf_Table_SequencesFungsi mengembalikan daftar urutan tabel database dan karakteristiknya.

Fungsi Admtf_Sequence_Features - daftar karakteristik urutan basis data


Fungsi admtf_Sequence_Features mengembalikan daftar karakteristik SEQUENCE database. Kode sumber dapat dilihat dan diunduh di sini .


Fungsi admtf_Sequence_Features mengembalikan daftar karakteristik urutan basis data ( SEQUENCE )

.

Sebagai parameter, fungsi mengambil nama urutan ( a_SequenceName ) dan nama skema tempat urutan dibuat ( a_SchemaName ).


Perlunya fungsi admtf_Sequence_Features muncul karena karakteristik utama dari urutan sebenarnya disimpan dalam tabel yang namanya cocok dengan nama urutan, dan data diekstraksi darinya menggunakan pernyataan SELECT . Dalam hal ini, nama urutan, nama skema, dan komentar untuk urutan disimpan dalam direktori pg_class , pg_namespace, dan pg_description .


SELECT * FROM kr_road_network_vertices_pgr_id_seq; 

Komentar 6


PostgreSQL 10 memisahkan karakteristik urutan dan karakteristik statusnya. Untuk ini, direktori pg_afterence dengan karakteristik urutan telah diperkenalkan, berisi nilai awal (nilai start_value ), kenaikan ( increment_by ) dan nilai maksimum (nilai max_value ) dari urutan. Nilai terakhir yang dikembalikan oleh urutan ( last_value ) ditinggalkan di "tabel" dengan nama urutan.

Akhir dari komentar itu.


Presentasi dari setiap urutan sebagai analog dari tabel, saya pikir, ditentukan oleh kebutuhan untuk menyimpan nilai urutan yang terakhir digunakan ( last_value ), yang merupakan karakteristik dari keadaan urutan, tetapi bukan urutan itu sendiri.


Entri urutan dalam direktori pg_class berbeda dari entri tabel dengan nilai tipe relasi (relkind = 'S' ).


Untuk mengekstraksi karakteristik urutan arbitrer, Anda harus menggunakan SQL dinamis.


 EXECUTE 'SELECT last_value,start_value,increment_by,max_value FROM '|| LOWER(a_SchemaName)||'.'||LOWER(a_SequenceName) INTO v_SequenceLastValue,v_SequenceStartValue, v_SequenceIncrementBy,v_SequenceMaxValue ; 


Tabel 12. Hasil dari menjalankan fungsi admtf_Sequence_Features ('publik', 'kr_road_network_vertices_pgr_id_seq').

JudulKomentarSaat iniMulaiPenambahanAkhirnya
kr_road_network
_vertices_pgr_id
_seq
Urutan138023119223372036854775807

Function admtf_Table_Sequences daftar urutan tabel database dan karakteristiknya


Fungsi admtf_Table_Sequences mengembalikan daftar urutan ( SEQUENCE ) dari tabel database yang menghasilkan nilai bidangnya dan karakteristik dari urutan ini. Kode sumber dapat dilihat dan diunduh di sini , dan ini adalah versi dari fungsi yang tidak menggunakan kursor .


Sebagai parameter, fungsi mengambil nama tabel sumber ( a_TableName ) dan nama skema di mana tabel dibuat (

a_SchemaName

)

kode sumber operator pada gambar
 SELECT pseq.relname AS SequenceName,snsp.nspname AS SequenceSchemaName, COALESCE(dsc.description,',    ' ||da.attname) AS SequenceDescription, d.depType AS DependcyType,da.attname AS AttributeName FROM pg_depend d INNER JOIN pg_class pseq ON d.objid = pseq.oid INNER JOIN pg_namespace snsp ON pseq.relnamespace=snsp.oid LEFT OUTER JOIN pg_Description dsc ON pseq.oid=dsc.objoid AND dsc.objsubid=0 INNER JOIN pg_class tbl ON d.refobjid = tbl.oid INNER JOIN pg_namespace nsp ON tbl.relnamespace=nsp.oid INNER JOIN pg_attribute da ON da.attrelid= d.refobjid AND da.attnum= d.refobjsubid WHERE LOWER(nsp.nspname)=LOWER(a_SchemaName) AND LOWER(tbl.relname)=LOWER(a_TableOID) AND tbl.relkind = 'r' AND pseq.relkind = 'S' ORDER BY pseq.relname; 


Deskripsi urutan tunggal adalah kombinasi dari catatan di pg_class yang menggambarkannya sebagai hubungan fisik dan tabel kondisional dengan nama urutan yang berisi data tentang karakteristik spesifik dari urutan tersebut.


Informasi tentang hubungan antara urutan dan tabel sumber disimpan di direktori sistem pg_depend .



Tabel 13. Atribut direktori pg_depend diperlukan untuk mengimplementasikan fungsi.
JudulDeskripsi
keberatanOID urutan dalam direktori pg_class
objsubidBidang ini mengandung nol
refobjidOID dari tabel di bidang yang urutannya digunakan
refobjsubidNomor atribut tabel yang nilainya diisi menggunakan urutan

Selain itu, fungsi mengakses data katalog pg_namespace dan pg_description untuk mengekstrak diagram dan komentar dari urutan dan tabel sumber.


Untuk menentukan atribut tabel yang nilainya diisi menggunakan urutan, fungsi mengakses direktori pg_attribute dalam kondisi: attrelid = refobjid AND attnum = refobjsubid . (Dalam kondisi ini, nama-nama atribut direktori pg_depend diindikasikan di sebelah kanan tanda sama dengan).


Karakteristik khusus dari urutan tabel diambil dalam satu lingkaran dengan memanggil admtf_Sequence_Features . Siklus digunakan karena lebih dari satu urutan dapat ditugaskan untuk mengisi bidang tabel.


Tabel 14. Hasil menjalankan fungsi admtf_Table_Sequences ('publik', 'kr_road_network_vertices_pgr').

JudulKomentarMulaiPenambahanAkhirnyaLapangan
kr_road_network
_vertices_pgr_id
_seq
Urutan menghasilkan nilai-nilai bidang id119223372036854775807id

Versi tanpa kursor


Dalam lingkungan PostgreSQL yang versinya kurang dari 10, kemungkinan besar tidak mungkin untuk mengimplementasikan fungsi admtf_Table_Sequences tanpa menggunakan kursor.
Tetapi pemilik beruntung versi 10 dapat melakukannya tanpa kursor, karena mereka memiliki direktori pg_afterence yang mereka miliki. Dalam hal ini, semua karakteristik urutan dapat diambil dengan pernyataan SELECT tunggal.


Dalam implementasi fungsi yang diberikan, menggunakan fungsi jendela RANK () LEBIH (PARTISI DENGAN pseq.relname) , nomor urut urutan yang digunakan untuk mengisi tabel sumber dihitung.



kode sumber operator pada gambar
 SELECT RANK() OVER (PARTITION BY pseq.relname) AS SequenceNo, pseq.relname AS SequenceName,snsp.nspname AS SequenceSchemaName, COALESCE(dsc.description,',    ' ||da.attname) AS SequenceDescription, seq.seqstart AS SequenceStartValue,seq.seqincrement AS SequenceIncrementBy, seq.seqmax AS SequenceMaxValue, d.depType AS DependcyType,da.attname AS AttributeName FROM pg_depend d INNER JOIN pg_class pseq ON d.objid = pseq.oid INNER JOIN pg_sequence seq ON seq.seqrelid= pseq.oid INNER JOIN pg_namespace snsp ON pseq.relnamespace=snsp.oid LEFT OUTER JOIN pg_Description dsc ON pseq.oid=dsc.objoid AND dsc.objsubid=0 INNER JOIN pg_class tbl ON d.refobjid = tbl.oid INNER JOIN pg_namespace nsp ON tbl.relnamespace=nsp.oid INNER JOIN pg_attribute da ON da.attrelid= d.refobjid AND da.attnum= d.refobjsubid WHERE LOWER(nsp.nspname)=LOWER(a_SchemaName) AND LOWER(tbl.relname)=LOWER(a_TableOID) AND tbl.relkind = 'r' AND pseq.relkind = 'S' ORDER BY pseq.relname; 


Komentar 7

.

Versi fungsi ini tidak mengembalikan nilai terakhir yang dihasilkan oleh urutan ( last_value ).

Akhir dari komentar itu.


Fungsi Admtf_Table_InheritanceChildrens - daftar karakteristik tabel yang diwarisi


Fungsi admtf_Table_InheritanceChildrens mengembalikan daftar karakteristik tabel yang diwarisi ( INHERITS ) dari tabel database. Kode sumber dapat dilihat dan diunduh di sini .


Sebagai parameter, fungsi tersebut mengambil nama tabel sumber ( a_TableName ) dan nama skema tempat tabel dibuat ( a_SchemaName ).


Deskripsi tabel legacy tunggal ada di entri di pg_class . Tetapi untuk mencari tabel yang diwarisi dengan nama tabel sumber, Anda harus menggunakan katalog sistem pg_depend .


Tabel 15. Atribut direktori pg_depend diperlukan untuk mengimplementasikan fungsi.
JudulDeskripsi
keberatanOID dari tabel yang diwarisi dalam direktori pg_class
refobjidOID dari tabel sumber


kode sumber operator pada gambar
 SELECT rtbl.relname,rnspc.nspname,rdsc.description,rtbl.relnatts::INTEGER, rtbl.relchecks::INTEGER, rtbl.relhaspkey,rtbl.relhasindex,rtbl.relhassubclass, rtbl.reltuples::INTEGER FROM pg_class tbl INNER JOIN pg_namespace nspc ON tbl.relnamespace = nspc.oid LEFT OUTER JOIN pg_Description dsc ON tbl.oid=dsc.objoid AND dsc.objsubid=0 INNER JOIN pg_depend dp ON tbl.oid=dp.refobjid INNER JOIN pg_class rtbl ON rtbl.OID=dp.objid INNER JOIN pg_namespace rnspc ON rtbl.relnamespace = rnspc.oid LEFT OUTER JOIN pg_Description rdsc ON rtbl.oid=rdsc.objoid AND rdsc.objsubid=0 WHERE LOWER(nspc.nspname)=LOWER(a_SchemaName) AND LOWER(tbl.relname)=LOWER(a_TableOID) AND tbl.relkind = 'r' AND rtbl.relkind = 'r' ORDER BY rtbl.relname; 


Selain itu, fungsi mengakses data direktori pg_namespace dan pg_description untuk mengekstrak skema dan komentar untuk kedua tabel yang diwarisi dan sumber.


Tabel 16. Hasil dari mengeksekusi fungsi admtf_Table_InheritanceChildrens ('publik', 'np_house').

JudulKomentarAtribut? kunci utama? indeks? keturunanJumlah catatan
np_house 04201 000000Rumah di pemukiman (Kabupaten Achinsky)15fff5651
np_house 4208 000 000Rumah di pemukiman (distrik Bogotolsky)15fff4314

Jumlah catatan dalam tabel yang dihasilkan dipilih dari atribut reltuple dari direktori pg_class. Dan meskipun nilai ini sering sama persis dengan jumlah entri aktual dalam tabel, itu masih merupakan nilai estimasi. Jadi, Anda mungkin ingin mendapatkan nilai yang tepat sebagai hasilnya. Misalnya, seperti yang ditunjukkan pada gambar.


 EXECUTE 'SELECT COUNT(*) FROM '||LOWER(a_SchemaName)||'.'||LOWER(a_TableName) INTO v_TableNumberOfRowCalc; 

Tetapi, pertama, untuk memenuhi pernyataan ini dalam teks, fungsi admtf_Table_InheritanceChildrens harus menggunakan kursor.


Kedua, saya ingin fungsi untuk menampilkan estimasi jumlah dan jumlah entri tabel.


Oleh karena itu, fungsi tersebut memiliki parameter opsional lain - mode memperoleh jumlah entri tabel ( a_Mode ), yang mengambil nilai "taksiran" ( taksiran ) atau "tepat" ( persis ).



Selain itu, fungsi admfn_Table_RowCount telah dibuat , yang mengembalikan jumlah entri tabel yang tepat, dan atribut reltuple diganti dalam daftar pengembalian SELECT dengan konstruksi berikut.



kode sumber operator pada gambar
 CASE WHEN a_Mode = 'exactly' THEN admfn_Table_RowCount(rnspc.nspname,rtbl.relname) ELSE reltuples END 


Akibatnya, fungsi mengembalikan nilai estimasi indikator "jumlah entri tabel" jika parameter a_Mode tidak menentukan persyaratan untuk mengembalikan nilai yang tepat.


Struktur fungsi yang mengembalikan daftar karakteristik atribut tabel



Fig. 3. Fungsi yang admtf_Attribute_Features Panggilan

versi teks dari tabel pada gambar
Tabel 17. Tujuan fungsi.

Tidak.JudulJanji temu
1admtf_Attribute_PKFeaturesFungsi mengembalikan atribut keberadaan atribut di kunci utama (PRIMARY KEY), serta beberapa karakteristiknya sebagai bagian dari kunci ini.
2admtf_Attribute_FKFeaturesFungsi mengembalikan atribut keberadaan atribut di kunci asing (KUNCI ASING), serta beberapa karakteristiknya sebagai bagian dari kunci ini.
3admtf_Attribute_FeaturesFungsi mengembalikan daftar karakteristik atribut tabel.


Function admtf_Attribute_PKFeatures - - apakah atribut ada di kunci utama



Fungsi admtf_Attribute_PKFeatures mengembalikan tanda kehadiran atribut tabel di primary key (PRIMARY KEY) dari tabel, dan jika ada, berapakah nomor seri di kunci ini, karena primary key dapat berupa komposit.
Kode sumber dapat dilihat dan diunduh di sini .


Sebagai parameter, fungsi tersebut mengambil OID dari tabel sumber ( a_TableOID ) dan nomor seri dari atribut yang diinginkan di dalamnya ( a_AttributeNo ).


Fungsi ini mengekstrak data yang diperlukan dari entri direktori pg_constraint yang berisi batasan (CONSTRAINT) dari tabel sumber, termasuk batasan kunci primer. OID dari tabel yang diinginkan disimpan dalam bidang conrelid , deskripsi kunci utama disimpan dalam catatan di mana bidang contype berisi nilai '' p '

.
 SELECT INTO v_PKAttributeList,rs_isAttributePK conkey,ARRAY[a_AttributeNo]<@conkey FROM pg_constraint c WHERE c.contype='p' AND c.conrelid=a_TableOID; 

Bidang conkey , yang ditemukan dengan cara ini, berisi array nomor atribut yang membentuk kunci utama. Oleh karena itu, untuk memeriksa keberadaan atribut sumber di kunci utama, cukup untuk menghitung ekspresi logis ARRAY [a_AttributeNo] <@ conkey .


Jika atribut hadir di kunci utama, maka nomor urutnya dihitung dalam loop.


Function admtf_Attribute_FKFeatures - apakah atribut ada di kunci asing



Fungsi admtf_Attribute_FKFeatures mengembalikan tanda kehadiran atribut tabel dalam satu atau lebih kunci asing (KUNCI LUAR NEGERI) dari tabel, dan jika ada, berapa nomor urut dalam kunci ini, karena kunci asing dapat berupa komposit.

Kode sumber dapat dilihat dan diunduh di sini .


Sebagai parameter, fungsi tersebut mengambil OID dari tabel sumber ( a_TableOID ) dan nomor seri dari atribut yang diinginkan di dalamnya ( a_AttributeNo ).


Fungsi mengambil data yang diperlukan dari entri direktori pg_constraint yang berisi CONSTRAINT dari tabel sumber, termasuk, tetapi tidak terbatas pada, batasan kunci asing. OID dari tabel yang diinginkan disimpan dalam bidang conrelid , deskripsi kunci utama disimpan dalam catatan di mana bidang contype berisi nilai '' f '

.
 SELECT * FROM pg_constraint c WHERE c.contype='f ' AND c.conrelid=a_TableOID AND ARRAY[a_AttributeNo]<@conkey ORDER BY c.oid; 

Bidang conkey , yang ditemukan dengan cara ini, berisi array nomor atribut yang membentuk kunci asing. Oleh karena itu, untuk memeriksa keberadaan atribut sumber di kunci asing, cukup untuk menghitung ekspresi logis ARRAY [a_AttributeNo] <@ conkey .


Jika atribut hadir di kunci asing, maka dalam loop sebuah array nomor urutnya terbentuk di kunci asing yang mengandungnya. Selain itu, dua array lagi dibentuk dari nama-nama tabel dan atributnya, yang dirujuk oleh atribut sumber dalam kunci asing yang mengandungnya.


Nama tabel diambil dari entri direktori pg_class dengan pengidentifikasi (OID) yang diambil dari bidang yang tidak sesuai dari entri kunci asing.


Untuk mendapatkan nama atribut dari tabel eksternal, gunakan array nomor seri dari bidang

confkey

(itu berbeda dari array di atas dengan huruf " f " dalam nama). Nomor seri atribut tabel eksternal yang terkait dengan atribut eksternal diekstraksi dari array ini. Dengan nomor seri ini atribut dari tabel eksternal dan OID-nya, yang terletak di direktori pg_attribute ada entri untuk deskripsi atribut dan namanya diambil.

Fungsi Admtf_Attribute_Features - daftar karakteristik atribut tabel


Fungsi admtf_Attribute_Features mengembalikan daftar karakteristik atribut tabel berikut. Kode sumber dapat dilihat dan diunduh di sini .



Versi teks dari tabel pada gambar
Tidak.JudulJenisJanji temu
1AttributeNamenamaNama atribut sumber.
2UserTypeNameVARCHAR (256)Jenis atribut sumber khusus
3Ketikkan namaVARCHAR (256)Tipe dasar atribut sumber
4isNotNULLBOOLEAN? Validitas Null
5isAttributePKBOOLEAN? partisipasi dalam PK
6KolomPKTidakKECILAtribut nomor seri dalam PK
7DeskripsiTEKSMengomentari atribut sumber
8isAttributeFKBOOLEAN? partisipasi di FK
9FKeyNamenama []Array nama tabel kendala di mana kunci asing didefinisikan
10KolomFKTidakKECIL []Array nomor urut atribut dalam kunci asing tabel
11Nama FKTablenama []Array tabel yang dirujuk oleh kunci asing
12FKTableColumnNamenama []Array nama atribut dalam tabel eksternal yang sesuai dengan atribut sumber


Sebagai parameter, fungsi tersebut mengambil OID dari tabel sumber ( a_TableOID ) dan nomor seri dari atribut yang diinginkan di dalamnya ( a_AttributeNo ).
Nilai-nilai bidang AttributeName dan isNotNULL diambil dari entri direktori pg_attribute yang sesuai dengan nilai-nilai parameter input.


 SELECT attr.attname, attr.attnotnull FROM pg_attribute attr WHERE attr.attrelid =a_TableOID AND attr.attnum=a_AttributeNo; SELECT rs_isAttributePK,rs_ColumnPKNo FROM admtf_Attribute_PKFeatures (a_TableOID,a_AttributeNo); SELECT rs_isAttributeFK,rs_FKeyName,rs_ColumnFKNo, rs_FKTableName,rs_FKTableColumnName FROM admtf_Attribute_FKFeatures (a_TableOID,a_AttributeNo); 

Nilai bidang isAttributePK dan ColumnPKNo dikembalikan oleh fungsi admtf_Attribute_PKFeatures .


Nilai dari isAttributeFK , FKeyName , ColumnFKNo , FKTableName , FKTableColumnName bidang dikembalikan oleh fungsi admtf_Attribute_FKFeatures .


Panggilan ke admtf_Attribute_Features ((PILIH OID DARI pg_class WHERE relname = 'street'), 2 :: SMALLINT) akan menghasilkan hasil sebagai berikut.


Tabel 18. Hasil menjalankan fungsi admtf_Attribute_Features
AttributeNameUserTypeNameKetikkan namaisNotNULLisAttributePKKolomPKTidak
localityidlocalityidbilangan bulatbilangan bulatbilangan bulatbilangan bulat


DeskripsiisAttributeFKFKeyNameKolomFKTidakNama FKTableFKTableColumnName
ID komunitast{fk_street_locality}{2}{lokalitas}{localityid}

LAMPIRAN 1. Skrip


Membuat Fungsi admtf_Sequence_Features


Komentar pada kode sumber fungsi dapat ditemukan di sini.
kode fungsi
 BEGIN TRANSACTION; DROP FUNCTION IF EXISTS admtf_Sequence_Features (a_SchemaName NAME,a_SequenceName NAME); /****************************************************************************/ /*     ,   */ /****************************************************************************/ CREATE OR REPLACE FUNCTION admtf_Sequence_Features (a_SchemaName NAME default 'public', /*     */ a_SequenceName NAME default NULL /*   */ ) RETURNS TABLE (rs_SequenceName NAME,rs_SequenceDescription TEXT,rs_NumberOfAttribute INTEGER,rs_SequenceLastValue BIGINT, rs_SequenceStartValue BIGINT,rs_SequenceIncrementBy BIGINT,rs_SequenceMaxValue BIGINT) AS $BODY$ DECLARE c_SequenceKind CONSTANT CHAR:='S'; v_SequenceOID OID; /*   */ v_SequenceName NAME; /*   */ v_SequenceDescription TEXT; /*   */ v_SequenceStartValue BIGINT; /*    */ v_SequenceIncrementBy BIGINT; /*   */ v_SequenceMaxValue BIGINT; /*    */ v_SequenceLastValue BIGINT; /*    */ v_SequenceNumberOfRowCalc INTEGER; /*     */ --************************************************************************ BEGIN SELECT INTO rs_SequenceName,rs_SequenceDescription,rs_NumberOfAttribute tbl.relname, COALESCE(dsc.description,'') AS r_SequenceDescription, tbl.relnatts::INTEGER,tbl.relchecks::INTEGER,tbl.relhaspkey, tbl.relhasindex,tbl.relhassubclass,tbl.reltuples::INTEGER FROM pg_class tbl INNER JOIN pg_namespace nspc ON tbl.relnamespace = nspc.oid LEFT OUTER JOIN pg_Description dsc ON tbl.oid=dsc.objoid AND dsc.objsubid=0 WHERE nspc.nspname=LOWER(a_SchemaName) AND tbl.relkind=c_SequenceKind AND tbl.relname =LOWER(a_SequenceName); IF FOUND THEN EXECUTE 'SELECT last_value,start_value,increment_by,max_value FROM '||LOWER(a_SchemaName)||'.'||LOWER(a_SequenceName) INTO v_SequenceLastValue,v_SequenceStartValue, v_SequenceIncrementBy,v_SequenceMaxValue ; RETURN QUERY SELECT rs_SequenceName,rs_SequenceDescription, rs_NumberOfAttribute,v_SequenceLastValue, v_SequenceStartValue,v_SequenceIncrementBy, v_SequenceMaxValue; END IF; RETURN; END $BODY$ LANGUAGE plpgsql; COMMENT ON FUNCTION admtf_Sequence_Features(a_SchemaName NAME,a_SequenceName NAME) IS '    ,  '; --ROLLBACK TRANSACTION; COMMIT TRANSACTION; BEGIN TRANSACTION; DROP FUNCTION IF EXISTS admtf_Sequence_Features (a_SchemaName VARCHAR(256),a_SequenceName VARCHAR(256)); /****************************************************************************/ /*     ,   */ /****************************************************************************/ CREATE OR REPLACE FUNCTION admtf_Sequence_Features (a_SchemaName VARCHAR(256) default 'public', /*     */ a_SequenceName VARCHAR(256) default NULL /*   */ ) RETURNS TABLE (rs_SequenceName VARCHAR(256),rs_SequenceDescription TEXT, rs_NumberOfAttribute INTEGER,rs_SequenceLastValue BIGINT, rs_SequenceStartValue BIGINT,rs_SequenceIncrementBy BIGINT, rs_SequenceMaxValue BIGINT) AS $BODY$ DECLARE c_SequenceKind CONSTANT CHAR:='S'; --******************************************************** BEGIN RETURN QUERY SELECT sf.rs_SequenceName::VARCHAR(256), sf.rs_SequenceDescription::TEXT, sf.rs_NumberOfAttribute::INTEGER, sf.rs_SequenceLastValue::BIGINT, sf.rs_SequenceStartValue::BIGINT, sf.rs_SequenceIncrementBy::BIGINT, sf.rs_SequenceMaxValue::BIGINT FROM admtf_Sequence_Features(a_SchemaName::NAME,a_SequenceName::NAME) sf; END $BODY$ LANGUAGE plpgsql; COMMENT ON FUNCTION admtf_Sequence_Features(a_SchemaName VARCHAR(256),a_SequenceName VARCHAR(256)) IS '    ,  '; --ROLLBACK TRANSACTION; COMMIT TRANSACTION; SELECT * FROM admtf_Sequence_Features('public'::VARCHAR(255),'k_dorogi_dijkstra_seq_seq'::VARCHAR(255)); SELECT * FROM admtf_Sequence_Features('public'::NAME,'kr_road_network_vertices_pgr_id_seq'::NAME); 



Membuat Fungsi admtf_Table_Sequences


Komentar pada kode sumber fungsi dapat ditemukan di sini.
kode fungsi
 BEGIN TRANSACTION; DROP FUNCTION IF EXISTS admtf_Table_Sequences (a_SchemaName NAME, a_TableName NAME); /*********************************************************************/ /*    ,     */ /*********************************************************************/ CREATE OR REPLACE FUNCTION admtf_Table_Sequences (a_SchemaName NAME default 'public', /*     */ a_TableName NAME default NULL /*   */ ) RETURNS TABLE (r_SequenceNumber SMALLINT,r_SequenceName NAME, r_SequenceSchemaName NAME,r_SequenceDescription TEXT, r_SequenceStartValue BIGINT,r_SequenceIncrementBy BIGINT, r_SequenceMaxValue BIGINT,r_DependType NAME, r_RefTableName NAME,r_RefTableSchemaName NAME, r_RefAttributeName NAME) AS $BODY$ DECLARE v_TableOID INTEGER;/* OID */ v_Sequence RECORD;/*   */ v_SequenceOID INTEGER;/* OID */ v_SequenceName NAME; /*   */ v_SequenceSchemaName NAME; /*    */ v_SequenceDescription TEXT; /*   */ v_SequenceStartValue BIGINT; /*    */ v_SequenceIncrementBy BIGINT; /*   */ v_SequenceMaxValue BIGINT; /*    */ v_DependcyType NAME; /*     */ /*    */ v_AttributeName NAME; /*  */ v_SequenceNumber SMALLINT; /*   */ c_Delimiter CONSTANT VARCHAR(2):=','; --********************************************************************* BEGIN v_SequenceNumber:=0; FOR v_Sequence IN SELECT pseq.relname AS SequenceName, snsp.nspname AS SequenceSchemaName, COALESCE(dsc.description,',    '||da.attname) AS SequenceDescription, d.depType AS DependcyType,da.attname AS AttributeName FROM pg_depend d INNER JOIN pg_class pseq ON d.objid = pseq.oid INNER JOIN pg_namespace snsp ON pseq.relnamespace=snsp.oid LEFT OUTER JOIN pg_Description dsc ON pseq.oid=dsc.objoid AND dsc.objsubid=0 INNER JOIN pg_class tbl ON d.refobjid = tbl.oid INNER JOIN pg_namespace nsp ON tbl.relnamespace=nsp.oid INNER JOIN pg_attribute da ON da.attrelid= d.refobjid AND d.refobjsubid=da.attnum WHERE tbl.relkind = 'r' AND pseq.relkind = 'S' AND LOWER(nsp.nspname)=LOWER(a_SchemaName) AND LOWER(tbl.relname)=LOWER(a_TableName) ORDER BY pseq.relname LOOP v_SequenceNumber:=v_SequenceNumber+1; v_SequenceName:=v_Sequence.SequenceName; v_SequenceSchemaName:=v_Sequence.SequenceSchemaName; v_DependcyType:=v_Sequence.DependcyType; v_AttributeName:=v_Sequence.AttributeName; v_SequenceDescription:=v_Sequence.SequenceDescription; SELECT INTO v_SequenceStartValue,v_SequenceIncrementBy, v_SequenceMaxValue rs_SequenceStartValue,rs_SequenceIncrementBy, rs_SequenceMaxValue FROM admtf_Sequence_Features(v_SequenceSchemaName,v_SequenceName); RETURN QUERY SELECT v_SequenceNumber,v_SequenceName, v_SequenceSchemaName,v_SequenceDescription, v_SequenceStartValue,v_SequenceIncrementBy, v_SequenceMaxValue,v_DependcyType, a_TableName,a_SchemaName,v_AttributeName; END LOOP; RETURN; END $BODY$ LANGUAGE plpgsql; COMMENT ON FUNCTION admtf_Table_Sequences(a_SchemaName NAME, a_TableName NAME) IS '  ,    '; --ROLLBACK TRANSACTION; COMMIT TRANSACTION; BEGIN TRANSACTION; DROP FUNCTION IF EXISTS admtf_Table_Sequences (a_SchemaName VARCHAR(256), a_TableName VARCHAR(256)); /**********************************************************************/ /*    ,     */ /**********************************************************************/ CREATE OR REPLACE FUNCTION admtf_Table_Sequences (a_SchemaName VARCHAR(256) default 'public', /*     */ a_TableName VARCHAR(256) default NULL /*   */ ) RETURNS TABLE (r_SequenceNumber SMALLINT,r_SequenceName VARCHAR(256), r_SequenceSchemaName VARCHAR(256),r_SequenceDescription TEXT, r_SequenceStartValue BIGINT,r_SequenceIncrementBy BIGINT, r_SequenceMaxValue BIGINT,r_DependType VARCHAR(256), r_RefTableName VARCHAR(256),r_RefTableSchemaName VARCHAR(256), r_RefAttributeName VARCHAR(256)) AS $BODY$ DECLARE c_Delimiter CONSTANT VARCHAR(2):=','; --****************************************************** BEGIN RETURN QUERY SELECT ts.r_SequenceNumber::SMALLINT, ts.r_SequenceName::VARCHAR(256), ts.r_SequenceSchemaName::VARCHAR(256) , ts.r_SequenceDescription::TEXT, ts.r_SequenceStartValue::BIGINT, ts.r_SequenceIncrementBy::BIGINT, ts.r_SequenceMaxValue::BIGINT, ts.r_DependType::VARCHAR(256), ts.r_RefTableName::VARCHAR(256), ts.r_RefTableSchemaName::VARCHAR(256), ts.r_RefAttributeName::VARCHAR(256) FROM admtf_Table_Sequences(a_SchemaName::NAME,a_TableName::NAME) ts; END $BODY$ LANGUAGE plpgsql; COMMENT ON FUNCTION admtf_Table_Sequences(a_SchemaName VARCHAR(256), a_TableName VARCHAR(256)) IS '  ,    '; --ROLLBACK TRANSACTION; COMMIT TRANSACTION; SELECT * FROM admtf_Table_Sequences('public'::VARCHAR(255),'kr_road_network_vertices_pgr'::VARCHAR(255)); SELECT * FROM admtf_Table_Sequences('public'::NAME,'kr_road_network_vertices_pgr'::NAME); 


admtf_Table_Sequences (PostgreSQL 10)


.
 BEGIN TRANSACTION; DROP FUNCTION IF EXISTS admtf_Table_Sequences (a_SchemaName NAME, a_TableName NAME); /*********************************************************************/ /*    ,     */ /**********************************************************************/ CREATE OR REPLACE FUNCTION admtf_Table_Sequences (a_SchemaName NAME default 'public', /*     */ a_TableName NAME default NULL /*   */ ) RETURNS TABLE (r_SequenceNumber SMALLINT,r_SequenceName NAME, r_SequenceSchemaName NAME,r_SequenceDescription TEXT, r_SequenceStartValue BIGINT,r_SequenceIncrementBy BIGINT, r_SequenceMaxValue BIGINT,r_DependType NAME, r_RefTableName NAME,r_RefTableSchemaName NAME, r_RefAttributeName NAME) AS $BODY$ DECLARE v_TableOID INTEGER; /* OID */ v_Sequence RECORD; /*   */ v_SequenceOID INTEGER; /* OID */ v_SequenceName NAME; /*   */ v_SequenceSchemaName NAME; /*    */ v_SequenceDescription TEXT; /*   */ v_SequenceStartValue BIGINT; /*    */ v_SequenceIncrementBy BIGINT; /*   */ v_SequenceMaxValue BIGINT; /*    */ v_DependcyType NAME; /*        */ v_AttributeName NAME; /*  */ v_SequenceNumber SMALLINT; /*   */ c_Delimiter CONSTANT VARCHAR(2):=','; --****************************************************************** BEGIN v_SequenceNumber:=0; FOR v_Sequence IN SELECT pseq.relname AS SequenceName, snsp.nspname AS SequenceSchemaName, COALESCE(dsc.description,',    '||da.attname) AS SequenceDescription, d.depType AS DependcyType,da.attname AS AttributeName FROM pg_depend d INNER JOIN pg_class pseq ON d.objid = pseq.oid INNER JOIN pg_namespace snsp ON pseq.relnamespace=snsp.oid LEFT OUTER JOIN pg_Description dsc ON pseq.oid=dsc.objoid AND dsc.objsubid=0 INNER JOIN pg_class tbl ON d.refobjid = tbl.oid INNER JOIN pg_namespace nsp ON tbl.relnamespace=nsp.oid INNER JOIN pg_attribute da ON da.attrelid= d.refobjid ND d.refobjsubid=da.attnum WHERE tbl.relkind = 'r' AND pseq.relkind = 'S' AND LOWER(nsp.nspname)=LOWER(a_SchemaName) AND LOWER(tbl.relname)=LOWER(a_TableName) ORDER BY pseq.relname LOOP v_SequenceNumber:=v_SequenceNumber+1; v_SequenceName:=v_Sequence.SequenceName; v_SequenceSchemaName:=v_Sequence.SequenceSchemaName; v_DependcyType:=v_Sequence.DependcyType; v_AttributeName:=v_Sequence.AttributeName; v_SequenceDescription:=v_Sequence.SequenceDescription; SELECT INTO v_SequenceStartValue,v_SequenceIncrementBy,v_SequenceMaxValue rs_SequenceStartValue,rs_SequenceIncrementBy,rs_SequenceMaxValue FROM admtf_Sequence_Features(v_SequenceSchemaName,v_SequenceName); RETURN QUERY SELECT v_SequenceNumber,v_SequenceName, v_SequenceSchemaName,v_SequenceDescription, v_SequenceStartValue,v_SequenceIncrementBy, v_SequenceMaxValue,v_DependcyType, a_TableName,a_SchemaName,v_AttributeName; END LOOP; RETURN; END $BODY$ LANGUAGE plpgsql; COMMENT ON FUNCTION admtf_Table_Sequences(a_SchemaName NAME, a_TableName NAME) IS '  ,    '; --ROLLBACK TRANSACTION; COMMIT TRANSACTION; BEGIN TRANSACTION; DROP FUNCTION IF EXISTS admtf_Table_Sequences (a_SchemaName VARCHAR(256), a_TableName VARCHAR(256)); /**********************************************************************/ /*    ,     */ /**********************************************************************/ CREATE OR REPLACE FUNCTION admtf_Table_Sequences (a_SchemaName VARCHAR(256) default 'public', /*     */ a_TableName VARCHAR(256) default NULL /*   */ ) RETURNS TABLE (r_SequenceNumber SMALLINT,r_SequenceName VARCHAR(256), r_SequenceSchemaName VARCHAR(256),r_SequenceDescription TEXT, r_SequenceStartValue BIGINT,r_SequenceIncrementBy BIGINT, r_SequenceMaxValue BIGINT,r_DependType VARCHAR(256), r_RefTableName VARCHAR(256),r_RefTableSchemaName VARCHAR(256), r_RefAttributeName VARCHAR(256)) AS $BODY$ DECLARE c_Delimiter CONSTANT VARCHAR(2):=','; --******************************************************* BEGIN RETURN QUERY SELECT ts.r_SequenceNumber::SMALLINT, ts.r_SequenceName::VARCHAR(256), ts.r_SequenceSchemaName::VARCHAR(256), ts.r_SequenceDescription::TEXT, ts.r_SequenceStartValue::BIGINT, ts.r_SequenceIncrementBy::BIGINT, ts.r_SequenceMaxValue::BIGINT, ts.r_DependType::VARCHAR(256), ts.r_RefTableName::VARCHAR(256), ts.r_RefTableSchemaName::VARCHAR(256), ts.r_RefAttributeName::VARCHAR(256) FROM admtf_Table_Sequences(a_SchemaName::NAME,a_TableName::NAME) ts; END $BODY$ LANGUAGE plpgsql; COMMENT ON FUNCTION admtf_Table_Sequences(a_SchemaName VARCHAR(256), a_TableName VARCHAR(256)) IS '  ,    '; --ROLLBACK TRANSACTION; COMMIT TRANSACTION; SELECT * FROM admtf_Table_Sequences('public'::VARCHAR(255), 'kr_road_network_vertices_pgr'::VARCHAR(255)); SELECT * FROM admtf_Table_Sequences('public'::NAME, 'kr_road_network_vertices_pgr'::NAME); 



admfn_Table_RowCount


.
 BEGIN TRANSACTION; DROP FUNCTION IF EXISTS admfn_Table_RowCount (a_SchemaName NAME,a_TableName NAME); /******************************************************/ /*       */ /******************************************************/ CREATE OR REPLACE FUNCTION admfn_Table_RowCount (a_SchemaName NAME default 'public',/*     */ a_TableName NAME default NULL /*   */ ) RETURNS BIGINT AS $BODY$ DECLARE v_TableNumberOfRowCalc BIGINT; /*  */ v_Found BOOLEAN; --*********************************************************** BEGIN IF a_SchemaName ~ E'^[a-z_0-9]+$' AND a_TableName ~ E'^[a-z_0-9]+$' THEN EXECUTE 'SELECT count(*) FROM ' ||a_SchemaName ||'.'|| a_TableName INTO v_TableNumberOfRowCalc; ELSE SELECT INTO v_Found true FROM pg_class tbl INNER JOIN pg_namespace nspc ON tbl.relnamespace = nspc.oid WHERE tbl.relkind='r' AND tbl.relname=a_TableName AND nspc.nspname=a_SchemaName; IF FOUND THEN EXECUTE 'SELECT count(*) FROM ' || CASE WHEN a_SchemaName ~ E'^[a-z_0-9]+$' THEN a_SchemaName ELSE quote_ident(a_SchemaName) END ||'.'|| CASE WHEN a_TableName ~ E'^[a-z_0-9]+$' THEN a_TableName ELSE quote_ident(a_TableName) END INTO v_TableNumberOfRowCalc; ELSE SELECT INTO v_Found true FROM pg_class tbl INNER JOIN pg_namespace nspc ON tbl.relnamespace = nspc.oid WHERE tbl.relkind='r' AND LOWER(tbl.relname)= LOWER(a_TableName) AND nspc.nspname=LOWER(a_SchemaName); IF FOUND THEN EXECUTE 'SELECT count(*) FROM ' || a_SchemaName ||'.'||a_TableName INTO v_TableNumberOfRowCalc; END IF; END IF; END IF; RETURN v_TableNumberOfRowCalc; END $BODY$ LANGUAGE plpgsql; COMMENT ON FUNCTION admfn_Table_RowCount(a_SchemaName NAME,a_TableName NAME) IS '    '; --ROLLBACK TRANSACTION; COMMIT TRANSACTION;BEGIN TRANSACTION; DROP FUNCTION IF EXISTS admfn_Table_RowCount (a_SchemaName VARCHAR(256),a_TableName VARCHAR(256)); /********************************************************************/ /*       */ /********************************************************************/ CREATE OR REPLACE FUNCTION admfn_Table_RowCount (a_SchemaName VARCHAR(256) default 'public',/*     */ a_TableName VARCHAR(256) default NULL /*   */ ) RETURNS BIGINT AS $BODY$ DECLARE v_TableNumberOfRowCalc BIGINT; /*  */ --********************************************************* BEGIN RETURN admfn_Table_RowCount(a_SchemaName::NAME,a_TableName::NAME); END $BODY$ LANGUAGE plpgsql; COMMENT ON FUNCTION admfn_Table_RowCount(a_SchemaName VARCHAR(256),a_TableName VARCHAR(256)) IS '    '; --ROLLBACK TRANSACTION; COMMIT TRANSACTION; SELECt admfn_Table_RowCount('public'::NAME,'Street'::NAME); SELECt admfn_Table_RowCount('public'::VARCHAR(256),'Street'::VARCHAR(256)); 


admtf_Table_InheritanceChildrens


.
 BEGIN TRANSACTION; DROP FUNCTION IF EXISTS admtf_Table_InheritanceChildrens (a_SchemaName NAME,a_TableName NAME,a_Mode VARCHAR(10)); /************************************************************/ /*       */ /************************************************************/ CREATE OR REPLACE FUNCTION admtf_Table_InheritanceChildrens (a_SchemaName NAME default 'public', /*     */ a_TableName NAME default NULL, /*   */ a_Mode VARCHAR(10) default 'estimate' /*     */ ) RETURNS TABLE (rs_TableName NAME,rs_TableDescription TEXT, rs_NumberOfAttribute INTEGER,rs_NumberOfChecks INTEGER, rs_hasPKey BOOLEAN,rs_hasIndex BOOLEAN, rs_hasSubClass BOOLEAN,rs_NumberOfRow INTEGER) AS $BODY$ DECLARE c_TableKind CONSTANT CHAR:='r'; c_ExactlyMode CONSTANT VARCHAR(10):='exactly'; c_EstimateMode CONSTANT VARCHAR(10):='estimate'; v_TableOID OID; /*   */ v_SchemaName NAME; /*    */ v_TableName NAME; /*   */ v_TableDescription TEXT; /*   */ v_TableNumberOfRowCalc INTEGER; /*     */ v_InheritanceRECORD RECORD; /*    */ v_InheritanceOID OID; /*    */ BEGIN RETURN QUERY SELECT rtbl.relname,rdsc.description,rtbl.relnatts::INTEGER, rtbl.relchecks::INTEGER,rtbl.relhaspkey,rtbl.relhasindex, rtbl.relhassubclass, CASE WHEN a_Mode=c_ExactlyMode THEN admfn_Table_RowCount(rnspc.nspname,rtbl.relname)::INTEGER ELSE rtbl.reltuples::INTEGER END FROM pg_class tbl INNER JOIN pg_namespace nspc ON tbl.relnamespace = nspc.oid LEFT OUTER JOIN pg_Description dsc ON tbl.oid=dsc.objoid AND dsc.objsubid=0 INNER JOIN pg_depend dp ON tbl.oid=dp.refobjid INNER JOIN pg_class rtbl ON rtbl.OID=dp.objid INNER JOIN pg_namespace rnspc ON rtbl.relnamespace = rnspc.oid LEFT OUTER JOIN pg_Description rdsc ON rtbl.oid=rdsc.objoid AND rdsc.objsubid=0 WHERE nspc.nspname=LOWER(a_SchemaName) AND tbl.relkind=c_TableKind AND rtbl.relkind=c_TableKind AND tbl.relname =LOWER(a_TableName) ORDER BY rtbl.relname; END $BODY$ LANGUAGE plpgsql; COMMENT ON FUNCTION admtf_Table_InheritanceChildrens(a_SchemaName NAME,a_TableName NAME,a_Mode VARCHAR(10)) IS '    '; --ROLLBACK TRANSACTION; COMMIT TRANSACTION; BEGIN TRANSACTION; DROP FUNCTION IF EXISTS admtf_Table_InheritanceChildrens (a_SchemaName VARCHAR(256),a_TableName VARCHAR(256),a_TableName NAME,a_Mode VARCHAR(10)); /************************************************************************/ /*       */ /************************************************************************/ CREATE OR REPLACE FUNCTION admtf_Table_InheritanceChildrens (a_SchemaName VARCHAR(256) default 'public',/*     */ a_TableName VARCHAR(256) default NULL,/*   */ a_Mode VARCHAR(10) default 'estimate' /*     */ ) RETURNS TABLE (rs_TableName VARCHAR(256),rs_TableDescription TEXT, rs_NumberOfAttribute INTEGER,rs_NumberOfChecks INTEGER, rs_hasPKey BOOLEAN,rs_hasIndex BOOLEAN, rs_hasSubClass BOOLEAN,rs_NumberOfRow INTEGER) AS $BODY$ DECLARE c_TableKind CONSTANT CHAR:='r'; BEGIN RETURN QUERY SELECT tic.rs_TableName::VARCHAR(256),tic.rs_TableDescription::TEXT, tic.rs_NumberOfAttribute::INTEGER,tic.rs_NumberOfChecks::INTEGER, tic.rs_hasPKey::BOOLEAN,tic.rs_hasIndex::BOOLEAN, tic.rs_hasSubClass::BOOLEAN,tic.rs_NumberOfRow::INTEGER FROM admtf_Table_InheritanceChildrens(a_SchemaName::NAME, a_TableName::NAME,a_Mode::VARCHAR(10)) tic; END $BODY$ LANGUAGE plpgsql; COMMENT ON FUNCTION admtf_Table_InheritanceChildrens(a_SchemaName VARCHAR(256),a_TableName VARCHAR(256),a_Mode VARCHAR(10)) IS '    '; --ROLLBACK TRANSACTION; COMMIT TRANSACTION; SELECT * FROM admtf_Table_InheritanceChildrens('public'::NAME,'np_house'::NAME); SELECT * FROM admtf_Table_InheritanceChildrens('public'::VARCHAR(256),'np_house'::VARCHAR(256)); 


admtf_Attribute_PKFeatures


.
 BEGIN TRANSACTION; DROP FUNCTION IF EXISTS admtf_Attribute_PKFeatures (a_TableOID OID,a_AttributeNo SMALLINT); /***************************************************************************/ /*        . */ /*   ,          */ /*   */ /***************************************************************************/ CREATE OR REPLACE FUNCTION admtf_Attribute_PKFeatures (a_TableOID OID, /*   */ a_AttributeNo SMALLINT /*     */ ) RETURNS TABLE (rs_isAttributePK BOOLEAN,rs_PKeyName name,rs_ColumnPKNo SMALLINT) AS $BODY$ DECLARE C_PKAttributeList_NDims CONSTANT INTEGER:=1; /*     */ v_PKAttributeList SMALLINT[]; /*       */ v_PKAttributeIndx INTEGER; /*      */ v_PKAttributeLBound INTEGER; /*      */ v_PKAttributeUBound INTEGER; /*      */ --********************************************************************** BEGIN rs_isAttributePK:=false; rs_ColumnPKNo:=NULL; SELECT INTO rs_PKeyName,v_PKAttributeList,rs_isAttributePK conname,conkey,ARRAY[a_AttributeNo]<@conkey FROM pg_constraint c WHERE c.contype='p' and c.conrelid=a_TableOID; IF FOUND AND rs_isAttributePK THEN --      v_PKAttributeLBound:=array_lower(v_PKAttributeList,C_PKAttributeList_NDims); v_PKAttributeUBound:=array_upper(v_PKAttributeList,C_PKAttributeList_NDims); v_PKAttributeIndx:=v_PKAttributeLBound; WHILE v_PKAttributeIndx <= v_PKAttributeUBound AND a_AttributeNo<>v_PKAttributeList[v_PKAttributeIndx] LOOP v_PKAttributeIndx:=v_PKAttributeIndx+1; END LOOP; IF v_PKAttributeIndx<=v_PKAttributeUBound THEN rs_ColumnPKNo:=v_PKAttributeIndx; END IF; END IF; RETURN QUERY SELECT rs_isAttributePK,rs_PKeyName,rs_ColumnPKNo; END $BODY$ LANGUAGE plpgsql; COMMENT ON FUNCTION admtf_Attribute_PKFeatures(a_TableOID OID,a_AttributeNo SMALLINT) IS '              '; --ROLLBACK TRANSACTION; COMMIT TRANSACTION; SELECT * FROM admtf_Attribute_PKFeatures((SELECT OID FROM pg_class WHERE relname='street'),3::SMALLINT); 


admtf_Attribute_FKFeatures


.
 BEGIN TRANSACTION; DROP FUNCTION IF EXISTS admtf_Attribute_FKFeatures (a_TableOID OID,a_AttributeNo SMALLINT); /****************************************************************************/ /*        . */ /*   ,         */ /*   . */ /****************************************************************************/ /****************************************************************************/ CREATE OR REPLACE FUNCTION admtf_Attribute_FKFeatures (a_TableOID OID, /*   */ a_AttributeNo SMALLINT /*     */ ) RETURNS TABLE (rs_isAttributeFK BOOLEAN,rs_FKeyName name[],rs_ColumnFKNo SMALLINT[],rs_FKTableName name[],rs_FKTableColumnName name[]) AS $BODY$ DECLARE C_FKAttributeList_NDims CONSTANT INTEGER:=1; /*     */ v_FKAttributeList SMALLINT[]; /*       */ v_RefAttributeList SMALLINT[]; /*     , */ /*     */ v_FKAttributeIndx INTEGER; /*      */ v_RefAttributeListIndx INTEGER; /*     , */ /*     */ v_FKAttributeLBound INTEGER; /*      */ v_FKAttributeUBound INTEGER; /*      */ v_FKConstraintIndx INTEGER; /*     */ v_FKeyName name; /*   , */ /*     */ v_FKTableName name; /*  ,     */ v_FKTableColumnName name; /*    , */ /*     */ v_RefAttributeNo SMALLINT; /*     , */ /*     */ v_Constraint pg_constraint%ROWTYPE; /*     */ /*  (CONSTRANT) */ --****************************************************************************************************** BEGIN rs_isAttributeFK:=false; rs_ColumnFKNo:=NULL; v_FKConstraintIndx:=0; FOR v_Constraint IN SELECT * FROM pg_constraint c WHERE c.contype='f' and c.conrelid=a_TableOID AND ARRAY[a_AttributeNo]<@conkey ORDER BY c.oid LOOP v_FKConstraintIndx:=v_FKConstraintIndx+1; rs_isAttributeFK:=true; v_FKeyName:=v_Constraint.conname; v_FKAttributeList:=v_Constraint.conkey; v_RefAttributeList:=v_Constraint.confkey; v_FKAttributeLBound:=array_lower(v_FKAttributeList,C_FKAttributeList_NDims); v_FKAttributeUBound:=array_upper(v_FKAttributeList,C_FKAttributeList_NDims); v_FKAttributeIndx:=v_FKAttributeLBound; WHILE v_FKAttributeIndx <= v_FKAttributeUBound AND a_AttributeNo<>v_FKAttributeList[v_FKAttributeIndx] LOOP v_FKAttributeIndx:=v_FKAttributeIndx+1; END LOOP; rs_FKeyName[v_FKConstraintIndx]:=v_FKeyName; rs_ColumnFKNo[v_FKConstraintIndx]:=v_FKAttributeIndx; SELECT INTO v_FKTableName ftbl.relname FROM pg_class ftbl WHERE ftbl.oid=v_Constraint.confrelid; rs_FKTableName[v_FKConstraintIndx]:=v_FKTableName; v_RefAttributeNo:=v_RefAttributeList[v_FKAttributeIndx]; v_FKTableColumnName:=NULL; SELECT INTO v_FKTableColumnName attname FROM pg_attribute a WHERE a.attrelid=v_Constraint.confrelid AND a.attnum=v_RefAttributeNo; rs_FKTableColumnName[v_FKConstraintIndx]:=v_FKTableColumnName; END LOOP; RETURN QUERY SELECT rs_isAttributeFK,rs_FKeyName,rs_ColumnFKNo, rs_FKTableName,rs_FKTableColumnName; END $BODY$ LANGUAGE plpgsql; COMMENT ON FUNCTION admtf_Attribute_FKFeatures(a_TableOID OID,a_AttributeNo SMALLINT) IS '              '; --ROLLBACK TRANSACTION; COMMIT TRANSACTION; SELECT * FROM admtf_Attribute_FKFeatures((SELECT OID FROM pg_class WHERE relname='street'),4::SMALLINT); 



admtf_Attribute_Features


.
 BEGIN TRANSACTION; DROP FUNCTION IF EXISTS admtf_Attribute_Features (a_TableOID OID,a_AttributeNo SMALLINT); /****************************************************************************/ /*      */ /****************************************************************************/ CREATE OR REPLACE FUNCTION admtf_Attribute_Features (a_TableOID OID, /*   */ a_AttributeNo SMALLINT/*     */ ) RETURNS TABLE (rsa_AttributeName name,rsa_UserTypeName VARCHAR(256),rsa_TypeName VARCHAR(256),rsa_isNotNULL BOOLEAN,rsa_isAttributePK BOOLEAN, rsa_ColumnPKNo SMALLINT,rsa_Description Text,rsa_isAttributeFK BOOLEAN,rsa_FKeyName name[],rsa_ColumnFKNo SMALLINT[],rsa_FKTableName name[],rsa_FKTableColumnName name[]) AS $BODY$ DECLARE v_Return_Error Integer := 0; /*  */ --********************************************************************* BEGIN SELECT INTO rsa_AttributeName,rsa_UserTypeName,rsa_TypeName, rsa_isNotNULL,rsa_Description attr.attname, CASE WHEN COALESCE(typ.typbasetype,0)>0 THEN typ.typname::VARCHAR(100) ELSE ''END AS r_UserTypeName, FORMAT_TYPE(COALESCE(NULLIF(typ.typbasetype,0),typ.oid), COALESCE(NULLIF(typ.typtypmod,-1),attr.atttypmod))::VARCHAR(256) AS r_TypeName, attr.attnotnull AS r_isNotNULL, dsc.description AS r_Description FROM pg_attribute attr LEFT OUTER JOIN pg_type typ ON attr.atttypid=typ.oid LEFT OUTER JOIN pg_type btyp ON typ.typbasetype=btyp.oid LEFT OUTER JOIN pg_description dsc ON dsc.objoid=attr.attrelid AND dsc.objsubid=attr.attnum WHERE attr.attrelid =a_TableOID AND attr.attnum=a_AttributeNo; SELECT INTO rsa_isAttributePK,rsa_ColumnPKNo rs_isAttributePK,rs_ColumnPKNo FROM admtf_Attribute_PKFeatures(a_TableOID,a_AttributeNo); SELECT INTO rsa_isAttributeFK,rsa_FKeyName,rsa_ColumnFKNo,rsa_FKTableName, rsa_FKTableColumnName rs_isAttributeFK,rs_FKeyName, rs_ColumnFKNo,rs_FKTableName,rs_FKTableColumnName FROM admtf_Attribute_FKFeatures(a_TableOID,a_AttributeNo); RETURN QUERY SELECT rsa_AttributeName,rsa_UserTypeName,rsa_TypeName,rsa_isNotNULL, rsa_isAttributePK,rsa_ColumnPKNo,rsa_Description,rsa_isAttributeFK, rsa_FKeyName,rsa_ColumnFKNo,rsa_FKTableName,rsa_FKTableColumnName; END $BODY$ LANGUAGE plpgsql; COMMENT ON FUNCTION admtf_Attribute_Features(a_TableOID OID,a_AttributeNo SMALLINT) IS '   '; --ROLLBACK TRANSACTION; COMMIT TRANSACTION; SELECT * FROM admtf_Attribute_Features ((SELECT OID FROM pg_class WHERE relname='street'),2::SMALLINT); 


Lihat juga


PostgreSQL. ;
PostgreSQL. .
PostgreSQL. ( ) .

Source: https://habr.com/ru/post/id418597/


All Articles