Fonctions de documentation des bases de données PostgreSQL. Première partie

Au cours du travail avec PostgreSQL, plus d'une centaine de fonctions pour travailler avec les répertoires système se sont accumulées: pg_class, pg_attribute, pg_constraints, etc.


Que faire avec eux? Ils sont utilisés relativement rarement. Inclure dans tout projet? Le client de Krasnoyarsk ne paiera pas de telles "absurdités". Et pourtant, si elles sont utiles à quelqu'un d'autre qu'à l'auteur. Et il a décidé de les mettre, comme des livres lus, dans un placard public pour ceux qui le souhaitent.

Quelqu'un veut les utiliser dans leur travail. Et quelqu'un d'autre que son expérience avec les catalogues système.

Mais pour ne pas transformer la publication en une énumération ennuyeuse, on ne sait pas pourquoi les fonctions ont été créées, j'ai décidé de m'attarder sur celles d'entre elles qui peuvent être unies par un objectif commun. Par conséquent, les fonctions utilisées pour afficher une liste étendue de caractéristiques d'une table de base de données arbitraire sont sélectionnées.

La liste étendue des caractéristiques de la table de base de données est renvoyée par la fonction admtf_Table_ComplexFeatures , qui sera appelée la fonction head dans cet article. Ainsi, l'article se limitera à considérer les fonctions qui sont appelées dans le processus d'exécution de la fonction tête.

La première moitié de l'article fournit des commentaires sur la mise en œuvre des fonctions. Le second est le code source des fonctions. Pour les lecteurs qui ne sont intéressés que par les textes sources, nous suggérons de passer immédiatement à l' annexe .

Voir aussi
Fonctions de documentation des bases de données PostgreSQL. Deuxième partie ;
Fonctions de documentation des bases de données PostgreSQL. Troisième partie .
Fonctions de documentation des bases de données PostgreSQL. La fin (quatrième partie) .




De quelles fonctionnalités avancées parlons-nous?


Afin d'avoir une idée de ce que l'on entend par les caractéristiques étendues de la table de base de données, nous commençons par examiner la liste de caractéristiques suivante. La liste contient les caractéristiques de la table de base de données Street retournée par admtf_Table_ComplexFeatures ( 'public' , 'street' ) .

Le tableau ci-dessous contient une liste abrégée des fonctionnalités de la table Street. Un ensemble complet de caractéristiques de ce tableau est donné dans les documents supplémentaires de l'annexe 2.

Tableau 1. Fonctions avancées de la table Street.

La version texte du tableau de la figure
CatégorieNon.Le titreCommentairetypeType de base? pas nul
tbl0rueListe des rues dans les colonies
att1wcrccodeCode payswcrccodesmallintt
att2localityidID de communautélocalityidentiert
att3streetidID rue du villagestreetidsmallintt
att4streettypeacrmAcronyme de la ruestreettypeacrmpersonnage (8)f
att5nom de rueNom de la ruestreettypeacrmvarchar (150)t
pk0xpkstreetClé primaire de la table de rue
pkatt1wcrccodeCode payswcrccodesmallintt
fk011fk_street_localityClé étrangère de table
fk022fk_street_streettypeClé étrangère de table
idx011xie1streetIndex par type et nom de rue de la colonie
idx022xie2streetCode postal
idx033xie3streetIndex des noms de rue de toutes les colonies
idx044xpkstreetL'index unique (clé primaire) de la table de rue


En énumérant l'hostilité à cet ensemble de lettres et de chiffres, vous pouvez voir que nous parlons des caractéristiques habituelles d'une table de base de données:


  • Noms de table;
  • La liste des attributs de table et leurs types;
  • La clé primaire et la liste des clés étrangères de la table, ainsi que les attributs de la table qui les composent;
  • Une liste d'index de table.

L'unicité de chaque entrée de la liste des caractéristiques est assurée par les valeurs des champs «catégorie» et le numéro de série («N °») de la caractéristique.



Tableau 2. Catégories de caractéristiques du tableau.

