LCOV - differential code coverage report
Current view: top level - src/backend/access/rmgrdesc - xactdesc.c (source / functions) Coverage Total Hit UNC UBC GNC CBC DUB DCB
Current: Differential Code Coverage HEAD vs 15 Lines: 70.3 % 246 173 2 71 18 155 2 18
Current Date: 2023-04-08 15:15:32 Functions: 75.0 % 12 9 2 1 5 4
Baseline: 15
Baseline Date: 2023-04-08 15:09:40
Legend: Lines: hit not hit

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

Generated by: LCOV version v1.16-55-g56c0a2a