Documentation PostgreSQL 15.15 » Annexes » Modules supplémentaires fournis » pageinspect

Précédent | Niveau supérieur | Suivant
F.24. old_snapshot | Sommaire | F.26. passwordcheck

## F.25. pageinspect

Le module `pageinspect` fournit des fonctions qui vous permettent d'inspecter le contenu des pages de la base de données à un bas niveau, ce qui est utile pour le débogage. Toutes ces fonctions ne sont utilisables que par les superutilisateurs.

### F.25.1. Fonctions générales

`get_raw_page(relname text, fork text, blkno bigint) returns bytea`

  `get_raw_page` lit le bloc spécifié de la relation nommée et renvoie une copie en tant que valeur de type `bytea`. Ceci permet la récupération de la copie cohérente à un instant t d'un bloc spécifique. `fork` devrait être `'main'` pour les données, et `'fsm'` pour la carte des espaces libres, `'vm'` pour la carte de visibilité ou `'init'` pour le fichier d'initialisation.

`get_raw_page(relname text, blkno bigint) returns bytea`

  Une version raccourcie de `get_raw_page`, pour ne lire que la partie des données. Équivalent à `get_raw_page(relname, 'main', blkno)`.

`page_header(page bytea) returns record`

  `page_header` affiche les champs communs à toutes les pages des tables et index PostgreSQL.

  L'image d'une page obtenu avec `get_raw_page` doit être passé en argument. Par exemple :

      test=# SELECT * FROM page_header(get_raw_page('pg_class', 0));
          lsn    | checksum | flags  | lower | upper | special | pagesize | version | prune_xid
      -----------+----------+--------+-------+-------+---------+----------+---------+-----------
       0/24A1B50 |        0 |      1 |   232 |   368 |    8192 |     8192 |       4 |         0

  Les colonnes renvoyées correspondent aux champs de la structure `PageHeaderData`. Voir `src/include/storage/bufpage.h` pour les détails.

  Le champ `checksum` est la somme de contrôle stockée dans la page, qui peut être incorrecte si la page est d'une manière ou d'une autre corrompue. Si les sommes de contrôle des données ne sont pas activées pour cette instance, alors la valeur stockée n'a aucune signification.

`page_checksum(page bytea, blkno bigint4) returns smallint`

  `page_checksum` calcule la somme de contrôle pour la page, comme si elle était citée au numéro de bloc passé en paramètre.

  Une image de page obtenue avec `get_raw_page` devrait être passée en argument. Par exemple :

      test=# SELECT page_checksum(get_raw_page('pg_class', 0), 0);
       page_checksum
      ---------------
               13443

  Veuillez noter que la somme de contrôle dépend du numéro de bloc, ainsi des numéros de blocs qui se correspondent devraient être passé (sauf lors de débugage ésotériques).

  Les sommes de contrôle calculées avec cette fonction peuvent être comparées avec le champ `checksum` retournée par la fonction `page_header`. Si les sommes de contrôle des données sont activées sur cette instance, alors les deux valeurs devraient être égales.

`fsm_page_contents(page bytea) returns text`

  `fsm_page_contents` montre la structure interne du nœud d'une page FSM. Par exemple :

      test=# SELECT fsm_page_contents(get_raw_page('pg_class', 'fsm', 0));

  La sortie est une chaîne de texte multiligne, avec une ligne par nœud dans l'arbre binaire au sein de la page. Seuls ces nœuds qui ne valent pas zéro sont affichés. Le pointeur appelé « next », qui pointe vers le prochain slot à être retourné depuis la page, est également affiché.

  Voir `src/backend/storage/freespace/README` pour plus d'information sur la structure d'une page FSM.

### F.25.2. Fonctions Heap

`heap_page_items(page bytea) returns setof record`

  `heap_page_items` affiche tous les pointeurs de ligne dans une page de table. Pour les pointeurs de ligne en utilisation, les en-têtes de ligne ainsi que les données des lignes sont aussi affichées. Toutes les lignes sont affichées, qu'elles soient ou non visibles dans l'image MVCC au moment où la page brute a été copiée.

  Une image d'une page de table obtenue avec `get_raw_page` doit être fournie en argument. Par exemple :

      test=# SELECT * FROM heap_page_items(get_raw_page('pg_class', 0));

  Voir `src/include/storage/itemid.h` et `src/include/access/htup_details.h` pour des explications sur les champs renvoyés.

  La fonction `heap_tuple_infomask_flags` peut être utilisée pour déchiffrer les drapeaux de `t_infomask` et `t_infomask2` pour les lignes de la table.