La version texte du tableau de la figure
AcronymeRendez-vous
tbCaractéristiques du tableau
attCaractéristiques des attributs de table
seqCaractéristiques de séquence
pkCaractéristiques principales principales
pkAttCaractéristiques des attributs de clé primaire
fk99Caractéristiques clés étrangères
fk99attCaractéristiques des attributs de clé étrangère
fk99rtblCaractéristiques de la table référencée par la clé étrangère
fk99rattCaractéristiques des attributs de la table référencée par la clé étrangère
Idx99Caractéristiques de l'indice
Idx99attCaractéristiques des attributs d'index
Inhtbl99Caractéristiques de la table générée


La valeur de la catégorie est nécessaire pour distinguer les différents groupes de caractéristiques les uns des autres. Un numéro de série, afin de distinguer les caractéristiques au sein du groupe.


Plusieurs clés étrangères (FOREIGN KEY) et index peuvent être déclarés dans la table de base de données. Par conséquent, la valeur de catégorie pour ces caractéristiques et leurs descendants contient un numéro de série. Par exemple, une entrée avec la clé «Category» = idx02att et «No.» = 1 indique le premier attribut du 2e index.


Dans la liste des catégories ci-dessus, l'emplacement du numéro de série est indiqué par «99».


Remarque 1



le code source de l'opérateur sur la figure
SELECT * FROM admtf_Table_ComplexFeatures('pg_catalog','pg_class'); 



L'article donne des exemples des caractéristiques des tables, qui sont brièvement décrites dans un schéma auxiliaire créé spécifiquement pour démontrer les capacités des fonctions. Mais le lecteur, ayant créé telle ou telle fonction dans sa base de données, peut utiliser les noms de ses schémas et tables comme paramètres. De plus, par exemple, le répertoire pg_class peut être utilisé comme paramètre, bien que dans ce cas un nombre limité de caractéristiques soient émises.

La fin de la remarque.



Structure de la fonction de tête



Fig. 1. Les fonctions qui provoquent la fonction de la tête.

Tableau 3. Affectation des fonctions.

La version texte du tableau de la figure
Non.Le titreRendez-vous
1admtf_Table_FeaturesLa fonction renvoie une liste des caractéristiques de la table de base de données
2admtf_Table_AttributesLa fonction renvoie une liste des attributs de table de base de données et leurs caractéristiques.
3admtf_Table_ConstraintesLa fonction renvoie une liste des restrictions de table de base de données et leurs caractéristiques.
4admtf_Table_IndexesLa fonction renvoie une liste des index de table de base de données et leurs caractéristiques.
5admtf_Table_InheritanceChildrensLa fonction renvoie une liste des tables générées par (IHERITS) à partir de la table de base de données source.
6admtf_Table_SequencesLa fonction renvoie une liste de séquences (SEQUENCE) dont dépend la table.
7admtf_PrimaryKey_ComplexFeaturesLa fonction renvoie une liste complète (étendue) des caractéristiques de clé primaire (PRIMARY KEY) de la table de base de données.
8admtf_ForeignKey_ComplexFeaturesLa fonction renvoie une liste complète (étendue) des caractéristiques de clé étrangère (FOREIGN KEY) de la table de base de données.
9admtf_Index_ComplexFeaturesLa fonction renvoie une liste complète (étendue) des caractéristiques d'index de table de base de données.
10admtf_Table_ComplexFeaturesLa fonction renvoie une liste complète (étendue) des caractéristiques de la table de base de données.


Remarque 2.


Les descriptions des fonctions seront organisées dans l'ordre indiqué ci-dessus. La raison en est que l'article devra être divisé en plusieurs parties. Et les fonctions organisées dans cet ordre peuvent être utilisées indépendamment du fait que certaines d'entre elles ne seront décrites que dans les parties suivantes de la publication.


La fin de la remarque.



Admtf_Table_Features, liste des fonctions de la table de base de données




La fonction admtf_Table_Features renvoie une liste des caractéristiques de la table de base de données elle-même. Le code source peut être consulté et téléchargé ici.


En tant que paramètres, la fonction prend le nom de la table source (a_TableName ) et le nom du schéma dans lequel la table est créée ( a_SchemaName ).


