Chaque catalogue qui a des données initiales créées manuellement (certains
   n'en ont pas) a un fichier .dat correspondant qui contient
   ses données initiales dans un format éditable.
  
    Chaque fichier .dat contient des structures de données
    Perl littérales qui sont simplement évaluées pour produire une structure
    de données en mémoire qui consiste en un tableau de références de hash, un
    par ligne de catalogue.  Un extrait de pg_database.dat
    légèrement modifié va vous décrire les fonctionnalités principales :
   
[
# A comment could appear here.
{ oid => '1', oid_symbol => 'Template1DbOid',
  descr => 'database\'s default template',
  datname => 'template1', encoding => 'ENCODING',
  datlocprovider => 'LOCALE_PROVIDER', datistemplate => 't',
  datallowconn => 't', datconnlimit => '-1', datfrozenxid => '0',
  datminmxid => '1', dattablespace => 'pg_default', datcollate => 'LC_COLLATE',
  datctype => 'LC_CTYPE', daticulocale => 'ICU_LOCALE', datacl => '_null_' },
]
   Les points à noter :
La structure générale du fichier est : crochet ouvrant, un ensemble ou plus d'accolades qui chacune représentent une ligne de catalogue, crochet fermant. Il faut mettre une virgule après chaque accolade fermante.
      Au sein de chaque ligne de catalogue, écrivez des paires de
      clé =>
      valeur séparées par des virgules.  Les
      clés autorisées sont les noms des colonnes du
      catalogue, ainsi que les clés de métadonnées oid,
      oid_symbol, array_type_oid et
      descr. (L'utilisation de oid et
      oid_symbol est décrite dans Section 75.2.2 ci-dessous, alors que
      array_type_oid est décrite dans Section 75.2.4. descr
      fournit une chaîne de texte de description pour l'objet, qui sera
      insérée dans pg_description ou
      pg_shdescription selon le cas.)
      Bien que les clés de métadonnées soient facultatives, les colonnes
      définies pour le catalogue doivent toutes être fournies, sauf pour le cas
      où le fichier .h du catalogue définit une valeur par
      défaut pour la colonne.
      (Dans l'exemple ci-dessus, le champ datdba a
      été volontairement omis car pg_database.h en fournit
      une valeur appropriée par défaut.)
     
      Toutes les valeurs doivent être entourées de guillemets simples.  Il faut
      échapper les guillemets simples utilisés au sein d'une valeur avec un
      antislash.  Les antislash qui doivent être utilisés comme une donnée
      peuvent être doublés, mais cela n'est pas nécessaire ; cela correspond aux
      règles Perl pour les littéraux entourés d'un guillemet simple.  Veuillez
      noter que les antislash apparaissant comme données seront traités comme
      des échappements par le scanner du « bootstrap », d'après les mêmes règles que
      pour les échappements de chaînes de texte constantes (voir
      Section 4.1.2.2) ; par exemple
      \t est converti en un caractère tabulation.  Si vous
      voulez un antislash dans la valeur finale, il vous faudra en écrire
      quatre : Perl en retire deux, laissant \\ pour le
      scanner « bootstrap ».
     
      Les valeurs NULL sont représentées par _null_.
      (Veuillez noter qu'il n'y a aucun moyen de créer une valeur qui est
      simplement cette chaîne de texte.)
     
      Les commentaires sont précédés d'un #, et doivent être
      sur leur propre ligne.
     
      Les valeurs de champs référençant des OID d'autres entrées de catalogue
      devraient être représentées par des macros plutôt que par de vrais
      nombres OID. (Dans l'exemple ci-dessus,
      dattablespace contient une telle référence.)
      Cela est décrit dans Section 75.2.3
      ci-dessous.
     
      Puisque les hash sont des structures de données non triées, l'ordre des
      champs et des lignes ne sont pas sémantiquement significatifs.  Cependant,
      pour maintenir un aspect cohérent, nous définissions quelques règles qui
      sont appliquées par le script de formatage
      reformat_dat_file.pl :
      
         Au sein de chaque paire d'accolades, les champs de métadonnées
         oid, oid_symbol,
         array_type_oid
         et descr (si présent) apparaissent en premier, dans
         cet ordre, puis les champs propres au catalogue apparaissent dans leur
         ordre défini.
        
Des retours à la ligne sont insérés entre les champs selon le besoin pour limiter la longueur de ligne à 80 caractères, si cela est possible. Un retour à la ligne est également inséré entre les champs de métadonnées et les champs normaux.
         Si le fichier de catalogue .h spécifie une valeur
         par défaut pour la colonne, et qu'une entrée de donnée a la même
         valeur, reformat_dat_file.pl omettra cette valeur
         du fichier de données.  Cela conserve la représentation de données
         compacte.
        
         reformat_dat_file.pl conserve les lignes vides
         et les commentaires en l'état.
        
      Il est recommandé d'exécuter reformat_dat_file.pl
      avant de soumettre des patchs pour les données de catalogue.  Par
      commodité, vous pouvez simplement effectuer des changements dans
      src/include/catalog/ et exécuter
      make reformat-dat-files.
     
      Si vous voulez ajouter une nouvelle méthode pour diminuer la taille de
      de la représentation des données, vous devez l'implémenter dans
      reformat_dat_file.pl et également apprendre à
      Catalog::ParseData() comment remettre les données
      dans leur représentation complète.
     
    Il est possible de donner un OID manuellement assigné à une ligne de
    catalogue apparaissant dans les données initiales en écrivant un champ de
    métadonnées oid => .
    De plus, si un OID est assigné, une macro C pour cet OID peut être créée
    en écrivant un champ de métadonnée nnnnoid_symbol
     => .
   nom
    Les lignes de catalogues préchargées doivent avoir des OID pré-assignés s'il
    y a des références d'OID pointant vers elles dans d'autres lignes
    pré-chargées.  Un OID pré-assigné est également nécessaire si l'OID de la
    ligne doit être référencé depuis le code C.  Si aucun de ces cas ne
    s'applique, le champ de métadonnée oid peut être omis,
    auquel cas le code de « bootstrap » assignera un OID automatiquement. En pratique, nous
    pré-assignons généralement des OID pour soit toutes soit aucune des lignes
    d'un catalogue donné, même si seulement une partie des lignes sont vraiment
    référencées dans d'autres catalogues.
   
    Écrire la vraie valeur numérique d'un OID dans le code C est considéré comme
    une très mauvaise pratique ; il faut toujours utiliser une macro à la place.
    Des références directes à des OID de pg_proc sont
    suffisamment communes pour qu'il y ait un mécanisme spécial afin de créer
    les macros nécessaires automatiquement ; voir
    src/backend/utils/Gen_fmgrtab.pl.  De même
     --  mais, pour raisons historiques, fait d'une autre manière  -- 
    il y a une méthode automatique pour créer les macros pour les OID de
    pg_type.  Les entrées de
    oid_symbol ne sont donc pas forcément dans ces deux
    catalogues.  De la même manière, les macros pour les OID de catalogue
    système et index pg_class sont positionnés
    automatiquement.  Pour tous les autres catalogues systèmes, vous devez
    spécifier manuellement toute macro dont vous avez besoin avec les entrées
    oid_symbol.
   
    Pour trouver un OID disponible pour une nouvelle ligne préchargée, exécutez
    le script src/include/catalog/unused_oids.  Il affiche
    l'intervalle inclusif d'OID inutilisés (par exemple, la ligne en sortie
    45-900 signifie que les OID 45 jusqu'à 900 n'ont pas encore
    été alloués).  Pour le moment, les OID 1–9999 sont réservés pour des
    allocations manuelles ; le script unused_oids regarde
    simplement dans les en-têtes de catalogue et les fichiers
    .dat pour voir lesquels n'apparaissent pas.  Vous
    pouvez également utiliser le script duplicate_oids pour
    trouver des erreurs.  (genbki.pl va allouer des OID
    à toutes les lignes qui n'en auraient pas reçu manuellement, et va aussi
    détecter les OID dupliqués au moment de la compilation.)
   
    Lors du choix d'OID pour l'écriture d'un patch qui n'est pas supposé être
    validé immédiatement, la bonne pratique est d'utiliser un groupe d'OID
    plus-ou-moins consécutifs en commençant par un choix aléatoire dans
    l'intervalle 8000 -- 9999. Cela minimise le risque de collisions d'OID
    avec d'autres patchs développés en parallèle. Pour garder l'intervalle
    8000 -- 9999 libre pour le développement, après qu'un patch ait été
    validé sur le dépôt git principal, ces OID doivent être renumérotés dans
    un intervalle inférieur libre. Typiquement, cela sera fait à l'approche
    de la fin de chaque cycle de développement, déplaçant tous les OID
    consommés par des patchs validés lors de ce cycle en même temps. Le script
    renumber_oids.pl peut être utilisé pour faire cela.
    Si un patch non validé contient des OID en conflit avec un patch récemment
    validé, renumber_oids.pl peut aussi être utile pour
    rétablir une telle situation.
   
À cause de cette convention de renumérotation des OID consommés par les patchs, les OID attribués à un patch ne doivent pas être considérés comme stables jusqu'à ce que celui-ci ait été inclus dans une version officielle. Nous ne changeons toutefois pas les OID assignés manuellement une fois la version sortie, car cela pourrait engendrer des problèmes de compatibilité.
    Si genbki.pl a besoin d'assigner un OID à un
    enregistrement du catalogue ne pouvant donc être un OID assigné
    manuellement, il utilisera une valeur de l'intervalle 10000 -- 11999.  Le
    compteur des OID serveur est défini à 10000 au début d'une phase de
    « bootstrap », pour que tout objet créé à la volée lors du
    traitement du « bootstrap » reçoive aussi un OID dans cet
    intervalle. (Le mécanisme habituel d'attribution des OID fait attention à
    prévenir tout conflit.).
   
    Les objets dont l'OID est en-dessous de
    FirstUnpinnedObjectId (12000) sont considérés comme
    « fixes », les empêchant d'être supprimés.  (Il existe un petit
    nombre d'exceptions, qui sont gérées en dur par la fonction
    IsPinnedObject().) initdb
    force le compteur d'OID à FirstUnpinnedObjectId dès qu'il
    est prêt à créer des objets non fixes. De ce fait, les objets créés dans les
    phases ultérieures de initdb, comme des objets
    créés lors de l'exécution du script
    information_schema.sql, ne seront pas fixes alors que
    tous les objets connus de genbki.pl le seront.
   
    Les OID assignés durant les opérations normales de la base de données
    sont contraints entre 16384 et plus. Cela assure que l'intervalle
    10000 -- 16383 soit libre pour l'assignation automatique d'OID par
    genbki.pl ou durant l'« initdb ». Ces
    OID assignés automatiquement ne sont pas considérés comme stables, et
    peuvent changer d'une installation à l'autre.
   
    En principe, la référence d'une ligne de catalogue vers une autre pourrait
    être écrite juste en se servant de l'OID pré-assigné de la ligne à
    référencer dans le champ la référençant. Cependant, cela va à l'encontre
    de la politique du projet, car sujet aux erreurs, difficile à lire et
    source d'incohérence si un OID nouvellement assigné est renuméroté.
    C'est pourquoi genbki.pl fournit un mécanisme de
    génération de macros à utiliser à la place.
    Les règles sont les suivantes :
   
      L'utilisation de références symboliques est activée pour une colonne
      en particulier en attachant
      BKI_LOOKUP(
      à la définition de la colonne, où lookuprule)lookuprule
      est le nom du catalogue référencé, par exemple pg_proc.
      BKI_LOOKUP peut être attaché aux colonnes de type
      Oid, regproc, oidvector,
      ou Oid[] ; dans les deux derniers cas, cela implique
      d'effectuer une recherche pour chaque élément du tableau.
     
      Dans certaines colonnes du catalogue, des entrées à zéro sont permises à
      la place d'une référence valide. Si cela est permis, écrivez
      BKI_LOOKUP_OPT au lieu de
      BKI_LOOKUP. Ainsi, vous pouvez écrire
      0 dans une entrée. (Si la colonne est déclarée
      regproc, vous pouvez optionnellement écrire
      - au lieu de 0.) En dehors de ce
      cas spécial, toutes les entrées dans une colonne
      BKI_LOOKUP doivent être une référence symbolique.
      genbki.pl vous avertira à propos des noms non
      reconnus.
     
      Il est également permis d'attacher BKI_LOOKUP(encoding)
      aux colonnes de type entier pour référencer les encodages de caractères,
      ce qui n'est actuellement pas représenté par des OID de catalogue, mais
      par un ensemble de valeurs connues de genbki.pl.
     
      La plupart des types d'objets du catalogue sont référencées par leurs noms.
      Notez que ces noms doivent être strictement identiques aux entrées
      typname de pg_type;
      vous ne pouvez pas utiliser d'alias comme integer à
      la place de int4.
     
      Une fonction peut être représentée par son
      proname, s'il est unique parmi les entrées
      de pg_proc.dat (cela fonctionne comme les entrées
      regproc).  Sinon, écrivez-les sous la forme
      proname(argtypename,argtypename,...), comme
      pour regprocedure.  Les noms de type des arguments doivent être écrits
      exactement comme ils le sont dans les champs
      proargtypes des entrées de
      pg_proc.dat.  N'insérez aucun espace.
     
      Les opérateurs sont représentés par
      oprname(lefttype,righttype),
      en écrivant les noms de type exactement comme ils apparaissent dans les
      oprleft et oprright
      des entrées de
      pg_operator.dat.
      (Écrivez 0 pour les opérandes omises d'un opérateur
      unaire.)
     
      Les noms des classes et familles d'opérateur ne sont uniques qu'au sein
      d'une méthode d'accès, elles sont donc représentées avec
      nom_methode_acces/nom_objet.
     
      Il n'est prévu de qualification par le schéma pour aucun de ces cas ;
      tous les objets créés durant le « bootstrap » sont prévus pour être dans le
      schéma pg_catalog.
     
    genbki.pl résout toutes les références symboliques
    pendant son exécution, et inscrit de simples OID numériques dans les
    fichiers BKI émis.  Le processus client de « bootstrap » n'a donc pas besoin
    de gérer les références symboliques.
   
    Il est recommandé de marquer les colonnes de référence OID avec
    BKI_LOOKUP ou BKI_LOOKUP_OPT même
    si le catalogue n'a pas de données initiales nécessitant une recherche.
    Ceci permet à genbki.pl d'enregistrer les clés
    étrangères des relations qui existent dans le catalogue système. Cette
    information est utilisée dans les tests de régression pour vérifier les
    entrées incorrectes. Voir aussi les macros
    DECLARE_FOREIGN_KEY,
    DECLARE_FOREIGN_KEY_OPT,
    DECLARE_ARRAY_FOREIGN_KEY, et
    DECLARE_ARRAY_FOREIGN_KEY_OPT, qui sont utilisées pour
    déclarer les clés étrangères des relations qui sont trop complexes pour
    BKI_LOOKUP (typiquement, des clés étrangères
    multi-colonnes).
   
    La plupart des types de données scalaires devraient avoir un type tableau
    correspondant (en fait, un type de tableau « varlena » standard,
    dont le type d'élément est un scalaire référencé par le champ
    typarray de l'entrée de type scalaire de
    pg_type). genbki.pl est
    capable de générer l'entrée de pg_type pour le
    type de tableau automatiquement dans la plupart des cas.
   
    Pour se servir de cette fonctionnalité, il suffit d'inscrire un champ de
    méta-données array_type_oid=> 
    dans l'entrée de type scalaire de nnnnpg_type,
    spécifiant l'OID à utiliser pour le type de tableau. Vous pouvez ensuite
    omettre le champ typarray, puisque l'OID y sera
    automatiquement renseigné.
   
    Le nom du type de tableau généré est le nom du type scalaire préfixé du
    tiret bas. Les autres champs du type de tableau sont remplis par les
    annotations BKI_ARRAY_DEFAULT(
    de value)pg_type.h, ou s'il n'y en a pas, copiés du type
    scalaire. (Il y a aussi un cas particulier pour typalign.)
    Ensuite, les champs typelem et
    typarray des deux enregistrements sont
    positionnés afin de se référencer l'un et l'autre.
   