`tuple_data_split(rel_oid oid, t_data bytea, t_infomask integer, t_infomask2 integer, t_bits text [, do_detoast bool]) returns bytea[]`

  `tuple_data_split` divise les données d'une ligne en attributs de la même façon que le fait le moteur.

      test=# SELECT tuple_data_split('pg_class'::regclass, t_data, t_infomask, t_infomask2, t_bits) FROM heap_page_items(get_raw_page('pg_class', 0));

  Cette fonction doit être appelée avec les mêmes arguments que ce qui est renvoyé par `heap_page_items`.

  Si `do_detoast` est `true`, la donnée TOAST sera traitée. La valeur par défaut est `false`.

`heap_page_item_attrs(page bytea, rel_oid regclass [, do_detoast bool]) returns setof record`

  `heap_page_item_attrs` est équivalent à `heap_page_items` sauf qu'elle renvoie les données brutes de la ligne sous la forme d'un tableau d'attributs pouvant en option être traités par `do_detoast` (comportement désactivé par défaut).

  Une image de la page HEAP obtenue avec `get_raw_page` doit être fournie comme argument. Par exemple :

      test=# SELECT * FROM heap_page_item_attrs(get_raw_page('pg_class', 0), 'pg_class'::regclass);

`heap_tuple_infomask_flags(t_infomask integer, t_infomask2 integer) returns record`

  `heap_tuple_infomask_flags` décode les champs `t_infomask` et `t_infomask2` renvoyés par `heap_page_items` en un ensemble de tableaux composés de noms de drapeau, lisibles par un humain, avec une colonne pour tous les drapeaux et une colonne pour les drapeaux composés. Par exemple :

      test=# SELECT t_ctid, raw_flags, combined_flags
               FROM heap_page_items(get_raw_page('pg_class', 0)),
                 LATERAL heap_tuple_infomask_flags(t_infomask, t_infomask2)
               WHERE t_infomask IS NOT NULL OR t_infomask2 IS NOT NULL;

  Cette fonction doit être appelée avec les mêmes arguments que les attributes de retour de `heap_page_items`.

  Les drapeaux combinés sont affichés pour les macros de niveau source prenant en compte la valeur de plus d'un bit, comme par exemple `HEAP_XMIN_FROZEN`.

  Voir `src/include/access/htup_details.h` pour des explications sur les noms des drapeaux renvoyés.

### F.25.3. Fonctions B-tree

`bt_metap(relname text) returns record`

  `bt_metap` renvoie des informations sur une méta-page d'un index B-tree. Par exemple :

      test=# SELECT * FROM bt_metap('pg_cast_oid_index');
      -[ RECORD 1 ]-------------+-------
      magic                     | 340322
      version                   | 4
      root                      | 1
      level                     | 0
      fastroot                  | 1
      fastlevel                 | 0
      last_cleanup_num_delpages | 0
      last_cleanup_num_tuples   | 230
      allequalimage             | f

`bt_page_stats(relname text, blkno bigint) returns record`

  `bt_page_stats` renvoie un résumé des informations sur les pages enfants des index B-tree. Par exemple :

      test=# SELECT * FROM bt_page_stats('pg_cast_oid_index', 1);
      -[ RECORD 1 ]-+-----
      blkno         | 1
      type          | l
      live_items    | 224
      dead_items    | 0
      avg_item_size | 16
      page_size     | 8192
      free_size     | 3668
      btpo_prev     | 0
      btpo_next     | 0
      btpo_level    | 0
      btpo_flags    | 3