La fonction extrait les données principales de l' entrée de catalogue pg_class , qui contient, en plus des entrées de table, des enregistrements sur les séquences, les vues, les vues matérialisées et les types composites. Par conséquent, pour sélectionner des tables, la condition relkind = 'r' est utilisée .



 SELECT tbl.relname,dsc.description,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 LOWER( nspc.nspname)=LOWER(a_SchemaName) AND tbl.relkind='r' AND LOWER(tbl.relname) =LOWER(a_TableName); 

De plus, la fonction accède aux données de répertoire pg_namespace et pg_description . Le premier contient les noms des schémas de base de données et le second contient des commentaires sur tous les objets de base de données.


Il est important de faire attention à la condition objsubid = 0 . Il définit le commentaire sur la table, car la valeur du champ objoid est la même pour la table et ses attributs. Le commentaire sur l'attribut de la table est contenu dans l'entrée dans laquelle objsubid correspond au numéro de cet attribut.



Tableau 4. Résultat de l'exécution de la fonction admtf_Table_Features ('public', 'Street').

Le titreCommentaireNombre d'attributsNombre de contraintes CHECK? y a-t-il une clé primaire? les index sont-ils déclarés? y a-t-il des descendantsLe nombre d'entrées dans le tableau
rueListe des rues dans les colonies220ttf20150

Remarque 3


Faites attention au nombre d'attributs de table de rue. Il diffère considérablement du nombre d'attributs spécifié dans le schéma auxiliaire.


Tableau 5. Attributs supplémentaires de la table Street.


attnameatttypidattnumRemarque
cmin29-4Attribut système
xmin28-3Attribut système
ctid27-1Attribut système
wcrccode7953691Attribut valide
localityid7953522Attribut valide
streetid7953643Attribut valide
streettypeacrm19191684Attribut valide
nom de rue10435Attribut valide
........ pg.dropped.6 ........06Attribut distant
........ pg.dropped.7 ........07Attribut distant

Le fait est que PostgreSQL, en plus des attributs principaux, prend également en compte plusieurs attributs système, et même des attributs supprimés.


Remarque finale



Fonction admtf_Table_Attributes liste des attributs de table de base de données et leurs caractéristiques


La fonction admtf_Table_Attributes renvoie une liste d'attributs de table de base de données. Le code source peut être consulté et téléchargé ici.


En tant que paramètres, la fonction prend le nom de la table source ( a_TableName ) et le nom du schéma dans lequel la table est créée ( a_SchemaName ).


La fonction récupère les données principales des entrées du répertoire pg_attribute et pg_type . Le premier contient des enregistrements contenant des données sur les attributs des tables, des vues, des vues matérialisées, des types composites et même des fonctions. La seconde concerne les caractéristiques des types d'attributs.


Peut-être que des précisions sont nécessaires sur la façon dont les types d'utilisateurs et de base sont définis dans la fonction.


Un attribut de table est déclaré avec un type personnalisé si le champ typbasetype est supérieur à 0 dans l' entrée de répertoire pg_type correspondante. Sinon, l'attribut est du type de base. Par conséquent, le répertoire pg_type est impliqué deux fois dans la clause FROM. Dans la première entrée de répertoire, la présence d'un type d'utilisateur est déterminée, s'il n'est pas défini ( typbasetype = 0 ), une valeur de type de base est générée à partir de cette entrée. Sinon, le type de base est déterminé à partir de l'enregistrement pour lequel btyp.OID = typ.typbasetype.


Directement la ligne avec le type de base est formée en utilisant la fonction du catalogue système FORMAT_TYPE (type_oid, typemod) . Le premier paramètre est les enregistrements OID de type de base. Le deuxième paramètre est la valeur du modificateur pour les types qui contiennent une taille. Par exemple, VARCHAR (100) ou NUMERIC (4,2), DECIMAL (4,2). La valeur du paramètre typemod est tirée de typ.typtypmod si l'attribut est d'un type utilisateur, sinon de attr.atttypmod , c'est-à-dire directement à partir d'un enregistrement d'attribut.



