Funktionen zum Dokumentieren von PostgreSQL-Datenbanken. Teil drei

Dies ist der dritte Teil des Artikels, der benutzerdefinierte Funktionen für die Arbeit mit Systemverzeichnissen beschreibt: pg_class, pg_attribute, pg_constraints usw.

In diesem Abschnitt des Artikels werden Funktionen erläutert, die die Eigenschaften von Sequenzen, geerbten Tabellen und die besonderen Eigenschaften von Tabellenattributen zurückgeben .

Siehe auch
Funktionen zum Dokumentieren von PostgreSQL-Datenbanken. Teil eins ;
Funktionen zum Dokumentieren von PostgreSQL-Datenbanken. Teil zwei ;
Funktionen zum Dokumentieren von PostgreSQL-Datenbanken. Das Ende (Teil vier) .

Die erste Hälfte des Artikels enthält Kommentare zur Implementierung von Funktionen. Der zweite ist der Quellcode der Funktionen. Für diejenigen Leser, die nur an den Ausgangstexten interessiert sind, empfehlen wir, sofort mit dem Anhang fortzufahren .

Struktur einer Funktion, die eine Liste von Merkmalen von Tabellensequenzen zurückgibt



Abb. 2. Funktionen, von denen die Funktionen von admtf_Table_Sequences abhängen

Tabelle 11. Zweck der Funktionen.

Nein, nein.TitelTermin
1admtf_Sequence_FeaturesDie Funktion gibt eine Liste der Tabellensequenzmerkmale zurück.
2admtf_Table_SequencesDie Funktion gibt eine Liste der Datenbanktabellenfolgen und ihrer Eigenschaften zurück.

Admtf_Sequence_Features- Funktion - Liste der Datenbanksequenzmerkmale


Die Funktion admtf_Sequence_Features gibt eine Liste der Datenbank-SEQUENCE-Merkmale zurück. Der Quellcode kann hier angezeigt und heruntergeladen werden .


Die Funktion admtf_Sequence_Features gibt eine Liste der Datenbanksequenzmerkmale ( SEQUENCE ) zurück.

.

Als Parameter verwendet die Funktion den Namen der Sequenz ( a_SequenceName ) und den Namen des Schemas, in dem die Sequenz erstellt wird ( a_SchemaName ).


Die Notwendigkeit für die Funktion admtf_Sequence_Features ergab sich, weil die Hauptmerkmale der Sequenz tatsächlich in einer Tabelle gespeichert sind, deren Name mit dem Namen der Sequenz übereinstimmt, und Daten mit der Anweisung SELECT daraus extrahiert werden. In diesem Fall werden der Name der Sequenz, der Name des Schemas und der Kommentar zur Sequenz in den Verzeichnissen pg_class , pg_namespace und pg_description gespeichert.


SELECT * FROM kr_road_network_vertices_pgr_id_seq; 

Bemerkung 6


PostgreSQL 10 trennte die Eigenschaften der Sequenz und die Eigenschaften ihrer Zustände. Zu diesem Zweck wurde das Verzeichnis pg_sequence mit Sequenzmerkmalen eingeführt, das den Anfangswert ( start_value ), das Inkrement ( increment_by ) und den Maximalwert ( max_value ) der Sequenz enthält. Der letzte von der Sequenz zurückgegebene Wert ( last_value ) wurde in der "Tabelle" mit dem Namen der Sequenz belassen.

Das Ende der Bemerkung.


Die Darstellung jeder Sequenz als Analogon der Tabelle wird meiner Meinung nach durch die Notwendigkeit bestimmt, den zuletzt verwendeten Wert der Sequenz ( last_value ) zu speichern, der ein Merkmal des Zustands der Sequenz ist, jedoch nicht der Sequenz selbst.


Der Sequenzeintrag im Verzeichnis pg_class unterscheidet sich vom Tabelleneintrag durch den Wert des Beziehungstyps (relkind = 'S' ).


Um die Eigenschaften einer beliebigen Sequenz zu extrahieren, müssen Sie dynamisches SQL verwenden.


 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 ; 