`bt_page_items(relname text, blkno bigint) returns setof record`

  `bt_page_items` renvoie des informations détaillées sur tous les éléments d'une page d'index B-tree. Par exemple :

      test=# SELECT itemoffset, ctid, itemlen, nulls, vars, data, dead, htid, tids[0:2] AS some_tids
              FROM bt_page_items('tenk2_hundred', 5);
       itemoffset |   ctid    | itemlen | nulls | vars |          data           | dead |  htid  |      some_tids
      ------------+-----------+---------+-------+------+-------------------------+------+--------+---------------------
                1 | (16,1)    |      16 | f     | f    | 30 00 00 00 00 00 00 00 |      |        |
                2 | (16,8292) |     616 | f     | f    | 24 00 00 00 00 00 00 00 | f    | (1,6)  | {"(1,6)","(10,22)"}
                3 | (16,8292) |     616 | f     | f    | 25 00 00 00 00 00 00 00 | f    | (1,18) | {"(1,18)","(4,22)"}
                4 | (16,8292) |     616 | f     | f    | 26 00 00 00 00 00 00 00 | f    | (4,18) | {"(4,18)","(6,17)"}
                5 | (16,8292) |     616 | f     | f    | 27 00 00 00 00 00 00 00 | f    | (1,2)  | {"(1,2)","(1,19)"}
                6 | (16,8292) |     616 | f     | f    | 28 00 00 00 00 00 00 00 | f    | (2,24) | {"(2,24)","(4,11)"}
                7 | (16,8292) |     616 | f     | f    | 29 00 00 00 00 00 00 00 | f    | (2,17) | {"(2,17)","(11,2)"}
                8 | (16,8292) |     616 | f     | f    | 2a 00 00 00 00 00 00 00 | f    | (0,25) | {"(0,25)","(3,20)"}
                9 | (16,8292) |     616 | f     | f    | 2b 00 00 00 00 00 00 00 | f    | (0,10) | {"(0,10)","(0,14)"}
               10 | (16,8292) |     616 | f     | f    | 2c 00 00 00 00 00 00 00 | f    | (1,3)  | {"(1,3)","(3,9)"}
               11 | (16,8292) |     616 | f     | f    | 2d 00 00 00 00 00 00 00 | f    | (6,28) | {"(6,28)","(11,1)"}
               12 | (16,8292) |     616 | f     | f    | 2e 00 00 00 00 00 00 00 | f    | (0,27) | {"(0,27)","(1,13)"}
               13 | (16,8292) |     616 | f     | f    | 2f 00 00 00 00 00 00 00 | f    | (4,17) | {"(4,17)","(4,21)"}
      (13 rows)

  Ceci est une page feuille B-tree. Tous les enregistrements qui pointent vers la table sont des éléments de la liste d'éléments (qui, chacune, stocke un total de 100 TID de 6 octets). Il existe aussi un enregistrement « clé haute » sur l'`itemoffset` numéro 1. `ctid` est utilisé pour enregistrer des informations codées sur chaque enregistrement dans cet exemple, bien que les enregistrements des pages feuilles enregistrent souvent directement le TID de la table dans le champ `ctid`. `tids` est la liste de TID enregistrée sous la forme d'une liste d'éléments.

  Dans un bloc interne (non affiché), la partie du numéro de bloc dans le champ `ctid` esy un lien inférieur (« downlink »), qui est un numéro de bloc vers un autre bloc de l'index lui-même. La partie décalage (offset, le deuxième nombre) du champ `ctid` enregistre des informations codées sur l'enregistrement, telle que le nombre de colonnes présentes (le troncage du suffixe pourrait avoir supprimé des colonnes de suffixe inutiles). Les colonnes tronquées sont traitées comme ayant la valeur « moins infini ».

  `htid` affiche un TID de table pour l'enregistrement, quelque soit la représentation sous-jacente de l'enregistrement. Cette valeur peut correspondre à un `ctid` ou peut être décodée parmi les représentations alternatives utilisées par les enregistrements des listes d'éléments et par les enregistrements des pages internes. Les enregistrements dans les pages internes ont habituellement la colonne TID de la table tronquée, ce qui est représenté comme une valeur `htid` NULL.

  Notez que le premier élément une page (autre que la dernière, toute page avec une valeur différente de zéro dans le champ `btpo_next`) est la « clé haute » du bloc, ce qui signifie que ces données (`data`) serve comme limite haute de tous les éléments apparaissant sur la page, alors que son champ `ctid` ne pointe pas vers un autre bloc. De plus, sur les pages internes, le premier véritable élément de donnée (le premier élément qui n'est pas une clé haute) a chaque colonne tronquée, laissant aucune valeur réelle dans son champ `data`. Néanmoins, un tel élément n'a pas de lien inférieur valide dans son champ `ctid`.

  Pour plus de détails sur la structure des index B-tree, voir Section 67.4.1. Pour plus de détails sur la déduplication et les listes d'éléments, voir Section 67.4.3.

`bt_page_items(page bytea) returns setof record`

  Il est également possible de passer une page à `bt_page_items` comme une valeur de type `bytea`. Une image de page obtenue avec `get_raw_page` devrait être passé en argument. Ainsi le précédent exemple pourrait également être réécrit ainsi :

      test=# SELECT itemoffset, ctid, itemlen, nulls, vars, data, dead, htid, tids[0:2] AS some_tids
              FROM bt_page_items(get_raw_page('tenk2_hundred', 5));
       itemoffset |   ctid    | itemlen | nulls | vars |          data           | dead |  htid  |      some_tids
      ------------+-----------+---------+-------+------+-------------------------+------+--------+---------------------
                1 | (16,1)    |      16 | f     | f    | 30 00 00 00 00 00 00 00 |      |        |
                2 | (16,8292) |     616 | f     | f    | 24 00 00 00 00 00 00 00 | f    | (1,6)  | {"(1,6)","(10,22)"}
                3 | (16,8292) |     616 | f     | f    | 25 00 00 00 00 00 00 00 | f    | (1,18) | {"(1,18)","(4,22)"}
                4 | (16,8292) |     616 | f     | f    | 26 00 00 00 00 00 00 00 | f    | (4,18) | {"(4,18)","(6,17)"}
                5 | (16,8292) |     616 | f     | f    | 27 00 00 00 00 00 00 00 | f    | (1,2)  | {"(1,2)","(1,19)"}
                6 | (16,8292) |     616 | f     | f    | 28 00 00 00 00 00 00 00 | f    | (2,24) | {"(2,24)","(4,11)"}
                7 | (16,8292) |     616 | f     | f    | 29 00 00 00 00 00 00 00 | f    | (2,17) | {"(2,17)","(11,2)"}
                8 | (16,8292) |     616 | f     | f    | 2a 00 00 00 00 00 00 00 | f    | (0,25) | {"(0,25)","(3,20)"}
                9 | (16,8292) |     616 | f     | f    | 2b 00 00 00 00 00 00 00 | f    | (0,10) | {"(0,10)","(0,14)"}
               10 | (16,8292) |     616 | f     | f    | 2c 00 00 00 00 00 00 00 | f    | (1,3)  | {"(1,3)","(3,9)"}
               11 | (16,8292) |     616 | f     | f    | 2d 00 00 00 00 00 00 00 | f    | (6,28) | {"(6,28)","(11,1)"}
               12 | (16,8292) |     616 | f     | f    | 2e 00 00 00 00 00 00 00 | f    | (0,27) | {"(0,27)","(1,13)"}
               13 | (16,8292) |     616 | f     | f    | 2f 00 00 00 00 00 00 00 | f    | (4,17) | {"(4,17)","(4,21)"}
      (13 rows)

  Tous les autres détails sont les même qu'expliqué au point précédent.

### F.25.4. Fonctions BRIN

`brin_page_type(page bytea) returns text`

  `brin_page_type` renvoie le type de bloc du bloc indiqué pour l'index BRIN donné ou renvoie une erreur si le bloc n'est pas un bloc valide d'un index BRIN. Par exemple :

      test=# SELECT brin_page_type(get_raw_page('brinidx', 0));
       brin_page_type
      ----------------
       meta

`brin_metapage_info(page bytea) returns record`

  `brin_metapage_info` renvoie une information assortie sur la métapage d'un index BRIN. Par exemple :

      test=# SELECT * FROM brin_metapage_info(get_raw_page('brinidx', 0));
         magic    | version | pagesperrange | lastrevmappage
      ------------+---------+---------------+----------------
       0xA8109CFA |       1 |             4 |              2

`brin_revmap_data(page bytea) returns setof tid`

  `brin_revmap_data` renvoie la liste des identifiants de lignes dans un bloc de type « range map » d'un index BRIN. Par exemple :

      test=# SELECT * FROM brin_revmap_data(get_raw_page('brinidx', 2)) LIMIT 5;
        pages
      ---------
       (6,137)
       (6,138)
       (6,139)
       (6,140)
       (6,141)

`brin_page_items(page bytea, index oid) returns setof record`

  `brin_page_items` renvoie les données enregistrées dans le bloc de données de l'index BRIN. Par exemple :

      test=# SELECT * FROM brin_page_items(get_raw_page('brinidx', 5),
                                           'brinidx')
             ORDER BY blknum, attnum LIMIT 6;
       itemoffset | blknum | attnum | allnulls | hasnulls | placeholder |    value
      ------------+--------+--------+----------+----------+-------------+--------------
              137 |      0 |      1 | t        | f        | f           |
              137 |      0 |      2 | f        | f        | f           | {1 .. 88}
              138 |      4 |      1 | t        | f        | f           |
              138 |      4 |      2 | f        | f        | f           | {89 .. 176}
              139 |      8 |      1 | t        | f        | f           |
              139 |      8 |      2 | f        | f        | f           | {177 .. 264}

  Les colonnes renvoyées correspondent aux champs des structures `BrinMemTuple` et `BrinValues`. Voir `src/include/access/brin_tuple.h` pour plus de détails.