le code source de l'opérateur sur la figure
 SELECT attr.attnum, attr.attname::VARCHAR(100), CASE WHEN COALESCE(typ.typbasetype,0)>0 THEN typ.typname::VARCHAR(100) ELSE '' END, FORMAT_TYPE(COALESCE(NULLIF(typ.typbasetype,0),typ.oid), COALESCE(NULLIF(typ.typtypmod,-1),attr.atttypmod))::VARCHAR(256), attr.attnotnull, dsc.description FROM pg_attribute attr INNER JOIN pg_class tbl ON tbl.oid = attr.attrelid INNER JOIN pg_namespace nspc ON tbl.relnamespace = nspc.oid INNER JOIN pg_type typ ON attr.atttypid=typ.oid LEFT OUTER JOIN pg_description dsc ON dsc.objoid=attr.attrelid AND dsc.objsubid=attr.attnum WHERE LOWER( nspc.nspname)=LOWER(a_SchemaName) AND LOWER(tbl.relname) =LOWER(a_TableName) AND tbl.relkind='r' AND attr.attnum>0 AND attr.atttypID>0 ORDER BY tbl.relname,attr.attnum; 


De plus, la fonction accède aux données de répertoire pg_class , pg_namespace et pg_description . Les premier et deuxième répertoires sont utilisés pour rechercher des attributs par les noms du schéma et de la table de base de données.

Le troisième répertoire est utilisé pour récupérer le commentaire de l'attribut de table.


Le commentaire sur l'attribut de la table se trouve dans l'entrée dans laquelle dsc.objoid contient l'OID de la table source et dsc.objsubid est le numéro de série de l'attribut dans la table, c'est-à-dire attr.attnum .


Pour empêcher la fonction de renvoyer des attributs système et distants, la clause WHERE définit la condition attr.attnum> 0 AND attr.atttypID> 0 .



Tableau 6. Résultat de l'exécution de la fonction admtf_Table_Attributes ('public', 'Street').

Non.Le titreType personnaliséType de base? pas nulCommentaire
1wcrccodewcrccodesmallinttCode pays
2localityidlocalityidentiertID de communauté
3streetidstreetidsmallinttID rue du village
4streettypeacrmstreettypeacrmpersonnage (8)fAcronyme de la rue
5nom de ruevarchar (150)tNom de la rue de la colonie

Version de fonction utilisant l'alias regclass pour le type oid


Les identificateurs d'objet (OID) PostgreSQL sont du même type que l'OID, qui est actuellement implémenté sous la forme d'un entier non signé sur quatre octets. Mais en raison de la présence d'alias de ce type, un entier peut être représenté comme le nom d'un objet. Et vice versa - convertissez le nom de l'objet en un entier de type OID.


Par exemple, jetez un œil à l' instruction SELECT suivante. Il récupère de manière inhabituelle les noms de la table attributaire et les noms de ses types - au lieu d'accéder aux champs de répertoire correspondants avec les noms de ces caractéristiques, ils sont utilisés:

  • attrelid :: regclass (attrelid :: regclass: NAME) ,
  • atttypid :: regtype (atttypid :: regtype: NAME)
  • typbasetype :: regtype (typbasetype :: regtype: NAME) .


 SELECT attr.attname,attr.attrelid::regclass, attr.atttypid::regtype, typ.typbasetype::regtype,attr.attrelid::regclass::name, attr.atttypid::regtype::name,typ.typbasetype::regtype::name FROM pg_attribute attr INNER JOIN pg_type typ ON attr.atttypid=typ.oid WHERE attr.attrelid=('public'||'.'||'Street')::regclass AND attr.attnum>0 AND attr.atttypID>0 ORDER BY attr.attnum; 

Voici le résultat de l'exécution de cette requête.



Dans la liste des valeurs de sortie de l'opérateur SELECT avant la conversion à l'aide d'alias de type OID, toutes les valeurs à l'exception du nom d'attribut sont numériques, mais en conséquence, les noms de table et les types d'attribut sont affichés. Les types de valeurs de sortie peuvent être considérés dans la deuxième ligne de l'en-tête du tableau.


De plus, dans la clause WHERE de l'instruction, la condition attr.attrelid = ('public' || '.' || 'Street') :: regclass se trouve , à gauche de laquelle se trouve une valeur numérique et à droite se trouve une chaîne qui est convertie en une valeur numérique avec en utilisant l'alias regclass .