Voici quelques suggestions pour les moyens les plus simples d'effectuer des tâches communes lors de la mise à jour de fichiers de données du catalogue.
Ajouter une nouvelle colonne avec valeur par défaut à un
     catalogue : 
     Ajoutez la colonne au fichier d'en-tête avec une annotation
     BKI_DEFAULT(
     Le fichier de données ne doit être ajusté en ajoutant le champ dans les
     lignes existantes que quand il est nécessaire d'avoir autre chose que la
     valeur par défaut.
    valeur)
Ajouter une valeur par défaut à une colonne existante qui n'en a
     pas : 
     Ajoutez une annotation BKI_DEFAULT au fichier d'en-tête,
     puis exécutez make reformat-dat-files pour supprimer les
     entrées de champ qui sont maintenant redondantes.
    
Ajouter une colonne, qu'elle ait une valeur par défaut ou
     non : 
     Supprimez la colonne de l'en-tête, puis exécutez make
      reformat-dat-files pour supprimer les entrées du champ maintenant
     inutiles.
    
Changer ou supprimer une valeur par défaut existante : 
     Vous ne pouvez pas simplement changer le fichier d'en-tête, puisque cela
     aurait pour conséquence une mauvaise interprétation des données actuelles.
     Tout d'abord, exécutez make expand-dat-files pour
     réécrire les fichiers de données avec toutes les valeurs par défaut
     insérées explicitement, puis modifiez ou supprimez l'annotation
     BKI_DEFAULT, puis exécutez make
      reformat-dat-files pour supprimer à nouveau les champs superflus.
    
