LCOV - code coverage report
Current view: top level - src/bin/pg_waldump - gindesc.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 37.7 % 130 49
Test Date: 2026-02-17 16:40:31 Functions: 66.7 % 3 2
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  * gindesc.c
       4              :  *    rmgr descriptor routines for access/transam/gin/ginxlog.c
       5              :  *
       6              :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       7              :  * Portions Copyright (c) 1994, Regents of the University of California
       8              :  *
       9              :  *
      10              :  * IDENTIFICATION
      11              :  *    src/backend/access/rmgrdesc/gindesc.c
      12              :  *
      13              :  *-------------------------------------------------------------------------
      14              :  */
      15              : #include "postgres.h"
      16              : 
      17              : #include "access/ginxlog.h"
      18              : #include "lib/stringinfo.h"
      19              : 
      20              : static void
      21            0 : desc_recompress_leaf(StringInfo buf, ginxlogRecompressDataLeaf *insertData)
      22              : {
      23              :     int         i;
      24            0 :     char       *walbuf = ((char *) insertData) + sizeof(ginxlogRecompressDataLeaf);
      25              : 
      26            0 :     appendStringInfo(buf, " %d segments:", insertData->nactions);
      27              : 
      28            0 :     for (i = 0; i < insertData->nactions; i++)
      29              :     {
      30            0 :         uint8       a_segno = *((uint8 *) (walbuf++));
      31            0 :         uint8       a_action = *((uint8 *) (walbuf++));
      32            0 :         uint16      nitems = 0;
      33            0 :         int         newsegsize = 0;
      34              : 
      35            0 :         if (a_action == GIN_SEGMENT_INSERT ||
      36              :             a_action == GIN_SEGMENT_REPLACE)
      37              :         {
      38            0 :             newsegsize = SizeOfGinPostingList((GinPostingList *) walbuf);
      39            0 :             walbuf += SHORTALIGN(newsegsize);
      40              :         }
      41              : 
      42            0 :         if (a_action == GIN_SEGMENT_ADDITEMS)
      43              :         {
      44            0 :             memcpy(&nitems, walbuf, sizeof(uint16));
      45            0 :             walbuf += sizeof(uint16);
      46            0 :             walbuf += nitems * sizeof(ItemPointerData);
      47              :         }
      48              : 
      49            0 :         switch (a_action)
      50              :         {
      51            0 :             case GIN_SEGMENT_ADDITEMS:
      52            0 :                 appendStringInfo(buf, " %d (add %d items)", a_segno, nitems);
      53            0 :                 break;
      54            0 :             case GIN_SEGMENT_DELETE:
      55            0 :                 appendStringInfo(buf, " %d (delete)", a_segno);
      56            0 :                 break;
      57            0 :             case GIN_SEGMENT_INSERT:
      58            0 :                 appendStringInfo(buf, " %d (insert)", a_segno);
      59            0 :                 break;
      60            0 :             case GIN_SEGMENT_REPLACE:
      61            0 :                 appendStringInfo(buf, " %d (replace)", a_segno);
      62            0 :                 break;
      63            0 :             default:
      64            0 :                 appendStringInfo(buf, " %d unknown action %d ???", a_segno, a_action);
      65              :                 /* cannot decode unrecognized actions further */
      66            0 :                 return;
      67              :         }
      68              :     }
      69              : }
      70              : 
      71              : void
      72         3096 : gin_desc(StringInfo buf, XLogReaderState *record)
      73              : {
      74         3096 :     char       *rec = XLogRecGetData(record);
      75         3096 :     uint8       info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
      76              : 
      77         3096 :     switch (info)
      78              :     {
      79            0 :         case XLOG_GIN_CREATE_PTREE:
      80              :             /* no further information */
      81            0 :             break;
      82           36 :         case XLOG_GIN_INSERT:
      83              :             {
      84           36 :                 ginxlogInsert *xlrec = (ginxlogInsert *) rec;
      85              : 
      86           72 :                 appendStringInfo(buf, "isdata: %c isleaf: %c",
      87           36 :                                  (xlrec->flags & GIN_INSERT_ISDATA) ? 'T' : 'F',
      88           36 :                                  (xlrec->flags & GIN_INSERT_ISLEAF) ? 'T' : 'F');
      89           36 :                 if (!(xlrec->flags & GIN_INSERT_ISLEAF))
      90              :                 {
      91            0 :                     char       *payload = rec + sizeof(ginxlogInsert);
      92              :                     BlockNumber leftChildBlkno;
      93              :                     BlockNumber rightChildBlkno;
      94              : 
      95            0 :                     leftChildBlkno = BlockIdGetBlockNumber((BlockId) payload);
      96            0 :                     payload += sizeof(BlockIdData);
      97            0 :                     rightChildBlkno = BlockIdGetBlockNumber((BlockId) payload);
      98            0 :                     payload += sizeof(BlockNumber);
      99            0 :                     appendStringInfo(buf, " children: %u/%u",
     100              :                                      leftChildBlkno, rightChildBlkno);
     101              :                 }
     102           36 :                 if (!XLogRecHasBlockImage(record, 0))
     103              :                 {
     104           36 :                     char       *payload = XLogRecGetBlockData(record, 0, NULL);
     105              : 
     106           36 :                     if (!(xlrec->flags & GIN_INSERT_ISDATA))
     107           36 :                         appendStringInfo(buf, " isdelete: %c",
     108           36 :                                          (((ginxlogInsertEntry *) payload)->isDelete) ? 'T' : 'F');
     109            0 :                     else if (xlrec->flags & GIN_INSERT_ISLEAF)
     110            0 :                         desc_recompress_leaf(buf, (ginxlogRecompressDataLeaf *) payload);
     111              :                     else
     112              :                     {
     113            0 :                         ginxlogInsertDataInternal *insertData =
     114              :                             (ginxlogInsertDataInternal *) payload;
     115              : 
     116            0 :                         appendStringInfo(buf, " pitem: %u-%u/%u",
     117            0 :                                          PostingItemGetBlockNumber(&insertData->newitem),
     118            0 :                                          ItemPointerGetBlockNumber(&insertData->newitem.key),
     119            0 :                                          ItemPointerGetOffsetNumber(&insertData->newitem.key));
     120              :                     }
     121              :                 }
     122              :             }
     123           36 :             break;
     124            0 :         case XLOG_GIN_SPLIT:
     125              :             {
     126            0 :                 ginxlogSplit *xlrec = (ginxlogSplit *) rec;
     127              : 
     128            0 :                 appendStringInfo(buf, "isrootsplit: %c",
     129            0 :                                  (((ginxlogSplit *) rec)->flags & GIN_SPLIT_ROOT) ? 'T' : 'F');
     130            0 :                 appendStringInfo(buf, " isdata: %c isleaf: %c",
     131            0 :                                  (xlrec->flags & GIN_INSERT_ISDATA) ? 'T' : 'F',
     132            0 :                                  (xlrec->flags & GIN_INSERT_ISLEAF) ? 'T' : 'F');
     133            0 :                 if (xlrec->leftChildBlkno != InvalidBlockNumber)
     134            0 :                     appendStringInfo(buf, " children: %u/%u",
     135              :                                      xlrec->leftChildBlkno, xlrec->rightChildBlkno);
     136              :             }
     137            0 :             break;
     138            0 :         case XLOG_GIN_VACUUM_PAGE:
     139              :             /* no further information */
     140            0 :             break;
     141            0 :         case XLOG_GIN_VACUUM_DATA_LEAF_PAGE:
     142              :             {
     143            0 :                 if (!XLogRecHasBlockImage(record, 0))
     144              :                 {
     145              :                     ginxlogVacuumDataLeafPage *xlrec =
     146            0 :                         (ginxlogVacuumDataLeafPage *) XLogRecGetBlockData(record, 0, NULL);
     147              : 
     148            0 :                     desc_recompress_leaf(buf, &xlrec->data);
     149              :                 }
     150              :             }
     151            0 :             break;
     152            0 :         case XLOG_GIN_DELETE_PAGE:
     153              :             /* no further information */
     154            0 :             break;
     155         3006 :         case XLOG_GIN_UPDATE_META_PAGE:
     156              :             {
     157         3006 :                 ginxlogUpdateMeta *xlrec = (ginxlogUpdateMeta *) rec;
     158              : 
     159         3006 :                 appendStringInfo(buf, "ntuples: %d", xlrec->ntuples);
     160         3006 :                 if (xlrec->prevTail != InvalidBlockNumber)
     161           42 :                     appendStringInfo(buf, " prevTail: %u",
     162              :                                      xlrec->prevTail);
     163         3006 :                 if (xlrec->newRightlink != InvalidBlockNumber)
     164           42 :                     appendStringInfo(buf, " newRightlink: %u",
     165              :                                      xlrec->newRightlink);
     166              :             }
     167         3006 :             break;
     168           48 :         case XLOG_GIN_INSERT_LISTPAGE:
     169              :             {
     170           48 :                 ginxlogInsertListPage *xlrec = (ginxlogInsertListPage *) rec;
     171              : 
     172           48 :                 appendStringInfo(buf, "ntuples: %d", xlrec->ntuples);
     173           48 :                 if (xlrec->rightlink != InvalidBlockNumber)
     174            0 :                     appendStringInfo(buf, " rightlink: %u",
     175              :                                      xlrec->rightlink);
     176              :             }
     177           48 :             break;
     178            6 :         case XLOG_GIN_DELETE_LISTPAGE:
     179            6 :             appendStringInfo(buf, "ndeleted: %d",
     180              :                              ((ginxlogDeleteListPages *) rec)->ndeleted);
     181            6 :             break;
     182              :     }
     183         3096 : }
     184              : 
     185              : const char *
     186         3100 : gin_identify(uint8 info)
     187              : {
     188         3100 :     const char *id = NULL;
     189              : 
     190         3100 :     switch (info & ~XLR_INFO_MASK)
     191              :     {
     192            0 :         case XLOG_GIN_CREATE_PTREE:
     193            0 :             id = "CREATE_PTREE";
     194            0 :             break;
     195           37 :         case XLOG_GIN_INSERT:
     196           37 :             id = "INSERT";
     197           37 :             break;
     198            0 :         case XLOG_GIN_SPLIT:
     199            0 :             id = "SPLIT";
     200            0 :             break;
     201            0 :         case XLOG_GIN_VACUUM_PAGE:
     202            0 :             id = "VACUUM_PAGE";
     203            0 :             break;
     204            0 :         case XLOG_GIN_VACUUM_DATA_LEAF_PAGE:
     205            0 :             id = "VACUUM_DATA_LEAF_PAGE";
     206            0 :             break;
     207            0 :         case XLOG_GIN_DELETE_PAGE:
     208            0 :             id = "DELETE_PAGE";
     209            0 :             break;
     210         3007 :         case XLOG_GIN_UPDATE_META_PAGE:
     211         3007 :             id = "UPDATE_META_PAGE";
     212         3007 :             break;
     213           49 :         case XLOG_GIN_INSERT_LISTPAGE:
     214           49 :             id = "INSERT_LISTPAGE";
     215           49 :             break;
     216            7 :         case XLOG_GIN_DELETE_LISTPAGE:
     217            7 :             id = "DELETE_LISTPAGE";
     218            7 :             break;
     219              :     }
     220              : 
     221         3100 :     return id;
     222              : }
        

Generated by: LCOV version 2.0-1