le code source de l'opérateur sur la figure
 SELECT attr.attnum, attr.attname::VARCHAR(100), CASE WHEN COALESCE(typ.typbasetype,0)>0 THEN typ.typname::VARCHAR(100) ELSE '' END, FORMAT_TYPE(COALESCE(NULLIF(typ.typbasetype,0),typ.oid), COALESCE(NULLIF(typ.typtypmod,-1),attr.atttypmod))::VARCHAR(256), attr.attnotnull, dsc.description FROM pg_attribute attr INNER JOIN pg_type typ ON attr.atttypid=typ.oid LEFT OUTER JOIN pg_description dsc ON dsc.objoid=attr.attrelid AND dsc.objsubid=attr.attnum WHERE attr.attrelid=( a_SchemaName ||'.'|| a_TableName)::regclass AND attr.attnum>0 AND attr.atttypID>0 ORDER BY attr.attnum; 


En utilisant l'alias regclass de l'instruction principale, vous pouvez supprimer la connexion à deux répertoires. Mais une telle amélioration n'a presque pas eu d'effet sur les performances de la fonction - dans les deux versions, la fonction est exécutée en 11 ms. Peut-être dû au fait que la table de test a peu d'attributs.
Remarque 4

Une faille grave dans la condition sous la forme attr.attrelid = (a_SchemaName || '.' || a_TableName) :: regclass se manifeste lorsqu'il existe un schéma et / ou une table avec un nom inhabituel dans la base de données. Par exemple, «Mon schéma» et / ou «Ma table» . Ces valeurs doivent être transmises entre guillemets ou utiliser la fonction QUOTE_IDENT, sinon la fonction échouera avec une erreur système.



le code source de l'opérateur sur la figure
 /*       «   »*/ SELECT attr.attname,attr.attrelid::regclass, attr.atttypid::regtype,typ.typbasetype::regtype, attr.attrelid::regclass::name, attr.atttypid::regtype::name,typ.typbasetype::regtype::name FROM pg_attribute attr INNER JOIN pg_type typ ON attr.atttypid=typ.oid WHERE attr.attrelid=(' '||'.'||' ')::regclass AND attr.attnum>0 AND attr.atttypID>0 ORDER BY attr.attnum; /*       */ SELECT attr.attname,attr.attrelid::regclass, attr.atttypid::regtype,typ.typbasetype::regtype, attr.attrelid::regclass::name, attr.atttypid::regtype::name,typ.typbasetype::regtype::name FROM pg_attribute attr INNER JOIN pg_type typ ON attr.atttypid=typ.oid WHERE attr.attrelid=('" "'||'.'||'" "')::regclass AND attr.attnum>0 AND attr.atttypID>0 ORDER BY attr.attnum; 


Par conséquent, je préfère utiliser des conditions sous la forme LOWER (nspc.nspname) = LOWER (a_SchemaName) AND LOWER (tbl.relname) = LOWER (a_TableName) , ce qui ne conduit pas à des erreurs système.

Remarque finale

ANNEXE 1. Scripts


Création de la fonction admtf_Table_Features