Tabelle 12. Das Ergebnis der Ausführung der Funktion admtf_Sequence_Features ('public', 'kr_road_network_vertices_pgr_id_seq').

TitelKommentarStromStarten SieInkrementierenDas Ende
kr_road_network
_vertices_pgr_id
_seq
Sequenz138023119223372036854775807

Funktion admtf_Table_Sequences Liste der Datenbanktabellenfolgen und ihrer Eigenschaften


Die Funktion admtf_Table_Sequences gibt eine Liste von Sequenzen ( SEQUENCE ) der Datenbanktabelle zurück, die die Werte ihrer Felder und die Eigenschaften dieser Sequenzen generiert. Der Quellcode kann hier angezeigt und heruntergeladen werden . Hier ist eine Version einer Funktion, die keinen Cursor verwendet .


Als Parameter verwendet die Funktion den Namen der Quelltabelle ( a_TableName ) und den Namen des Schemas, in dem die Tabelle erstellt wird (

a_SchemaName

)

der Quellcode des Operators in der Abbildung
 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; 


Eine Beschreibung einer einzelnen Sequenz ist eine Kombination aus einem Datensatz in pg_class , der sie als physikalische Beziehung beschreibt, und einer bedingten Tabelle mit dem Namen der Sequenz, die Daten zu den spezifischen Merkmalen der Sequenz enthält


Informationen zur Beziehung zwischen der Sequenz und der Quelltabelle werden im Systemverzeichnis pg_depend gespeichert.



Tabelle 13. Attribute des Verzeichnisses pg_depend, die zur Implementierung der Funktion benötigt werden.
TitelBeschreibung
objidOID der Sequenz im Verzeichnis pg_class
objsubidDieses Feld enthält Null
refobjidOID der Tabelle, in deren Feldern die Sequenz verwendet wird
refobjsubidTabellenattributnummer, deren Werte mit einer Sequenz gefüllt werden

Zusätzlich greift die Funktion auf die Katalogdaten pg_namespace und pg_description zu, um die Diagramme und Kommentare sowohl der Sequenz als auch der Quelltabelle zu extrahieren.


Um das Attribut einer Tabelle zu bestimmen, deren Werte mithilfe einer Sequenz gefüllt werden, greift die Funktion unter der Bedingung attrelid = refobjid AND attnum = refobjsubid auf das Verzeichnis pg_attribute zu . (In diesem Zustand werden die Namen der Attribute des Verzeichnisses pg_depend rechts vom Gleichheitszeichen angegeben.)


Die besonderen Merkmale von Tabellensequenzen werden in einer Schleife durch Aufrufen von admtf_Sequence_Features abgerufen. Der Zyklus wird verwendet, weil mehr als eine Sequenz zugewiesen werden kann, um die Felder der Tabelle auszufüllen.


Tabelle 14. Das Ergebnis der Ausführung der Funktion admtf_Table_Sequences ('public', 'kr_road_network_vertices_pgr').

TitelKommentarStarten SieInkrementierenDas EndeDas Feld
kr_road_network
_vertices_pgr_id
_seq
Sequenzgenerierung von ID-Feldwerten119223372036854775807id

Version ohne Cursor


In einer PostgreSQL- Umgebung mit einer Version unter 10 ist es höchstwahrscheinlich unmöglich, die Funktion admtf_Table_Sequences ohne Verwendung eines Cursors zu implementieren.
Aber die glücklichen Besitzer von Version 10 können gut auf einen Cursor verzichten, denn Sie verfügen über das Verzeichnis pg_sequence . In diesem Fall können alle Merkmale der Sequenz mit einer einzigen SELECT-Anweisung abgerufen werden.


In der gegebenen Funktionsimplementierung wird unter Verwendung der Fensterfunktion RANK () OVER (PARTITION BY pseq.relname) die Sequenznummer der Sequenz berechnet, die zum Füllen der Quellentabelle verwendet wird.



der Quellcode des Operators in der Abbildung
 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; 


