LCOV - code coverage report
Current view: top level - src/bin/pg_waldump - xactdesc.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 125 247 50.6 %
Date: 2024-11-21 08:14:44 Functions: 9 12 75.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * xactdesc.c
       4             :  *    rmgr descriptor routines for access/transam/xact.c
       5             :  *
       6             :  * Portions Copyright (c) 1996-2024, PostgreSQL Global Development Group
       7             :  * Portions Copyright (c) 1994, Regents of the University of California
       8             :  *
       9             :  *
      10             :  * IDENTIFICATION
      11             :  *    src/backend/access/rmgrdesc/xactdesc.c
      12             :  *
      13             :  *-------------------------------------------------------------------------
      14             :  */
      15             : #include "postgres.h"
      16             : 
      17             : #include "access/transam.h"
      18             : #include "access/xact.h"
      19             : #include "replication/origin.h"
      20             : #include "storage/sinval.h"
      21             : #include "storage/standbydefs.h"
      22             : #include "utils/timestamp.h"
      23             : 
      24             : /*
      25             :  * Parse the WAL format of an xact commit and abort records into an easier to
      26             :  * understand format.
      27             :  *
      28             :  * These routines are in xactdesc.c because they're accessed in backend (when
      29             :  * replaying WAL) and frontend (pg_waldump) code. This file is the only xact
      30             :  * specific one shared between both. They're complicated enough that
      31             :  * duplication would be bothersome.
      32             :  */
      33             : 
      34             : void
      35        3280 : ParseCommitRecord(uint8 info, xl_xact_commit *xlrec, xl_xact_parsed_commit *parsed)
      36             : {
      37        3280 :     char       *data = ((char *) xlrec) + MinSizeOfXactCommit;
      38             : 
      39        3280 :     memset(parsed, 0, sizeof(*parsed));
      40             : 
      41        3280 :     parsed->xinfo = 0;           /* default, if no XLOG_XACT_HAS_INFO is
      42             :                                  * present */
      43             : 
      44        3280 :     parsed->xact_time = xlrec->xact_time;
      45             : 
      46        3280 :     if (info & XLOG_XACT_HAS_INFO)
      47             :     {
      48        3240 :         xl_xact_xinfo *xl_xinfo = (xl_xact_xinfo *) data;
      49             : 
      50        3240 :         parsed->xinfo = xl_xinfo->xinfo;
      51             : 
      52        3240 :         data += sizeof(xl_xact_xinfo);
      53             :     }
      54             : 
      55        3280 :     if (parsed->xinfo & XACT_XINFO_HAS_DBINFO)
      56             :     {
      57        3240 :         xl_xact_dbinfo *xl_dbinfo = (xl_xact_dbinfo *) data;
      58             : 
      59        3240 :         parsed->dbId = xl_dbinfo->dbId;
      60        3240 :         parsed->tsId = xl_dbinfo->tsId;
      61             : 
      62        3240 :         data += sizeof(xl_xact_dbinfo);
      63             :     }
      64             : 
      65        3280 :     if (parsed->xinfo & XACT_XINFO_HAS_SUBXACTS)
      66             :     {
      67           0 :         xl_xact_subxacts *xl_subxacts = (xl_xact_subxacts *) data;
      68             : 
      69           0 :         parsed->nsubxacts = xl_subxacts->nsubxacts;
      70           0 :         parsed->subxacts = xl_subxacts->subxacts;
      71             : 
      72           0 :         data += MinSizeOfXactSubxacts;
      73           0 :         data += parsed->nsubxacts * sizeof(TransactionId);
      74             :     }
      75             : 
      76        3280 :     if (parsed->xinfo & XACT_XINFO_HAS_RELFILELOCATORS)
      77             :     {
      78          24 :         xl_xact_relfilelocators *xl_rellocators = (xl_xact_relfilelocators *) data;
      79             : 
      80          24 :         parsed->nrels = xl_rellocators->nrels;
      81          24 :         parsed->xlocators = xl_rellocators->xlocators;
      82             : 
      83          24 :         data += MinSizeOfXactRelfileLocators;
      84          24 :         data += xl_rellocators->nrels * sizeof(RelFileLocator);
      85             :     }
      86             : 
      87        3280 :     if (parsed->xinfo & XACT_XINFO_HAS_DROPPED_STATS)
      88             :     {
      89          24 :         xl_xact_stats_items *xl_drops = (xl_xact_stats_items *) data;
      90             : 
      91          24 :         parsed->nstats = xl_drops->nitems;
      92          24 :         parsed->stats = xl_drops->items;
      93             : 
      94          24 :         data += MinSizeOfXactStatsItems;
      95          24 :         data += xl_drops->nitems * sizeof(xl_xact_stats_item);
      96             :     }
      97             : 
      98        3280 :     if (parsed->xinfo & XACT_XINFO_HAS_INVALS)
      99             :     {
     100        3144 :         xl_xact_invals *xl_invals = (xl_xact_invals *) data;
     101             : 
     102        3144 :         parsed->nmsgs = xl_invals->nmsgs;
     103        3144 :         parsed->msgs = xl_invals->msgs;
     104             : 
     105        3144 :         data += MinSizeOfXactInvals;
     106        3144 :         data += xl_invals->nmsgs * sizeof(SharedInvalidationMessage);
     107             :     }
     108             : 
     109        3280 :     if (parsed->xinfo & XACT_XINFO_HAS_TWOPHASE)
     110             :     {
     111           0 :         xl_xact_twophase *xl_twophase = (xl_xact_twophase *) data;
     112             : 
     113           0 :         parsed->twophase_xid = xl_twophase->xid;
     114             : 
     115           0 :         data += sizeof(xl_xact_twophase);
     116             : 
     117           0 :         if (parsed->xinfo & XACT_XINFO_HAS_GID)
     118             :         {
     119           0 :             strlcpy(parsed->twophase_gid, data, sizeof(parsed->twophase_gid));
     120           0 :             data += strlen(data) + 1;
     121             :         }
     122             :     }
     123             : 
     124             :     /* Note: no alignment is guaranteed after this point */
     125             : 
     126        3280 :     if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN)
     127             :     {
     128             :         xl_xact_origin xl_origin;
     129             : 
     130             :         /* no alignment is guaranteed, so copy onto stack */
     131           0 :         memcpy(&xl_origin, data, sizeof(xl_origin));
     132             : 
     133           0 :         parsed->origin_lsn = xl_origin.origin_lsn;
     134           0 :         parsed->origin_timestamp = xl_origin.origin_timestamp;
     135             : 
     136           0 :         data += sizeof(xl_xact_origin);
     137             :     }
     138        3280 : }
     139             : 
     140             : void
     141          12 : ParseAbortRecord(uint8 info, xl_xact_abort *xlrec, xl_xact_parsed_abort *parsed)
     142             : {
     143          12 :     char       *data = ((char *) xlrec) + MinSizeOfXactAbort;
     144             : 
     145          12 :     memset(parsed, 0, sizeof(*parsed));
     146             : 
     147          12 :     parsed->xinfo = 0;           /* default, if no XLOG_XACT_HAS_INFO is
     148             :                                  * present */
     149             : 
     150          12 :     parsed->xact_time = xlrec->xact_time;
     151             : 
     152          12 :     if (info & XLOG_XACT_HAS_INFO)
     153             :     {
     154           0 :         xl_xact_xinfo *xl_xinfo = (xl_xact_xinfo *) data;
     155             : 
     156           0 :         parsed->xinfo = xl_xinfo->xinfo;
     157             : 
     158           0 :         data += sizeof(xl_xact_xinfo);
     159             :     }
     160             : 
     161          12 :     if (parsed->xinfo & XACT_XINFO_HAS_DBINFO)
     162             :     {
     163           0 :         xl_xact_dbinfo *xl_dbinfo = (xl_xact_dbinfo *) data;
     164             : 
     165           0 :         parsed->dbId = xl_dbinfo->dbId;
     166           0 :         parsed->tsId = xl_dbinfo->tsId;
     167             : 
     168           0 :         data += sizeof(xl_xact_dbinfo);
     169             :     }
     170             : 
     171          12 :     if (parsed->xinfo & XACT_XINFO_HAS_SUBXACTS)
     172             :     {
     173           0 :         xl_xact_subxacts *xl_subxacts = (xl_xact_subxacts *) data;
     174             : 
     175           0 :         parsed->nsubxacts = xl_subxacts->nsubxacts;
     176           0 :         parsed->subxacts = xl_subxacts->subxacts;
     177             : 
     178           0 :         data += MinSizeOfXactSubxacts;
     179           0 :         data += parsed->nsubxacts * sizeof(TransactionId);
     180             :     }
     181             : 
     182          12 :     if (parsed->xinfo & XACT_XINFO_HAS_RELFILELOCATORS)
     183             :     {
     184           0 :         xl_xact_relfilelocators *xl_rellocator = (xl_xact_relfilelocators *) data;
     185             : 
     186           0 :         parsed->nrels = xl_rellocator->nrels;
     187           0 :         parsed->xlocators = xl_rellocator->xlocators;
     188             : 
     189           0 :         data += MinSizeOfXactRelfileLocators;
     190           0 :         data += xl_rellocator->nrels * sizeof(RelFileLocator);
     191             :     }
     192             : 
     193          12 :     if (parsed->xinfo & XACT_XINFO_HAS_DROPPED_STATS)
     194             :     {
     195           0 :         xl_xact_stats_items *xl_drops = (xl_xact_stats_items *) data;
     196             : 
     197           0 :         parsed->nstats = xl_drops->nitems;
     198           0 :         parsed->stats = xl_drops->items;
     199             : 
     200           0 :         data += MinSizeOfXactStatsItems;
     201           0 :         data += xl_drops->nitems * sizeof(xl_xact_stats_item);
     202             :     }
     203             : 
     204          12 :     if (parsed->xinfo & XACT_XINFO_HAS_TWOPHASE)
     205             :     {
     206           0 :         xl_xact_twophase *xl_twophase = (xl_xact_twophase *) data;
     207             : 
     208           0 :         parsed->twophase_xid = xl_twophase->xid;
     209             : 
     210           0 :         data += sizeof(xl_xact_twophase);
     211             : 
     212           0 :         if (parsed->xinfo & XACT_XINFO_HAS_GID)
     213             :         {
     214           0 :             strlcpy(parsed->twophase_gid, data, sizeof(parsed->twophase_gid));
     215           0 :             data += strlen(data) + 1;
     216             :         }
     217             :     }
     218             : 
     219             :     /* Note: no alignment is guaranteed after this point */
     220             : 
     221          12 :     if (parsed->xinfo & XACT_XINFO_HAS_ORIGIN)
     222             :     {
     223             :         xl_xact_origin xl_origin;
     224             : 
     225             :         /* no alignment is guaranteed, so copy onto stack */
     226           0 :         memcpy(&xl_origin, data, sizeof(xl_origin));
     227             : 
     228           0 :         parsed->origin_lsn = xl_origin.origin_lsn;
     229           0 :         parsed->origin_timestamp = xl_origin.origin_timestamp;
     230             : 
     231           0 :         data += sizeof(xl_xact_origin);
     232             :     }
     233          12 : }
     234             : 
     235             : /*
     236             :  * ParsePrepareRecord
     237             :  */
     238             : void
     239           0 : ParsePrepareRecord(uint8 info, xl_xact_prepare *xlrec, xl_xact_parsed_prepare *parsed)
     240             : {
     241             :     char       *bufptr;
     242             : 
     243           0 :     bufptr = ((char *) xlrec) + MAXALIGN(sizeof(xl_xact_prepare));
     244             : 
     245           0 :     memset(parsed, 0, sizeof(*parsed));
     246             : 
     247           0 :     parsed->xact_time = xlrec->prepared_at;
     248           0 :     parsed->origin_lsn = xlrec->origin_lsn;
     249           0 :     parsed->origin_timestamp = xlrec->origin_timestamp;
     250           0 :     parsed->twophase_xid = xlrec->xid;
     251           0 :     parsed->dbId = xlrec->database;
     252           0 :     parsed->nsubxacts = xlrec->nsubxacts;
     253           0 :     parsed->nrels = xlrec->ncommitrels;
     254           0 :     parsed->nabortrels = xlrec->nabortrels;
     255           0 :     parsed->nmsgs = xlrec->ninvalmsgs;
     256             : 
     257           0 :     strncpy(parsed->twophase_gid, bufptr, xlrec->gidlen);
     258           0 :     bufptr += MAXALIGN(xlrec->gidlen);
     259             : 
     260           0 :     parsed->subxacts = (TransactionId *) bufptr;
     261           0 :     bufptr += MAXALIGN(xlrec->nsubxacts * sizeof(TransactionId));
     262             : 
     263           0 :     parsed->xlocators = (RelFileLocator *) bufptr;
     264           0 :     bufptr += MAXALIGN(xlrec->ncommitrels * sizeof(RelFileLocator));
     265             : 
     266           0 :     parsed->abortlocators = (RelFileLocator *) bufptr;
     267           0 :     bufptr += MAXALIGN(xlrec->nabortrels * sizeof(RelFileLocator));
     268             : 
     269           0 :     parsed->stats = (xl_xact_stats_item *) bufptr;
     270           0 :     bufptr += MAXALIGN(xlrec->ncommitstats * sizeof(xl_xact_stats_item));
     271             : 
     272           0 :     parsed->abortstats = (xl_xact_stats_item *) bufptr;
     273           0 :     bufptr += MAXALIGN(xlrec->nabortstats * sizeof(xl_xact_stats_item));
     274             : 
     275           0 :     parsed->msgs = (SharedInvalidationMessage *) bufptr;
     276           0 :     bufptr += MAXALIGN(xlrec->ninvalmsgs * sizeof(SharedInvalidationMessage));
     277           0 : }
     278             : 
     279             : static void
     280        3292 : xact_desc_relations(StringInfo buf, char *label, int nrels,
     281             :                     RelFileLocator *xlocators)
     282             : {
     283             :     int         i;
     284             : 
     285        3292 :     if (nrels > 0)
     286             :     {
     287          24 :         appendStringInfo(buf, "; %s:", label);
     288         120 :         for (i = 0; i < nrels; i++)
     289             :         {
     290          96 :             char       *path = relpathperm(xlocators[i], MAIN_FORKNUM);
     291             : 
     292          96 :             appendStringInfo(buf, " %s", path);
     293          96 :             pfree(path);
     294             :         }
     295             :     }
     296        3292 : }
     297             : 
     298             : static void
     299        3292 : xact_desc_subxacts(StringInfo buf, int nsubxacts, TransactionId *subxacts)
     300             : {
     301             :     int         i;
     302             : 
     303        3292 :     if (nsubxacts > 0)
     304             :     {
     305           0 :         appendStringInfoString(buf, "; subxacts:");
     306           0 :         for (i = 0; i < nsubxacts; i++)
     307           0 :             appendStringInfo(buf, " %u", subxacts[i]);
     308             :     }
     309        3292 : }
     310             : 
     311             : static void
     312        3292 : xact_desc_stats(StringInfo buf, const char *label,
     313             :                 int ndropped, xl_xact_stats_item *dropped_stats)
     314             : {
     315             :     int         i;
     316             : 
     317        3292 :     if (ndropped > 0)
     318             :     {
     319          24 :         appendStringInfo(buf, "; %sdropped stats:", label);
     320          48 :         for (i = 0; i < ndropped; i++)
     321             :         {
     322          24 :             uint64      objid =
     323          24 :                 ((uint64) dropped_stats[i].objid_hi) << 32 | dropped_stats[i].objid_lo;
     324             : 
     325          24 :             appendStringInfo(buf, " %d/%u/%llu",
     326          24 :                              dropped_stats[i].kind,
     327          24 :                              dropped_stats[i].dboid,
     328             :                              (unsigned long long) objid);
     329             :         }
     330             :     }
     331        3292 : }
     332             : 
     333             : static void
     334        3280 : xact_desc_commit(StringInfo buf, uint8 info, xl_xact_commit *xlrec, RepOriginId origin_id)
     335             : {
     336             :     xl_xact_parsed_commit parsed;
     337             : 
     338        3280 :     ParseCommitRecord(info, xlrec, &parsed);
     339             : 
     340             :     /* If this is a prepared xact, show the xid of the original xact */
     341        3280 :     if (TransactionIdIsValid(parsed.twophase_xid))
     342           0 :         appendStringInfo(buf, "%u: ", parsed.twophase_xid);
     343             : 
     344        3280 :     appendStringInfoString(buf, timestamptz_to_str(xlrec->xact_time));
     345             : 
     346        3280 :     xact_desc_relations(buf, "rels", parsed.nrels, parsed.xlocators);
     347        3280 :     xact_desc_subxacts(buf, parsed.nsubxacts, parsed.subxacts);
     348        3280 :     xact_desc_stats(buf, "", parsed.nstats, parsed.stats);
     349             : 
     350        3280 :     standby_desc_invalidations(buf, parsed.nmsgs, parsed.msgs, parsed.dbId,
     351             :                                parsed.tsId,
     352        3280 :                                XactCompletionRelcacheInitFileInval(parsed.xinfo));
     353             : 
     354        3280 :     if (XactCompletionApplyFeedback(parsed.xinfo))
     355           0 :         appendStringInfoString(buf, "; apply_feedback");
     356             : 
     357        3280 :     if (XactCompletionForceSyncCommit(parsed.xinfo))
     358          56 :         appendStringInfoString(buf, "; sync");
     359             : 
     360        3280 :     if (parsed.xinfo & XACT_XINFO_HAS_ORIGIN)
     361             :     {
     362           0 :         appendStringInfo(buf, "; origin: node %u, lsn %X/%X, at %s",
     363             :                          origin_id,
     364           0 :                          LSN_FORMAT_ARGS(parsed.origin_lsn),
     365             :                          timestamptz_to_str(parsed.origin_timestamp));
     366             :     }
     367        3280 : }
     368             : 
     369             : static void
     370          12 : xact_desc_abort(StringInfo buf, uint8 info, xl_xact_abort *xlrec, RepOriginId origin_id)
     371             : {
     372             :     xl_xact_parsed_abort parsed;
     373             : 
     374          12 :     ParseAbortRecord(info, xlrec, &parsed);
     375             : 
     376             :     /* If this is a prepared xact, show the xid of the original xact */
     377          12 :     if (TransactionIdIsValid(parsed.twophase_xid))
     378           0 :         appendStringInfo(buf, "%u: ", parsed.twophase_xid);
     379             : 
     380          12 :     appendStringInfoString(buf, timestamptz_to_str(xlrec->xact_time));
     381             : 
     382          12 :     xact_desc_relations(buf, "rels", parsed.nrels, parsed.xlocators);
     383          12 :     xact_desc_subxacts(buf, parsed.nsubxacts, parsed.subxacts);
     384             : 
     385          12 :     if (parsed.xinfo & XACT_XINFO_HAS_ORIGIN)
     386             :     {
     387           0 :         appendStringInfo(buf, "; origin: node %u, lsn %X/%X, at %s",
     388             :                          origin_id,
     389           0 :                          LSN_FORMAT_ARGS(parsed.origin_lsn),
     390             :                          timestamptz_to_str(parsed.origin_timestamp));
     391             :     }
     392             : 
     393          12 :     xact_desc_stats(buf, "", parsed.nstats, parsed.stats);
     394          12 : }
     395             : 
     396             : static void
     397           0 : xact_desc_prepare(StringInfo buf, uint8 info, xl_xact_prepare *xlrec, RepOriginId origin_id)
     398             : {
     399             :     xl_xact_parsed_prepare parsed;
     400             : 
     401           0 :     ParsePrepareRecord(info, xlrec, &parsed);
     402             : 
     403           0 :     appendStringInfo(buf, "gid %s: ", parsed.twophase_gid);
     404           0 :     appendStringInfoString(buf, timestamptz_to_str(parsed.xact_time));
     405             : 
     406           0 :     xact_desc_relations(buf, "rels(commit)", parsed.nrels, parsed.xlocators);
     407           0 :     xact_desc_relations(buf, "rels(abort)", parsed.nabortrels,
     408             :                         parsed.abortlocators);
     409           0 :     xact_desc_stats(buf, "commit ", parsed.nstats, parsed.stats);
     410           0 :     xact_desc_stats(buf, "abort ", parsed.nabortstats, parsed.abortstats);
     411           0 :     xact_desc_subxacts(buf, parsed.nsubxacts, parsed.subxacts);
     412             : 
     413           0 :     standby_desc_invalidations(buf, parsed.nmsgs, parsed.msgs, parsed.dbId,
     414           0 :                                parsed.tsId, xlrec->initfileinval);
     415             : 
     416             :     /*
     417             :      * Check if the replication origin has been set in this record in the same
     418             :      * way as PrepareRedoAdd().
     419             :      */
     420           0 :     if (origin_id != InvalidRepOriginId)
     421           0 :         appendStringInfo(buf, "; origin: node %u, lsn %X/%X, at %s",
     422             :                          origin_id,
     423           0 :                          LSN_FORMAT_ARGS(parsed.origin_lsn),
     424             :                          timestamptz_to_str(parsed.origin_timestamp));
     425           0 : }
     426             : 
     427             : static void
     428           0 : xact_desc_assignment(StringInfo buf, xl_xact_assignment *xlrec)
     429             : {
     430             :     int         i;
     431             : 
     432           0 :     appendStringInfoString(buf, "subxacts:");
     433             : 
     434           0 :     for (i = 0; i < xlrec->nsubxacts; i++)
     435           0 :         appendStringInfo(buf, " %u", xlrec->xsub[i]);
     436           0 : }
     437             : 
     438             : void
     439        5464 : xact_desc(StringInfo buf, XLogReaderState *record)
     440             : {
     441        5464 :     char       *rec = XLogRecGetData(record);
     442        5464 :     uint8       info = XLogRecGetInfo(record) & XLOG_XACT_OPMASK;
     443             : 
     444        5464 :     if (info == XLOG_XACT_COMMIT || info == XLOG_XACT_COMMIT_PREPARED)
     445        3280 :     {
     446        3280 :         xl_xact_commit *xlrec = (xl_xact_commit *) rec;
     447             : 
     448        3280 :         xact_desc_commit(buf, XLogRecGetInfo(record), xlrec,
     449        3280 :                          XLogRecGetOrigin(record));
     450             :     }
     451        2184 :     else if (info == XLOG_XACT_ABORT || info == XLOG_XACT_ABORT_PREPARED)
     452          12 :     {
     453          12 :         xl_xact_abort *xlrec = (xl_xact_abort *) rec;
     454             : 
     455          12 :         xact_desc_abort(buf, XLogRecGetInfo(record), xlrec,
     456          12 :                         XLogRecGetOrigin(record));
     457             :     }
     458        2172 :     else if (info == XLOG_XACT_PREPARE)
     459             :     {
     460           0 :         xl_xact_prepare *xlrec = (xl_xact_prepare *) rec;
     461             : 
     462           0 :         xact_desc_prepare(buf, XLogRecGetInfo(record), xlrec,
     463           0 :                           XLogRecGetOrigin(record));
     464             :     }
     465        2172 :     else if (info == XLOG_XACT_ASSIGNMENT)
     466             :     {
     467           0 :         xl_xact_assignment *xlrec = (xl_xact_assignment *) rec;
     468             : 
     469             :         /*
     470             :          * Note that we ignore the WAL record's xid, since we're more
     471             :          * interested in the top-level xid that issued the record and which
     472             :          * xids are being reported here.
     473             :          */
     474           0 :         appendStringInfo(buf, "xtop %u: ", xlrec->xtop);
     475           0 :         xact_desc_assignment(buf, xlrec);
     476             :     }
     477        2172 :     else if (info == XLOG_XACT_INVALIDATIONS)
     478             :     {
     479        2172 :         xl_xact_invals *xlrec = (xl_xact_invals *) rec;
     480             : 
     481        2172 :         standby_desc_invalidations(buf, xlrec->nmsgs, xlrec->msgs, InvalidOid,
     482             :                                    InvalidOid, false);
     483             :     }
     484        5464 : }
     485             : 
     486             : const char *
     487        5470 : xact_identify(uint8 info)
     488             : {
     489        5470 :     const char *id = NULL;
     490             : 
     491        5470 :     switch (info & XLOG_XACT_OPMASK)
     492             :     {
     493        3282 :         case XLOG_XACT_COMMIT:
     494        3282 :             id = "COMMIT";
     495        3282 :             break;
     496           0 :         case XLOG_XACT_PREPARE:
     497           0 :             id = "PREPARE";
     498           0 :             break;
     499          14 :         case XLOG_XACT_ABORT:
     500          14 :             id = "ABORT";
     501          14 :             break;
     502           0 :         case XLOG_XACT_COMMIT_PREPARED:
     503           0 :             id = "COMMIT_PREPARED";
     504           0 :             break;
     505           0 :         case XLOG_XACT_ABORT_PREPARED:
     506           0 :             id = "ABORT_PREPARED";
     507           0 :             break;
     508           0 :         case XLOG_XACT_ASSIGNMENT:
     509           0 :             id = "ASSIGNMENT";
     510           0 :             break;
     511        2174 :         case XLOG_XACT_INVALIDATIONS:
     512        2174 :             id = "INVALIDATION";
     513        2174 :             break;
     514             :     }
     515             : 
     516        5470 :     return id;
     517             : }

Generated by: LCOV version 1.14