Vous trouverez des commentaires sur le code source de la fonction ici.
code source de la fonction
 BEGIN TRANSACTION; DROP FUNCTION IF EXISTS admtf_Table_Features (a_SchemaName NAME,a_TableName NAME); /********************************************************************************************************/ /*     ,   */ /********************************************************************************************************/ CREATE OR REPLACE FUNCTION admtf_Table_Features (a_SchemaName NAME default 'public', /*     */ a_TableName NAME default NULL /*   */ ) 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'; v_TableOID OID; /*   */ v_TableName NAME; /*   */ v_TableDescription TEXT; /*   */ v_TableNumberOfRowCalc INTEGER; /*     */ --****************************************************************************************************** BEGIN SELECT INTO rs_TableName,rs_TableDescription,rs_NumberOfAttribute, rs_NumberOfChecks,rs_hasPKey,rs_hasIndex,rs_hasSubClass, rs_NumberOfRow tbl.relname,dsc.description,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_TableKind AND tbl.relname =LOWER(a_TableName); EXECUTE 'SELECT count(*) FROM ' ||LOWER(a_SchemaName) ||'.'||quote_ident(LOWER(a_TableName)) INTO v_TableNumberOfRowCalc; RETURN QUERY SELECT rs_TableName,rs_TableDescription,rs_NumberOfAttribute, rs_NumberOfChecks,rs_hasPKey,rs_hasIndex, rs_hasSubClass,v_TableNumberOfRowCalc AS rs_NumberOfRow; END $BODY$ LANGUAGE plpgsql; COMMENT ON FUNCTION admtf_Table_Features(a_SchemaName NAME,a_TableName NAME) IS '   ,  '; --ROLLBACK TRANSACTION; COMMIT TRANSACTION; BEGIN TRANSACTION; DROP FUNCTION IF EXISTS admtf_Table_Features (a_SchemaName VARCHAR(256),a_TableName VARCHAR(256)); /********************************************************************************************************/ /*     ,   */ /********************************************************************************************************/ CREATE OR REPLACE FUNCTION admtf_Table_Features (a_SchemaName VARCHAR(256) default 'public', /*     */ a_TableName VARCHAR(256) default NULL /*   */ ) 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'; v_TableOID OID; /*   */ v_TableName VARCHAR(256); /*   */ v_TableDescription TEXT; /*   */ v_TableNumberOfRowCalc INTEGER; /*     */ --****************************************************************************************************** BEGIN RETURN QUERY SELECT tf.rs_TableName::VARCHAR(256), tf.rs_TableDescription::TEXT, tf.rs_NumberOfAttribute::INTEGER, tf.rs_NumberOfChecks::INTEGER, tf.rs_hasPKey::BOOLEAN, tf.rs_hasIndex::BOOLEAN, tf.rs_hasSubClass::BOOLEAN, tf.rs_NumberOfRow::INTEGER FROM admtf_Table_Features(a_SchemaName::NAME,a_TableName::NAME) tf; END $BODY$ LANGUAGE plpgsql; COMMENT ON FUNCTION admtf_Table_Features(a_SchemaName VARCHAR(256),a_TableName VARCHAR(256)) IS '   ,  '; --ROLLBACK TRANSACTION; COMMIT TRANSACTION; SELECt * FROM admtf_Table_Features('public'::VARCHAR(256),'Street'::VARCHAR(256)); SELECt * FROM admtf_Table_Features('public':: NAME,'Street'::NAME); 



Création de la fonction admtf_Table_Attributes