Bemerkung 7

.

Diese Version der Funktion gibt nicht den letzten von der Sequenz generierten Wert zurück ( last_value ).

Das Ende der Bemerkung.


Admtf_Table_InheritanceChildrens-Funktion - Liste der Merkmale geerbter Tabellen


Die Funktion admtf_Table_InheritanceChildrens gibt eine Liste der Merkmale der geerbten Tabellen ( INHERITS ) der Datenbanktabelle zurück. Der Quellcode kann hier angezeigt und heruntergeladen werden .


Als Parameter verwendet die Funktion den Namen der Quelltabelle ( a_TableName ) und den Namen des Schemas, in dem die Tabelle erstellt wird ( a_SchemaName ).


Die Beschreibung einer einzelnen Legacy-Tabelle befindet sich im Eintrag in pg_class . Um jedoch nach geerbten Tabellen mit dem Namen der Quelltabelle zu suchen, müssen Sie den Systemkatalog pg_depend verwenden.


Tabelle 15. Attribute des Verzeichnisses pg_depend, die zur Implementierung der Funktion benötigt werden.
TitelBeschreibung
objidOID der geerbten Tabelle im Verzeichnis pg_class
refobjidOID der Quelltabelle


der Quellcode des Operators in der Abbildung
 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; 


Darüber hinaus greift die Funktion auf die Verzeichnisdaten pg_namespace und pg_description zu, um Schemas und Kommentare sowohl für die geerbte als auch für die Quelltabelle zu extrahieren.


Tabelle 16. Das Ergebnis der Ausführung der Funktion admtf_Table_InheritanceChildrens ('public', 'np_house').

TitelKommentarAttribute? Primärschlüssel? Indizes? NachkommenAnzahl der Datensätze
np_house 04201 000000Häuser in Siedlungen (Bezirk Achinsky)15fff5651
np_house 4208 000 000Häuser in Siedlungen (Bezirk Bogotolsky)15fff4314

Die Anzahl der Datensätze in der generierten Tabelle wird aus dem reltuple-Attribut des Verzeichnisses pg_class ausgewählt. Und obwohl dieser Wert oft genau mit der tatsächlichen Anzahl von Einträgen in der Tabelle übereinstimmt, ist er immer noch ein geschätzter Wert. Vielleicht möchten Sie als Ergebnis den genauen Wert erhalten. Zum Beispiel wie in der Abbildung gezeigt.


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

Um diese Aussage im Text zu erfüllen, muss die Funktion admtf_Table_InheritanceChildrens zunächst einen Cursor verwenden.


Zweitens möchte ich, dass die Funktion sowohl die geschätzte als auch die genaue Anzahl der Tabelleneinträge anzeigt.


Daher verfügt die Funktion über einen weiteren optionalen Parameter - den Modus zum Abrufen der Anzahl der Tabelleneinträge ( a_Mode ), der die Werte "Schätzung" ( Schätzung ) oder "genau" ( genau ) annimmt.



Zusätzlich wurde die Funktion admfn_Table_RowCount erstellt , die die genaue Anzahl der Tabelleneinträge zurückgibt, und das Attribut reltuple wird in der Rückgabeliste SELECT durch die folgende Konstruktion ersetzt.



der Quellcode des Operators in der Abbildung
 CASE WHEN a_Mode = 'exactly' THEN admfn_Table_RowCount(rnspc.nspname,rtbl.relname) ELSE reltuples END 


Infolgedessen gibt die Funktion den geschätzten Wert des Indikators "Anzahl der Tabelleneinträge" zurück, wenn der Parameter a_Mode nicht die Anforderung angibt , den genauen Wert zurückzugeben.


Struktur einer Funktion, die eine Liste von Tabellenattributmerkmalen zurückgibt



Abb. 3. Funktionen, die admtf_Attribute_Features aufruft

Textversion der Tabelle in der Abbildung
Tabelle 17. Zweck der Funktionen.

