LCOV - code coverage report
Current view: top level - src/backend/access/rmgrdesc - xactdesc.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 70.6 % 248 175
Test Date: 2026-03-03 07:15:00 Functions: 75.0 % 12 9
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-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/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        27835 : ParseCommitRecord(uint8 info, xl_xact_commit *xlrec, xl_xact_parsed_commit *parsed)
      36              : {
      37        27835 :     char       *data = ((char *) xlrec) + MinSizeOfXactCommit;
      38              : 
      39        27835 :     memset(parsed, 0, sizeof(*parsed));
      40              : 
      41        27835 :     parsed->xinfo = 0;           /* default, if no XLOG_XACT_HAS_INFO is
      42              :                                  * present */
      43              : 
      44        27835 :     parsed->xact_time = xlrec->xact_time;
      45              : 
      46        27835 :     if (info & XLOG_XACT_HAS_INFO)
      47              :     {
      48        20585 :         xl_xact_xinfo *xl_xinfo = (xl_xact_xinfo *) data;
      49              : 
      50        20585 :         parsed->xinfo = xl_xinfo->xinfo;
      51              : 
      52        20585 :         data += sizeof(xl_xact_xinfo);
      53              :     }
      54              : 
      55        27835 :     if (parsed->xinfo & XACT_XINFO_HAS_DBINFO)
      56              :     {
      57        20421 :         xl_xact_dbinfo *xl_dbinfo = (xl_xact_dbinfo *) data;
      58              : 
      59        20421 :         parsed->dbId = xl_dbinfo->dbId;
      60        20421 :         parsed->tsId = xl_dbinfo->tsId;
      61              : 
      62        20421 :         data += sizeof(xl_xact_dbinfo);
      63              :     }
      64              : 
      65        27835 :     if (parsed->xinfo & XACT_XINFO_HAS_SUBXACTS)
      66              :     {
      67          230 :         xl_xact_subxacts *xl_subxacts = (xl_xact_subxacts *) data;
      68              : 
      69          230 :         parsed->nsubxacts = xl_subxacts->nsubxacts;
      70          230 :         parsed->subxacts = xl_subxacts->subxacts;
      71              : 
      72          230 :         data += MinSizeOfXactSubxacts;
      73          230 :         data += parsed->nsubxacts * sizeof(TransactionId);
      74              :     }
      75              : 
      76        27835 :     if (parsed->xinfo & XACT_XINFO_HAS_RELFILELOCATORS)
      77              :     {
      78         2415 :         xl_xact_relfilelocators *xl_rellocators = (xl_xact_relfilelocators *) data;
      79              : 
      80         2415 :         parsed->nrels = xl_rellocators->nrels;
      81         2415 :         parsed->xlocators = xl_rellocators->xlocators;
      82              : 
      83         2415 :         data += MinSizeOfXactRelfileLocators;
      84         2415 :         data += xl_rellocators->nrels * sizeof(RelFileLocator);
      85              :     }
      86              : 
      87        27835 :     if (parsed->xinfo & XACT_XINFO_HAS_DROPPED_STATS)
      88              :     {
      89         3013 :         xl_xact_stats_items *xl_drops = (xl_xact_stats_items *) data;
      90              : 
      91         3013 :         parsed->nstats = xl_drops->nitems;
      92         3013 :         parsed->stats = xl_drops->items;
      93              : 
      94         3013 :         data += MinSizeOfXactStatsItems;
      95         3013 :         data += xl_drops->nitems * sizeof(xl_xact_stats_item);
      96              :     }
      97              : 
      98        27835 :     if (parsed->xinfo & XACT_XINFO_HAS_INVALS)
      99              :     {
     100        18257 :         xl_xact_invals *xl_invals = (xl_xact_invals *) data;
     101              : 
     102        18257 :         parsed->nmsgs = xl_invals->nmsgs;
     103        18257 :         parsed->msgs = xl_invals->msgs;
     104              : 
     105        18257 :         data += MinSizeOfXactInvals;
     106        18257 :         data += xl_invals->nmsgs * sizeof(SharedInvalidationMessage);
     107              :     }
     108              : 
     109        27835 :     if (parsed->xinfo & XACT_XINFO_HAS_TWOPHASE)
     110              :     {
     111          229 :         xl_xact_twophase *xl_twophase = (xl_xact_twophase *) data;
     112              : 
     113          229 :         parsed->twophase_xid = xl_twophase->xid;
     114              : 
     115          229 :         data += sizeof(xl_xact_twophase);
     116              : 
     117          229 :         if (parsed->xinfo & XACT_XINFO_HAS_GID)
     118              :         {
     119          130 :             strlcpy(parsed->twophase_gid, data, sizeof(parsed->twophase_gid));
     120          130 :             data += strlen(data) + 1;
     121              :         }
     122              :     }
     123              : 
     124              :     /* Note: no alignment is guaranteed after this point */
     125              : 
     126        27835 :     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          125 :         memcpy(&xl_origin, data, sizeof(xl_origin));
     132              : 
     133          125 :         parsed->origin_lsn = xl_origin.origin_lsn;
     134          125 :         parsed->origin_timestamp = xl_origin.origin_timestamp;
     135              : 
     136          125 :         data += sizeof(xl_xact_origin);
     137              :     }
     138        27835 : }
     139              : 
     140              : void
     141         2125 : ParseAbortRecord(uint8 info, xl_xact_abort *xlrec, xl_xact_parsed_abort *parsed)
     142              : {
     143         2125 :     char       *data = ((char *) xlrec) + MinSizeOfXactAbort;
     144              : 
     145         2125 :     memset(parsed, 0, sizeof(*parsed));
     146              : 
     147         2125 :     parsed->xinfo = 0;           /* default, if no XLOG_XACT_HAS_INFO is
     148              :                                  * present */
     149              : 
     150         2125 :     parsed->xact_time = xlrec->xact_time;
     151              : 
     152         2125 :     if (info & XLOG_XACT_HAS_INFO)
     153              :     {
     154         1358 :         xl_xact_xinfo *xl_xinfo = (xl_xact_xinfo *) data;
     155              : 
     156         1358 :         parsed->xinfo = xl_xinfo->xinfo;
     157              : 
     158         1358 :         data += sizeof(xl_xact_xinfo);
     159              :     }
     160              : 
     161         2125 :     if (parsed->xinfo & XACT_XINFO_HAS_DBINFO)
     162              :     {
     163           50 :         xl_xact_dbinfo *xl_dbinfo = (xl_xact_dbinfo *) data;
     164              : 
     165           50 :         parsed->dbId = xl_dbinfo->dbId;
     166           50 :         parsed->tsId = xl_dbinfo->tsId;
     167              : 
     168           50 :         data += sizeof(xl_xact_dbinfo);
     169              :     }
     170              : 
     171         2125 :     if (parsed->xinfo & XACT_XINFO_HAS_SUBXACTS)
     172              :     {
     173           23 :         xl_xact_subxacts *xl_subxacts = (xl_xact_subxacts *) data;
     174              : 
     175           23 :         parsed->nsubxacts = xl_subxacts->nsubxacts;
     176           23 :         parsed->subxacts = xl_subxacts->subxacts;
     177              : 
     178           23 :         data += MinSizeOfXactSubxacts;
     179           23 :         data += parsed->nsubxacts * sizeof(TransactionId);
     180              :     }
     181              : 
     182         2125 :     if (parsed->xinfo & XACT_XINFO_HAS_RELFILELOCATORS)
     183              :     {
     184          350 :         xl_xact_relfilelocators *xl_rellocator = (xl_xact_relfilelocators *) data;
     185              : 
     186          350 :         parsed->nrels = xl_rellocator->nrels;
     187          350 :         parsed->xlocators = xl_rellocator->xlocators;
     188              : 
     189          350 :         data += MinSizeOfXactRelfileLocators;
     190          350 :         data += xl_rellocator->nrels * sizeof(RelFileLocator);
     191              :     }
     192              : 
     193         2125 :     if (parsed->xinfo & XACT_XINFO_HAS_DROPPED_STATS)
     194              :     {
     195          455 :         xl_xact_stats_items *xl_drops = (xl_xact_stats_items *) data;
     196              : 
     197          455 :         parsed->nstats = xl_drops->nitems;
     198          455 :         parsed->stats = xl_drops->items;
     199              : 
     200          455 :         data += MinSizeOfXactStatsItems;
     201          455 :         data += xl_drops->nitems * sizeof(xl_xact_stats_item);
     202              :     }
     203              : 
     204         2125 :     if (parsed->xinfo & XACT_XINFO_HAS_TWOPHASE)
     205              :     {
     206           94 :         xl_xact_twophase *xl_twophase = (xl_xact_twophase *) data;
     207              : 
     208           94 :         parsed->twophase_xid = xl_twophase->xid;
     209              : 
     210           94 :         data += sizeof(xl_xact_twophase);
     211              : 
     212           94 :         if (parsed->xinfo & XACT_XINFO_HAS_GID)
     213              :         {
     214           50 :             strlcpy(parsed->twophase_gid, data, sizeof(parsed->twophase_gid));
     215           50 :             data += strlen(data) + 1;
     216              :         }
     217              :     }
     218              : 
     219              :     /* Note: no alignment is guaranteed after this point */
     220              : 
     221         2125 :     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            9 :         memcpy(&xl_origin, data, sizeof(xl_origin));
     227              : 
     228            9 :         parsed->origin_lsn = xl_origin.origin_lsn;
     229            9 :         parsed->origin_timestamp = xl_origin.origin_timestamp;
     230              : 
     231            9 :         data += sizeof(xl_xact_origin);
     232              :     }
     233         2125 : }
     234              : 
     235              : /*
     236              :  * ParsePrepareRecord
     237              :  */
     238              : void
     239          188 : ParsePrepareRecord(uint8 info, xl_xact_prepare *xlrec, xl_xact_parsed_prepare *parsed)
     240              : {
     241              :     char       *bufptr;
     242              : 
     243          188 :     bufptr = ((char *) xlrec) + MAXALIGN(sizeof(xl_xact_prepare));
     244              : 
     245          188 :     memset(parsed, 0, sizeof(*parsed));
     246              : 
     247          188 :     parsed->xact_time = xlrec->prepared_at;
     248          188 :     parsed->origin_lsn = xlrec->origin_lsn;
     249          188 :     parsed->origin_timestamp = xlrec->origin_timestamp;
     250          188 :     parsed->twophase_xid = xlrec->xid;
     251          188 :     parsed->dbId = xlrec->database;
     252          188 :     parsed->nsubxacts = xlrec->nsubxacts;
     253          188 :     parsed->nrels = xlrec->ncommitrels;
     254          188 :     parsed->nabortrels = xlrec->nabortrels;
     255          188 :     parsed->nstats = xlrec->ncommitstats;
     256          188 :     parsed->nabortstats = xlrec->nabortstats;
     257          188 :     parsed->nmsgs = xlrec->ninvalmsgs;
     258              : 
     259          188 :     strncpy(parsed->twophase_gid, bufptr, xlrec->gidlen);
     260          188 :     bufptr += MAXALIGN(xlrec->gidlen);
     261              : 
     262          188 :     parsed->subxacts = (TransactionId *) bufptr;
     263          188 :     bufptr += MAXALIGN(xlrec->nsubxacts * sizeof(TransactionId));
     264              : 
     265          188 :     parsed->xlocators = (RelFileLocator *) bufptr;
     266          188 :     bufptr += MAXALIGN(xlrec->ncommitrels * sizeof(RelFileLocator));
     267              : 
     268          188 :     parsed->abortlocators = (RelFileLocator *) bufptr;
     269          188 :     bufptr += MAXALIGN(xlrec->nabortrels * sizeof(RelFileLocator));
     270              : 
     271          188 :     parsed->stats = (xl_xact_stats_item *) bufptr;
     272          188 :     bufptr += MAXALIGN(xlrec->ncommitstats * sizeof(xl_xact_stats_item));
     273              : 
     274          188 :     parsed->abortstats = (xl_xact_stats_item *) bufptr;
     275          188 :     bufptr += MAXALIGN(xlrec->nabortstats * sizeof(xl_xact_stats_item));
     276              : 
     277          188 :     parsed->msgs = (SharedInvalidationMessage *) bufptr;
     278          188 :     bufptr += MAXALIGN(xlrec->ninvalmsgs * sizeof(SharedInvalidationMessage));
     279          188 : }
     280              : 
     281              : static void
     282           24 : xact_desc_relations(StringInfo buf, char *label, int nrels,
     283              :                     RelFileLocator *xlocators)
     284              : {
     285              :     int         i;
     286              : 
     287           24 :     if (nrels > 0)
     288              :     {
     289            3 :         appendStringInfo(buf, "; %s:", label);
     290           11 :         for (i = 0; i < nrels; i++)
     291              :         {
     292            8 :             appendStringInfo(buf, " %s",
     293            8 :                              relpathperm(xlocators[i], MAIN_FORKNUM).str);
     294              :         }
     295              :     }
     296           24 : }
     297              : 
     298              : static void
     299           24 : xact_desc_subxacts(StringInfo buf, int nsubxacts, TransactionId *subxacts)
     300              : {
     301              :     int         i;
     302              : 
     303           24 :     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           24 : }
     310              : 
     311              : static void
     312           24 : xact_desc_stats(StringInfo buf, const char *label,
     313              :                 int ndropped, xl_xact_stats_item *dropped_stats)
     314              : {
     315              :     int         i;
     316              : 
     317           24 :     if (ndropped > 0)
     318              :     {
     319            6 :         appendStringInfo(buf, "; %sdropped stats:", label);
     320           15 :         for (i = 0; i < ndropped; i++)
     321              :         {
     322            9 :             uint64      objid =
     323            9 :                 ((uint64) dropped_stats[i].objid_hi) << 32 | dropped_stats[i].objid_lo;
     324              : 
     325            9 :             appendStringInfo(buf, " %d/%u/%" PRIu64,
     326            9 :                              dropped_stats[i].kind,
     327            9 :                              dropped_stats[i].dboid,
     328              :                              objid);
     329              :         }
     330              :     }
     331           24 : }
     332              : 
     333              : static void
     334           24 : xact_desc_commit(StringInfo buf, uint8 info, xl_xact_commit *xlrec, ReplOriginId origin_id)
     335              : {
     336              :     xl_xact_parsed_commit parsed;
     337              : 
     338           24 :     ParseCommitRecord(info, xlrec, &parsed);
     339              : 
     340              :     /* If this is a prepared xact, show the xid of the original xact */
     341           24 :     if (TransactionIdIsValid(parsed.twophase_xid))
     342            0 :         appendStringInfo(buf, "%u: ", parsed.twophase_xid);
     343              : 
     344           24 :     appendStringInfoString(buf, timestamptz_to_str(xlrec->xact_time));
     345              : 
     346           24 :     xact_desc_relations(buf, "rels", parsed.nrels, parsed.xlocators);
     347           24 :     xact_desc_subxacts(buf, parsed.nsubxacts, parsed.subxacts);
     348           24 :     xact_desc_stats(buf, "", parsed.nstats, parsed.stats);
     349              : 
     350           24 :     standby_desc_invalidations(buf, parsed.nmsgs, parsed.msgs, parsed.dbId,
     351              :                                parsed.tsId,
     352           24 :                                XactCompletionRelcacheInitFileInval(parsed.xinfo));
     353              : 
     354           24 :     if (XactCompletionApplyFeedback(parsed.xinfo))
     355            0 :         appendStringInfoString(buf, "; apply_feedback");
     356              : 
     357           24 :     if (XactCompletionForceSyncCommit(parsed.xinfo))
     358           11 :         appendStringInfoString(buf, "; sync");
     359              : 
     360           24 :     if (parsed.xinfo & XACT_XINFO_HAS_ORIGIN)
     361              :     {
     362            0 :         appendStringInfo(buf, "; origin: node %u, lsn %X/%08X, at %s",
     363              :                          origin_id,
     364            0 :                          LSN_FORMAT_ARGS(parsed.origin_lsn),
     365              :                          timestamptz_to_str(parsed.origin_timestamp));
     366              :     }
     367           24 : }
     368              : 
     369              : static void
     370            0 : xact_desc_abort(StringInfo buf, uint8 info, xl_xact_abort *xlrec, ReplOriginId origin_id)
     371              : {
     372              :     xl_xact_parsed_abort parsed;
     373              : 
     374            0 :     ParseAbortRecord(info, xlrec, &parsed);
     375              : 
     376              :     /* If this is a prepared xact, show the xid of the original xact */
     377            0 :     if (TransactionIdIsValid(parsed.twophase_xid))
     378            0 :         appendStringInfo(buf, "%u: ", parsed.twophase_xid);
     379              : 
     380            0 :     appendStringInfoString(buf, timestamptz_to_str(xlrec->xact_time));
     381              : 
     382            0 :     xact_desc_relations(buf, "rels", parsed.nrels, parsed.xlocators);
     383            0 :     xact_desc_subxacts(buf, parsed.nsubxacts, parsed.subxacts);
     384              : 
     385            0 :     if (parsed.xinfo & XACT_XINFO_HAS_ORIGIN)
     386              :     {
     387            0 :         appendStringInfo(buf, "; origin: node %u, lsn %X/%08X, at %s",
     388              :                          origin_id,
     389            0 :                          LSN_FORMAT_ARGS(parsed.origin_lsn),
     390              :                          timestamptz_to_str(parsed.origin_timestamp));
     391              :     }
     392              : 
     393            0 :     xact_desc_stats(buf, "", parsed.nstats, parsed.stats);
     394            0 : }
     395              : 
     396              : static void
     397            0 : xact_desc_prepare(StringInfo buf, uint8 info, xl_xact_prepare *xlrec, ReplOriginId 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 != InvalidReplOriginId)
     421            0 :         appendStringInfo(buf, "; origin: node %u, lsn %X/%08X, 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           24 : xact_desc(StringInfo buf, XLogReaderState *record)
     440              : {
     441           24 :     char       *rec = XLogRecGetData(record);
     442           24 :     uint8       info = XLogRecGetInfo(record) & XLOG_XACT_OPMASK;
     443              : 
     444           24 :     if (info == XLOG_XACT_COMMIT || info == XLOG_XACT_COMMIT_PREPARED)
     445           24 :     {
     446           24 :         xl_xact_commit *xlrec = (xl_xact_commit *) rec;
     447              : 
     448           24 :         xact_desc_commit(buf, XLogRecGetInfo(record), xlrec,
     449           24 :                          XLogRecGetOrigin(record));
     450              :     }
     451            0 :     else if (info == XLOG_XACT_ABORT || info == XLOG_XACT_ABORT_PREPARED)
     452            0 :     {
     453            0 :         xl_xact_abort *xlrec = (xl_xact_abort *) rec;
     454              : 
     455            0 :         xact_desc_abort(buf, XLogRecGetInfo(record), xlrec,
     456            0 :                         XLogRecGetOrigin(record));
     457              :     }
     458            0 :     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            0 :     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            0 :     else if (info == XLOG_XACT_INVALIDATIONS)
     478              :     {
     479            0 :         xl_xact_invals *xlrec = (xl_xact_invals *) rec;
     480              : 
     481            0 :         standby_desc_invalidations(buf, xlrec->nmsgs, xlrec->msgs, InvalidOid,
     482              :                                    InvalidOid, false);
     483              :     }
     484           24 : }
     485              : 
     486              : const char *
     487           24 : xact_identify(uint8 info)
     488              : {
     489           24 :     const char *id = NULL;
     490              : 
     491           24 :     switch (info & XLOG_XACT_OPMASK)
     492              :     {
     493           24 :         case XLOG_XACT_COMMIT:
     494           24 :             id = "COMMIT";
     495           24 :             break;
     496            0 :         case XLOG_XACT_PREPARE:
     497            0 :             id = "PREPARE";
     498            0 :             break;
     499            0 :         case XLOG_XACT_ABORT:
     500            0 :             id = "ABORT";
     501            0 :             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            0 :         case XLOG_XACT_INVALIDATIONS:
     512            0 :             id = "INVALIDATION";
     513            0 :             break;
     514              :     }
     515              : 
     516           24 :     return id;
     517              : }
        

Generated by: LCOV version 2.0-1