Vous trouverez des commentaires sur le code source de la fonction ici.
code source de la fonction
 BEGIN TRANSACTION; DROP FUNCTION IF EXISTS admtf_Table_Attributes (a_SchemaName NAME,a_TableName NAME); /********************************************************************************************************/ /*      */ /********************************************************************************************************/ CREATE OR REPLACE FUNCTION admtf_Table_Attributes (a_SchemaName NAME default 'public', /*     */ a_TableName NAME default NULL /*   */ ) RETURNS TABLE (r_AttributeNumber SMALLINT,r_AttributeName NAME,r_UserTypeName NAME,r_TypeName NAME,r_isNotNULL BOOLEAN, r_Description Text) AS $BODY$ DECLARE c_TableKind CONSTANT CHAR:='r'; v_Scale INTEGER; /*   */ --****************************************************************************************************** BEGIN RETURN QUERY SELECT attr.attnum AS r_AttributeNumber, attr.attname::NAME AS r_AttributeName, CASE WHEN COALESCE(typ.typbasetype,0)>0 THEN typ.typname::NAME ELSE ''::NAME END AS r_UserTypeName, FORMAT_TYPE(COALESCE(NULLIF(typ.typbasetype,0),typ.oid), COALESCE(NULLIF(typ.typtypmod,-1),attr.atttypmod))::NAME AS r_TypeName, attr.attnotnull AS r_isNotNULL, dsc.description AS r_Description FROM pg_attribute attr INNER JOIN pg_class tbl ON tbl.oid = attr.attrelid INNER JOIN pg_namespace nsp ON tbl.relnamespace=nsp.oid 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 LOWER(nsp.nspname)=LOWER(a_SchemaName) AND LOWER(tbl.relname)=LOWER(a_TableName) AND tbl.relkind=c_TableKind AND attr.attnum>0 AND attr.atttypID>0 ORDER BY tbl.relname,attr.attnum; RETURN; END $BODY$ LANGUAGE plpgsql; COMMENT ON FUNCTION admtf_Table_Attributes(a_SchemaName NAME,a_TableName NAME) IS '   '; --ROLLBACK TRANSACTION; COMMIT TRANSACTION; BEGIN TRANSACTION; DROP FUNCTION IF EXISTS admtf_Table_Attributes (a_SchemaName VARCHAR(256),a_TableName VARCHAR(256)); /********************************************************************************************************/ /*      */ /********************************************************************************************************/ CREATE OR REPLACE FUNCTION admtf_Table_Attributes (a_SchemaName VARCHAR(256) default 'public', /*     */ a_TableName VARCHAR(256) default NULL /*   */ ) RETURNS TABLE (r_AttributeNumber SMALLINT,r_AttributeName VARCHAR(256),r_UserTypeName VARCHAR(256),r_TypeName VARCHAR(256),r_isNotNULL BOOLEAN, r_Description Text) AS $BODY$ DECLARE c_TableKind CONSTANT CHAR:='r'; v_Scale INTEGER; /*   */ --****************************************************************************************************** BEGIN RETURN QUERY SELECT ta.r_AttributeNumber::SMALLINT, ta.r_AttributeName::VARCHAR(256), ta.r_UserTypeName::VARCHAR(256), ta.r_TypeName::VARCHAR(256), ta.r_isNotNULL::BOOLEAN, ta.r_Description::TEXT FROM admtf_Table_Attributes(a_SchemaName::NAME,a_TableName::NAME) ta; RETURN; END $BODY$ LANGUAGE plpgsql; COMMENT ON FUNCTION admtf_Table_Attributes(a_SchemaName VARCHAR(256),a_TableName VARCHAR(256)) IS '   '; --ROLLBACK TRANSACTION; COMMIT TRANSACTION; SELECT * FROM admtf_Table_Attributes('public'::VARCHAR(256),'Street'::VARCHAR(256)); SELECT * FROM admtf_Table_Attributes('public'::NAME,'Street'::NAME); 


Création de la fonction admtf_Table_Attributes à l'aide de l'alias Regclass


Vous trouverez des commentaires sur le code source de la fonction ici.
code source de la fonction
 BEGIN TRANSACTION; DROP FUNCTION IF EXISTS admtf_Table_Attributes (a_SchemaName NAME,a_TableName NAME); /********************************************************************************************************/ /*      */ /********************************************************************************************************/ CREATE OR REPLACE FUNCTION admtf_Table_Attributes (a_SchemaName NAME default 'public', /*     */ a_TableName NAME default NULL /*   */ ) RETURNS TABLE (r_AttributeNumber SMALLINT,r_AttributeName NAME,r_UserTypeName NAME,r_TypeName NAME,r_isNotNULL BOOLEAN, r_Description Text) AS $BODY$ DECLARE c_TableKind CONSTANT CHAR:='r'; v_Scale INTEGER; /*   */ --****************************************************************************************************** BEGIN RETURN QUERY SELECT attr.attnum AS r_AttributeNumber, attr.attname::NAME AS r_AttributeName, CASE WHEN COALESCE(typ.typbasetype,0)>0 THEN typ.typname::NAME ELSE ''::NAME END AS r_UserTypeName, FORMAT_TYPE(COALESCE(NULLIF(typ.typbasetype,0),typ.oid), COALESCE(NULLIF(typ.typtypmod,-1),attr.atttypmod))::NAME AS r_TypeName, attr.attnotnull AS r_isNotNULL, dsc.description AS r_Description FROM pg_attribute attr INNER 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=(LOWER(a_SchemaName)||'.'|| LOWER(a_TableName))::regclass AND attr.attnum>0 AND attr.atttypID>0 ORDER BY attr.attnum; RETURN; END $BODY$ LANGUAGE plpgsql; COMMENT ON FUNCTION admtf_Table_Attributes(a_SchemaName NAME,a_TableName NAME) IS '   '; --ROLLBACK TRANSACTION; COMMIT TRANSACTION; BEGIN TRANSACTION; DROP FUNCTION IF EXISTS admtf_Table_Attributes (a_SchemaName VARCHAR(256),a_TableName VARCHAR(256)); /********************************************************************************************************/ /*      */ /********************************************************************************************************/ CREATE OR REPLACE FUNCTION admtf_Table_Attributes (a_SchemaName VARCHAR(256) default 'public', /*     */ a_TableName VARCHAR(256) default NULL /*   */ ) RETURNS TABLE (r_AttributeNumber SMALLINT,r_AttributeName VARCHAR(256),r_UserTypeName VARCHAR(256),r_TypeName VARCHAR(256),r_isNotNULL BOOLEAN, r_Description Text) AS $BODY$ DECLARE c_TableKind CONSTANT CHAR:='r'; v_Scale INTEGER; /*   */ --****************************************************************************************************** BEGIN RETURN QUERY SELECT ta.r_AttributeNumber::SMALLINT, ta.r_AttributeName::VARCHAR(256), ta.r_UserTypeName::VARCHAR(256), ta.r_TypeName::VARCHAR(256), ta.r_isNotNULL::BOOLEAN, ta.r_Description::TEXT FROM admtf_Table_Attributes(a_SchemaName::NAME,a_TableName::NAME) ta; RETURN; END $BODY$ LANGUAGE plpgsql; COMMENT ON FUNCTION admtf_Table_Attributes(a_SchemaName VARCHAR(256),a_TableName VARCHAR(256)) IS '   '; --ROLLBACK TRANSACTION; COMMIT TRANSACTION; SELECT * FROM admtf_Table_Attributes('public'::VARCHAR(256),'Street'::VARCHAR(256)); SELECT * FROM admtf_Table_Attributes('public'::NAME,'Street'::NAME); 