### F.25.5. Fonctions GIN

`gin_metapage_info(page bytea) returns record`

  `gin_metapage_info` renvoie des informations sur la métapage d'un index GIN index metapage. Par exemple :

      test=# SELECT * FROM gin_metapage_info(get_raw_page('gin_index', 0));
      -[ RECORD 1 ]----+-----------
      pending_head     | 4294967295
      pending_tail     | 4294967295
      tail_free_size   | 0
      n_pending_pages  | 0
      n_pending_tuples | 0
      n_total_pages    | 7
      n_entry_pages    | 6
      n_data_pages     | 0
      n_entries        | 693
      version          | 2

`gin_page_opaque_info(page bytea) returns record`

  `gin_page_opaque_info` renvoie des informations sur la partie opaque d'un index GIN, comme le type de bloc. Par exemple :

      test=# SELECT * FROM gin_page_opaque_info(get_raw_page('gin_index', 2));
       rightlink | maxoff |         flags
      -----------+--------+------------------------
               5 |      0 | {data,leaf,compressed}
      (1 row)

`gin_leafpage_items(page bytea) returns setof record`

  `gin_leafpage_items` renvoie des informations sur les données enregistrées dans un bloc feuille d'un index GIN. Par exemple :

      test=# SELECT first_tid, nbytes, tids[0:5] AS some_tids
              FROM gin_leafpage_items(get_raw_page('gin_test_idx', 2));
       first_tid | nbytes |                        some_tids
      -----------+--------+----------------------------------------------------------
       (8,41)    |    244 | {"(8,41)","(8,43)","(8,44)","(8,45)","(8,46)"}
       (10,45)   |    248 | {"(10,45)","(10,46)","(10,47)","(10,48)","(10,49)"}
       (12,52)   |    248 | {"(12,52)","(12,53)","(12,54)","(12,55)","(12,56)"}
       (14,59)   |    320 | {"(14,59)","(14,60)","(14,61)","(14,62)","(14,63)"}
       (167,16)  |    376 | {"(167,16)","(167,17)","(167,18)","(167,19)","(167,20)"}
       (170,30)  |    376 | {"(170,30)","(170,31)","(170,32)","(170,33)","(170,34)"}
       (173,44)  |    197 | {"(173,44)","(173,45)","(173,46)","(173,47)","(173,48)"}
      (7 rows)