Édition en masse ad hoc : 
     reformat_dat_file.pl peut être modifié pour effectuer
     différents types de changements en masse.  Cherchez les commentaires de
     blocs montrant où du code unique peut être inséré.  Dans l'exemple suivant,
     nous allons consolider deux champs booléens de
     pg_proc en un champ de type char :
     
        Ajout de la nouvelle colonne, avec une valeur par défaut, à
        pg_proc.h:
        
+    /* see PROKIND_ categories below */
+    char        prokind BKI_DEFAULT(f);
        
        Création d'un nouveau script basé sur
        reformat_dat_file.pl pour insérer les valeurs
        appropriées à la volée :
        
-           # At this point we have the full row in memory as a hash
-           # and can do any operations we want. As written, it only
-           # removes default values, but this script can be adapted to
-           # do one-off bulk-editing.
+           # One-off change to migrate to prokind
+           # Default has already been filled in by now, so change to other
+           # values as appropriate
+           if ($values{proisagg} eq 't')
+           {
+               $values{prokind} = 'a';
+           }
+           elsif ($values{proiswindow} eq 't')
+           {
+               $values{prokind} = 'w';
+           }
        
Lancement du nouveau script :
$ cd src/include/catalog
$ perl  rewrite_dat_with_prokind.pl  pg_proc.dat
        
        À cette étape, pg_proc.dat a la totalité des trois
        colonnes, prokind,
        proisagg
        et proiswindow, bien qu'elles n'apparaîtront
        que dans les lignes où elles ont des valeurs qui ne sont pas la valeur
        par défaut.
       
        Suppression de l'ancienne colonne de pg_proc.h :
        
-    /* is it an aggregate? */
-    bool        proisagg BKI_DEFAULT(f);
-
-    /* is it a window function? */
-    bool        proiswindow BKI_DEFAULT(f);
        
        Finalement, exécution de make reformat-dat-files
        pour supprimer les anciennes entrées inutiles de
        pg_proc.dat.
       
     Pour plus d'exemples de scripts utilisés pour l'édition en masse, voir
     convert_oid2name.pl
     et remove_pg_type_oid_symbols.pl joints au message
     suivant :
     https://www.postgresql.org/message-id/CAJVSVGVX8gXnPm+Xa=DxR7kFYprcQ1tNcCT5D0O3ShfnM6jehA@mail.gmail.com