ANNEXE 2. Documents supplémentaires


Schéma de base de données auxiliaire





  • PAYS - Classificateur des pays du monde - OKSM (Classification panrusse des pays du monde);
  • HOUSEADDR - Liste des numéros de maison dans les rues des colonies;
  • LCLTYTYPE - Répertoire des types de colonies;
  • LOCALITÉ - Liste des établissements;
  • STREET — ;
  • STREETTYPE — ;
  • TERRITORY — (, , , ..);
  • TERRITORYTYPE — .



Street ()


.
1. Street ().

CatégorieNon.Le titreCommentairetypeType de base? pas nul
tbl0rueListe des rues dans les colonies
att1wcrccodeCode payswcrccodesmallintt
att2localityidID de communautélocalityidentiert
att3streetidID rue du villagestreetidsmallintt
att4streettypeacrmAcronyme de la ruestreettypeacrmpersonnage (8)f
att5nom de ruestreettypeacrmvarchar(150)t
pk0xpkstreetstreet
pkatt1wcrccodewcrccodesmallintt
pkatt2localityidlocalityidintegert
pkatt3streetidstreetidsmallintt
fk011fk_street_locality
fk01att1wcrccodewcrccodesmallintt
fk01att2localityidlocalityidintegert
fk01rtbl0locality
fk01ratt1wcrccodewcrccodesmallintt
fk01ratt2localityidlocalityidintegert
fk022fk_street_streettype
fk02att1streettypeacrmstreettypeacrmcharacter(8)f
fk02rtbl0streettype
fk02ratt1streettypeacrmstreettypeacrmcharacter(8)t
idx011xie1street
idx01att1wcrccodewcrccodesmallintt
idx01att2localityidlocalityidintegert
idx01att3streettypeacrmstreettypeacrmcharacter(8)f
idx01att4streetnamevarchar(150)t
idx022xie2street
idx02att1wcrccodewcrccodesmallint
idx02att2localityidlocalityidintegert
idx02att3streetnamevarchar(150)t
idx033xie3street
idx03att1streetnamevarchar(150)t
idx044xpkstreet( ) street
idx04att1wcrccodewcrccodesmallintt
idx04att2localityidlocalityidintegert
idx04att3streetidstreetidsmallintt


Voir aussi


Fonctions de documentation des bases de données PostgreSQL. ;
Fonctions de documentation des bases de données PostgreSQL. Troisième partie .
Fonctions de documentation des bases de données PostgreSQL. La fin (quatrième partie) .

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


All Articles