### F.25.6. Fonctions GiST

`gist_page_opaque_info(page bytea) returns record`

  `gist_page_opaque_info` renvoie des informations à partir de l'aire opaque d'un bloc d'index GiST, tel que le NSN, le lien droit et le type de bloc. Par exemple :

      test=# SELECT * FROM gist_page_opaque_info(get_raw_page('test_gist_idx', 2));
       lsn | nsn | rightlink | flags
      -----+-----+-----------+--------
       0/1 | 0/0 |         1 | {leaf}
      (1 row)

`gist_page_items(page bytea, index_oid regclass) returns setof record`

  `gist_page_items` renvoie des informations sur les données enregistrées dans un bloc d'un index GiST. Par exemple :

      test=# SELECT * FROM gist_page_items(get_raw_page('test_gist_idx', 0), 'test_gist_idx');
       itemoffset |   ctid    | itemlen | dead |             keys
      ------------+-----------+---------+------+-------------------------------
                1 | (1,65535) |      40 | f    | (p)=("(166,166),(1,1)")
                2 | (2,65535) |      40 | f    | (p)=("(332,332),(167,167)")
                3 | (3,65535) |      40 | f    | (p)=("(498,498),(333,333)")
                4 | (4,65535) |      40 | f    | (p)=("(664,664),(499,499)")
                5 | (5,65535) |      40 | f    | (p)=("(830,830),(665,665)")
                6 | (6,65535) |      40 | f    | (p)=("(996,996),(831,831)")
                7 | (7,65535) |      40 | f    | (p)=("(1000,1000),(997,997)")
      (7 rows)