Nein, nein.TitelTermin
1admtf_Attribute_PKFeaturesDie Funktion gibt das Attribut Präsenzpräsenz im Primärschlüssel (PRIMARY KEY) sowie einige seiner Merkmale als Teil dieses Schlüssels zurück.
2admtf_Attribute_FKFeaturesDie Funktion gibt das Attribut Präsenzpräsenz im Fremdschlüssel (FOREIGN KEY) sowie einige seiner Merkmale als Teil dieses Schlüssels zurück.
3admtf_Attribute_FeaturesDie Funktion gibt eine Liste der Tabellenattributmerkmale zurück.


Funktion admtf_Attribute_PKFeatures - - ob das Attribut im Primärschlüssel vorhanden ist



Die Funktion admtf_Attribute_PKFeatures gibt ein Zeichen für das Vorhandensein eines Tabellenattributs im Primärschlüssel (PRIMARY KEY) der Tabelle zurück. Wenn es vorhanden ist, wie lautet die Seriennummer in diesem Schlüssel seitdem Primärschlüssel kann zusammengesetzt sein.
Der Quellcode kann hier angezeigt und heruntergeladen werden .


Als Parameter verwendet die Funktion die OID der Quelltabelle ( a_TableOID ) und die Seriennummer des gewünschten Attributs ( a_AttributeNo ).


Die Funktion extrahiert die erforderlichen Daten aus dem Verzeichniseintrag pg_constraint , der die (CONSTRAINT) -Einschränkungen der Quelltabelle enthält, einschließlich der Primärschlüsseleinschränkung. Die OID der gewünschten Tabelle wird im Conrelid- Feld gespeichert, die Beschreibung des Primärschlüssels wird in einem Datensatz gespeichert, in dem das Contype-Feld den Wert '' p 'enthält.

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

Das auf diese Weise gefundene Schlüsselfeld enthält ein Array von Attributnummern, aus denen der Primärschlüssel besteht. Um das Vorhandensein des Quellattributs im Primärschlüssel zu überprüfen, reicht es daher aus, den logischen Ausdruck ARRAY [a_AttributeNo] <@ conkey zu berechnen.


Wenn das Attribut im Primärschlüssel vorhanden ist, wird seine Sequenznummer in der Schleife berechnet.


Funktion admtf_Attribute_FKFeatures - Gibt an, ob das Attribut im Fremdschlüssel vorhanden ist



Die Funktion admtf_Attribute_FKFeatures gibt ein Zeichen für das Vorhandensein eines Tabellenattributs in einem oder mehreren Fremdschlüsseln (FOREIGN KEY) der Tabelle zurück. Wenn vorhanden, wie lauten die Folgenummern in diesen Schlüsseln, weil Fremdschlüssel kann zusammengesetzt sein.

Der Quellcode kann hier angezeigt und heruntergeladen werden .


Als Parameter verwendet die Funktion die OID der Quelltabelle ( a_TableOID ) und die Seriennummer des gewünschten Attributs ( a_AttributeNo ).


Die Funktion ruft die erforderlichen Daten aus dem Verzeichniseintrag pg_constraint ab , der CONSTRAINT der Quelltabelle enthält, einschließlich, aber nicht beschränkt auf Fremdschlüsseleinschränkungen. Die OID der gewünschten Tabelle wird im Conrelid- Feld gespeichert, die Beschreibung des Primärschlüssels wird in einem Datensatz gespeichert, in dem das Contype-Feld den Wert '' f 'enthält.

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

Das auf diese Weise gefundene Schlüsselfeld enthält ein Array von Attributnummern, aus denen der Fremdschlüssel besteht. Um das Vorhandensein des Quellattributs im Fremdschlüssel zu überprüfen, reicht es daher aus, den logischen Ausdruck ARRAY [a_AttributeNo] <@ conkey zu berechnen.


Wenn das Attribut im Fremdschlüssel vorhanden ist, wird in der Schleife ein Array seiner Sequenznummern in den Fremdschlüsseln gebildet, die es enthalten. Zusätzlich werden zwei weitere Arrays aus den Namen der Tabellen und ihren Attributen gebildet, auf die das Quellattribut in den Fremdschlüsseln verweist, die es enthalten.