`gist_page_items_bytea(page bytea) returns setof record`

  Identique à `gist_page_items`, mais renvoie la donnée clé sous la forme d'un objet brut de type `bytea`. Comme il ne tente pas de décoder la clé, il n'a pas besoin de connaître l'index impliqué. Par exemple :

      test=# SELECT * FROM gist_page_items_bytea(get_raw_page('test_gist_idx', 0));
       itemoffset |   ctid    | itemlen | dead |                                      key_data
      ------------+-----------+---------+------+-----------------------------------------​-------------------------------------------
                1 | (1,65535) |      40 | f    | \x00000100ffff28000000000000c0644000000000​00c06440000000000000f03f000000000000f03f
                2 | (2,65535) |      40 | f    | \x00000200ffff28000000000000c0744000000000​00c074400000000000e064400000000000e06440
                3 | (3,65535) |      40 | f    | \x00000300ffff28000000000000207f4000000000​00207f400000000000d074400000000000d07440
                4 | (4,65535) |      40 | f    | \x00000400ffff28000000000000c0844000000000​00c084400000000000307f400000000000307f40
                5 | (5,65535) |      40 | f    | \x00000500ffff28000000000000f0894000000000​00f089400000000000c884400000000000c88440
                6 | (6,65535) |      40 | f    | \x00000600ffff28000000000000208f4000000000​00208f400000000000f889400000000000f88940
                7 | (7,65535) |      40 | f    | \x00000700ffff28000000000000408f4000000000​00408f400000000000288f400000000000288f40
      (7 rows)

### F.25.7. Fonctions Hash

`hash_page_type(page bytea) returns text`

  `hash_page_type` renvoie le type de page de la page d'index HASH donné. Par exemple :

      test=# SELECT hash_page_type(get_raw_page('con_hash_index', 0));
       hash_page_type
      ----------------
       metapage

`hash_page_stats(page bytea) returns setof record`

  `hash_page_stats` retourne des informations sur un bucket ou une page overflow d'un index HASH. Par exemple :

      test=# SELECT * FROM hash_page_stats(get_raw_page('con_hash_index', 1));
      -[ RECORD 1 ]---+-----------
      live_items      | 407
      dead_items      | 0
      page_size       | 8192
      free_size       | 8
      hasho_prevblkno | 4096
      hasho_nextblkno | 8474
      hasho_bucket    | 0
      hasho_flag      | 66
      hasho_page_id   | 65408

`hash_page_items(page bytea) returns setof record`

  `hash_page_items` retourne des informations sur les données stockées dans un bucket ou une page overflow d'une page d'index HASH. Par exemple :

      test=# SELECT * FROM hash_page_items(get_raw_page('con_hash_index', 1)) LIMIT 5;
       itemoffset |   ctid    |    data
      ------------+-----------+------------
                1 | (899,77)  | 1053474816
                2 | (897,29)  | 1053474816
                3 | (894,207) | 1053474816
                4 | (892,159) | 1053474816
                5 | (890,111) | 1053474816

`hash_bitmap_info(index oid, blkno bigint) returns record`

  `hash_bitmap_info` montre le statut d'un bit dans la page de bitmap pour une page overflow en particulier d'un index HASH. Par exemple :

      test=# SELECT * FROM hash_bitmap_info('con_hash_index', 2052);
       bitmapblkno | bitmapbit | bitstatus
      -------------+-----------+-----------
                65 |         3 | t

`hash_metapage_info(page bytea) returns record`

  `hash_metapage_info` retourne l'information stockée dans la méta-page d'un index HASH index. Par exemple :

      test=# SELECT magic, version, ntuples, ffactor, bsize, bmsize, bmshift,
      test-#     maxbucket, highmask, lowmask, ovflpoint, firstfree, nmaps, procid,
      test-#     regexp_replace(spares::text, '(,0)*}', '}') as spares,
      test-#     regexp_replace(mapp::text, '(,0)*}', '}') as mapp
      test-# FROM hash_metapage_info(get_raw_page('con_hash_index', 0));
      -[ RECORD 1 ]-------------------------------------------------------------------------------
      magic     | 105121344
      version   | 4
      ntuples   | 500500
      ffactor   | 40
      bsize     | 8152
      bmsize    | 4096
      bmshift   | 15
      maxbucket | 12512
      highmask  | 16383
      lowmask   | 8191
      ovflpoint | 28
      firstfree | 1204
      nmaps     | 1
      procid    | 450
      spares    | {0,0,0,0,0,0,1,1,1,1,1,1,1,1,3,4,4,4,45,55,58,59,508,567,628,704,1193,1202,1204}
      mapp      | {65}