Tabellennamen werden aus dem Verzeichniseintrag pg_class durch eine Kennung (OID) abgerufen, die aus dem Konfrelidfeld des Fremdschlüsseleintrags abgerufen wird.


Verwenden Sie ein Array mit Seriennummern aus dem Feld, um den Namen des Attributs der externen Tabelle abzurufen

confkey

(Es unterscheidet sich vom obigen Array durch den Buchstaben " f " im Namen). Aus diesem Array wird die Seriennummer des Attributs der externen Tabelle extrahiert, der das externe Attribut entspricht. Durch diese Seriennummer des Attributs der externen Tabelle und ihrer OID im Verzeichnis pg_attribute wird ein Eintrag für die Beschreibung des Attributs erstellt und dessen Name abgerufen.

Admtf_Attribute_Features- Funktion - Liste der Tabellenattributmerkmale


Die Funktionen admtf_Attribute_Features geben eine Liste der folgenden Tabellenattributmerkmale zurück. Der Quellcode kann hier angezeigt und heruntergeladen werden .



Die Textversion der Tabelle in der Abbildung
Nein, nein.TitelTypTermin
1AttributnameNameDer Name des Quellattributs.
2UserTypeNameVARCHAR (256)Benutzerdefinierter Quellattributtyp
3TypenameVARCHAR (256)Basistyp des Quellattributs
4isNotNULLBOOLEAN? Nullgültigkeit
5isAttributePKBOOLEAN? Teilnahme an PK
6ColumnPKNoSMALLINTAttribut Seriennummer in PK
7BeschreibungTEXTKommentar zum Quellattribut
8isAttributeFKBOOLEAN? Teilnahme an FK
9FKeyNameName []Ein Array von Namen von Einschränkungstabellen, in denen der Fremdschlüssel definiert ist
10ColumnFKNoSMALLINT []Array von Attributsequenznummern in Fremdschlüsseln einer Tabelle
11FKTableNameName []Array von Tabellen, auf die durch Fremdschlüssel verwiesen wird
12FKTableColumnNameName []Array von Attributnamen in externen Tabellen, die dem Quellattribut entsprechen


Als Parameter verwendet die Funktion die OID der Quelltabelle ( a_TableOID ) und die Seriennummer des gewünschten Attributs ( a_AttributeNo ).
Die Werte der Felder AttributeName und isNotNULL werden aus dem Verzeichniseintrag pg_attribute abgerufen, der den Werten der Eingabeparameter entspricht.


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

Die Werte der Felder isAttributePK und ColumnPKNo werden von der Funktion admtf_Attribute_PKFeatures zurückgegeben .


Die Werte der Felder isAttributeFK , FKeyName , ColumnFKNo , FKTableName und FKTableColumnName werden von der Funktion admtf_Attribute_FKFeatures zurückgegeben .


Ein Aufruf von admtf_Attribute_Features ((SELECT OID FROM pg_class WHERE relname = 'street'), 2 :: SMALLINT) führt zu folgendem Ergebnis.


Tabelle 18. Ergebnis der Ausführung der Funktion admtf_Attribute_Features
AttributnameUserTypeNameTypenameisNotNULLisAttributePKColumnPKNo
localityidlocalityidGanzzahlGanzzahlGanzzahlGanzzahl


BeschreibungisAttributeFKFKeyNameColumnFKNoFKTableNameFKTableColumnName
Community IDt{fk_street_locality}{2}{Ort}{localityid}

ANHANG 1. Skripte


Erstellen der Funktion admtf_Sequence_Features


Kommentare zum Funktionsquellcode finden Sie hier.
Funktionscode
 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); 



Erstellen der Funktion admtf_Table_Sequences


Kommentare zum Funktionsquellcode finden Sie hier.
Funktionscode
 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); 


Siehe auch


PostgreSQL. ;
PostgreSQL. .
PostgreSQL. ( ) .

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


All Articles