LCOV - differential code coverage report
Current view: top level - contrib/pg_logicalinspect - pg_logicalinspect.c (source / functions) Coverage Total Hit UBC CBC
Current: c70b6db34ffeab48beef1fb4ce61bcad3772b8dd vs 06473f5a344df8c9594ead90a609b86f6724cff8 Lines: 79.3 % 82 65 17 65
Current Date: 2025-09-06 07:49:51 +0900 Functions: 100.0 % 7 7 7
Baseline: lcov-20250906-005545-baseline Branches: 41.9 % 31 13 18 13
Baseline Date: 2025-09-05 08:21:35 +0100 Line coverage date bins:
Legend: Lines:     hit not hit
Branches: + taken - not taken # not executed
(30,360] days: 79.3 % 82 65 17 65
Function coverage date bins:
(30,360] days: 100.0 % 7 7 7
Branch coverage date bins:
(30,360] days: 41.9 % 31 13 18 13

 Age         Owner                    Branch data    TLA  Line data    Source code
                                  1                 :                : /*-------------------------------------------------------------------------
                                  2                 :                :  *
                                  3                 :                :  * pg_logicalinspect.c
                                  4                 :                :  *        Functions to inspect contents of PostgreSQL logical snapshots
                                  5                 :                :  *
                                  6                 :                :  * Copyright (c) 2024-2025, PostgreSQL Global Development Group
                                  7                 :                :  *
                                  8                 :                :  * IDENTIFICATION
                                  9                 :                :  *        contrib/pg_logicalinspect/pg_logicalinspect.c
                                 10                 :                :  *
                                 11                 :                :  *-------------------------------------------------------------------------
                                 12                 :                :  */
                                 13                 :                : #include "postgres.h"
                                 14                 :                : 
                                 15                 :                : #include "funcapi.h"
                                 16                 :                : #include "replication/snapbuild_internal.h"
                                 17                 :                : #include "utils/array.h"
                                 18                 :                : #include "utils/builtins.h"
                                 19                 :                : #include "utils/pg_lsn.h"
                                 20                 :                : 
  164 tgl@sss.pgh.pa.us          21                 :CBC           2 : PG_MODULE_MAGIC_EXT(
                                 22                 :                :                     .name = "pg_logicalinspect",
                                 23                 :                :                     .version = PG_VERSION
                                 24                 :                : );
                                 25                 :                : 
  327 msawada@postgresql.o       26                 :              2 : PG_FUNCTION_INFO_V1(pg_get_logical_snapshot_meta);
                                 27                 :              2 : PG_FUNCTION_INFO_V1(pg_get_logical_snapshot_info);
                                 28                 :                : 
                                 29                 :                : /* Return the description of SnapBuildState */
                                 30                 :                : static const char *
                                 31                 :              1 : get_snapbuild_state_desc(SnapBuildState state)
                                 32                 :                : {
                                 33                 :              1 :     const char *stateDesc = "unknown state";
                                 34                 :                : 
                                 35   [ -  -  -  +  :              1 :     switch (state)
                                                 - ]
                                 36                 :                :     {
  327 msawada@postgresql.o       37                 :UBC           0 :         case SNAPBUILD_START:
                                 38                 :              0 :             stateDesc = "start";
                                 39                 :              0 :             break;
                                 40                 :              0 :         case SNAPBUILD_BUILDING_SNAPSHOT:
                                 41                 :              0 :             stateDesc = "building";
                                 42                 :              0 :             break;
                                 43                 :              0 :         case SNAPBUILD_FULL_SNAPSHOT:
                                 44                 :              0 :             stateDesc = "full";
                                 45                 :              0 :             break;
  327 msawada@postgresql.o       46                 :CBC           1 :         case SNAPBUILD_CONSISTENT:
                                 47                 :              1 :             stateDesc = "consistent";
                                 48                 :              1 :             break;
                                 49                 :                :     }
                                 50                 :                : 
                                 51                 :              1 :     return stateDesc;
                                 52                 :                : }
                                 53                 :                : 
                                 54                 :                : /*
                                 55                 :                :  * Extract the LSN from the given serialized snapshot file name.
                                 56                 :                :  */
                                 57                 :                : static XLogRecPtr
  179                            58                 :              2 : parse_snapshot_filename(const char *filename)
                                 59                 :                : {
                                 60                 :                :     uint32      hi;
                                 61                 :                :     uint32      lo;
                                 62                 :                :     XLogRecPtr  lsn;
                                 63                 :                :     char        tmpfname[MAXPGPATH];
                                 64                 :                : 
                                 65                 :                :     /*
                                 66                 :                :      * Extract the values to build the LSN.
                                 67                 :                :      *
                                 68                 :                :      * Note: Including ".snap" doesn't mean that sscanf() also does the format
                                 69                 :                :      * check including the suffix. The subsequent check validates if the given
                                 70                 :                :      * filename has the expected suffix.
                                 71                 :                :      */
                                 72         [ -  + ]:              2 :     if (sscanf(filename, "%X-%X.snap", &hi, &lo) != 2)
  179 msawada@postgresql.o       73                 :UBC           0 :         goto parse_error;
                                 74                 :                : 
                                 75                 :                :     /*
                                 76                 :                :      * Bring back the extracted LSN to the snapshot file format and compare it
                                 77                 :                :      * to the given filename. This check strictly checks if the given filename
                                 78                 :                :      * follows the format of the snapshot filename.
                                 79                 :                :      */
  179 msawada@postgresql.o       80                 :CBC           2 :     sprintf(tmpfname, "%X-%X.snap", hi, lo);
                                 81         [ -  + ]:              2 :     if (strcmp(tmpfname, filename) != 0)
  179 msawada@postgresql.o       82                 :UBC           0 :         goto parse_error;
                                 83                 :                : 
  179 msawada@postgresql.o       84                 :CBC           2 :     lsn = ((uint64) hi) << 32 | lo;
                                 85                 :                : 
                                 86                 :              2 :     return lsn;
                                 87                 :                : 
  179 msawada@postgresql.o       88                 :UBC           0 : parse_error:
                                 89         [ #  # ]:              0 :     ereport(ERROR,
                                 90                 :                :             errmsg("invalid snapshot file name \"%s\"", filename));
                                 91                 :                : 
                                 92                 :                :     return InvalidXLogRecPtr;   /* keep compiler quiet */
                                 93                 :                : }
                                 94                 :                : 
                                 95                 :                : /*
                                 96                 :                :  * Retrieve the logical snapshot file metadata.
                                 97                 :                :  */
                                 98                 :                : Datum
  327 msawada@postgresql.o       99                 :CBC           1 : pg_get_logical_snapshot_meta(PG_FUNCTION_ARGS)
                                100                 :                : {
                                101                 :                : #define PG_GET_LOGICAL_SNAPSHOT_META_COLS 3
                                102                 :                :     SnapBuildOnDisk ondisk;
                                103                 :                :     HeapTuple   tuple;
                                104                 :              1 :     Datum       values[PG_GET_LOGICAL_SNAPSHOT_META_COLS] = {0};
                                105                 :              1 :     bool        nulls[PG_GET_LOGICAL_SNAPSHOT_META_COLS] = {0};
                                106                 :                :     TupleDesc   tupdesc;
                                107                 :                :     XLogRecPtr  lsn;
                                108                 :              1 :     int         i = 0;
                                109                 :              1 :     text       *filename_t = PG_GETARG_TEXT_PP(0);
                                110                 :                : 
                                111                 :                :     /* Build a tuple descriptor for our result type */
                                112         [ -  + ]:              1 :     if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
  327 msawada@postgresql.o      113         [ #  # ]:UBC           0 :         elog(ERROR, "return type must be a row type");
                                114                 :                : 
  179 msawada@postgresql.o      115                 :CBC           1 :     lsn = parse_snapshot_filename(text_to_cstring(filename_t));
                                116                 :                : 
                                117                 :                :     /* Validate and restore the snapshot to 'ondisk' */
                                118                 :              1 :     SnapBuildRestoreSnapshot(&ondisk, lsn, CurrentMemoryContext, false);
                                119                 :                : 
  327                           120                 :              1 :     values[i++] = UInt32GetDatum(ondisk.magic);
                                121                 :              1 :     values[i++] = Int64GetDatum((int64) ondisk.checksum);
                                122                 :              1 :     values[i++] = UInt32GetDatum(ondisk.version);
                                123                 :                : 
                                124         [ -  + ]:              1 :     Assert(i == PG_GET_LOGICAL_SNAPSHOT_META_COLS);
                                125                 :                : 
                                126                 :              1 :     tuple = heap_form_tuple(tupdesc, values, nulls);
                                127                 :                : 
                                128                 :              1 :     PG_RETURN_DATUM(HeapTupleGetDatum(tuple));
                                129                 :                : 
                                130                 :                : #undef PG_GET_LOGICAL_SNAPSHOT_META_COLS
                                131                 :                : }
                                132                 :                : 
                                133                 :                : Datum
                                134                 :              1 : pg_get_logical_snapshot_info(PG_FUNCTION_ARGS)
                                135                 :                : {
                                136                 :                : #define PG_GET_LOGICAL_SNAPSHOT_INFO_COLS 14
                                137                 :                :     SnapBuildOnDisk ondisk;
                                138                 :                :     HeapTuple   tuple;
                                139                 :              1 :     Datum       values[PG_GET_LOGICAL_SNAPSHOT_INFO_COLS] = {0};
                                140                 :              1 :     bool        nulls[PG_GET_LOGICAL_SNAPSHOT_INFO_COLS] = {0};
                                141                 :                :     TupleDesc   tupdesc;
                                142                 :                :     XLogRecPtr  lsn;
                                143                 :              1 :     int         i = 0;
                                144                 :              1 :     text       *filename_t = PG_GETARG_TEXT_PP(0);
                                145                 :                : 
                                146                 :                :     /* Build a tuple descriptor for our result type */
                                147         [ -  + ]:              1 :     if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
  327 msawada@postgresql.o      148         [ #  # ]:UBC           0 :         elog(ERROR, "return type must be a row type");
                                149                 :                : 
  179 msawada@postgresql.o      150                 :CBC           1 :     lsn = parse_snapshot_filename(text_to_cstring(filename_t));
                                151                 :                : 
                                152                 :                :     /* Validate and restore the snapshot to 'ondisk' */
                                153                 :              1 :     SnapBuildRestoreSnapshot(&ondisk, lsn, CurrentMemoryContext, false);
                                154                 :                : 
  327                           155                 :              1 :     values[i++] = CStringGetTextDatum(get_snapbuild_state_desc(ondisk.builder.state));
                                156                 :              1 :     values[i++] = TransactionIdGetDatum(ondisk.builder.xmin);
                                157                 :              1 :     values[i++] = TransactionIdGetDatum(ondisk.builder.xmax);
                                158                 :              1 :     values[i++] = LSNGetDatum(ondisk.builder.start_decoding_at);
                                159                 :              1 :     values[i++] = LSNGetDatum(ondisk.builder.two_phase_at);
                                160                 :              1 :     values[i++] = TransactionIdGetDatum(ondisk.builder.initial_xmin_horizon);
                                161                 :              1 :     values[i++] = BoolGetDatum(ondisk.builder.building_full_snapshot);
                                162                 :              1 :     values[i++] = BoolGetDatum(ondisk.builder.in_slot_creation);
                                163                 :              1 :     values[i++] = LSNGetDatum(ondisk.builder.last_serialized_snapshot);
                                164                 :              1 :     values[i++] = TransactionIdGetDatum(ondisk.builder.next_phase_at);
                                165                 :                : 
                                166                 :              1 :     values[i++] = UInt32GetDatum(ondisk.builder.committed.xcnt);
                                167         [ +  - ]:              1 :     if (ondisk.builder.committed.xcnt > 0)
                                168                 :                :     {
                                169                 :                :         Datum      *arrayelems;
                                170                 :                : 
                                171                 :              1 :         arrayelems = (Datum *) palloc(ondisk.builder.committed.xcnt * sizeof(Datum));
                                172                 :                : 
                                173         [ +  + ]:              2 :         for (int j = 0; j < ondisk.builder.committed.xcnt; j++)
                                174                 :              1 :             arrayelems[j] = TransactionIdGetDatum(ondisk.builder.committed.xip[j]);
                                175                 :                : 
                                176                 :              1 :         values[i++] = PointerGetDatum(construct_array_builtin(arrayelems,
                                177                 :              1 :                                                               ondisk.builder.committed.xcnt,
                                178                 :                :                                                               XIDOID));
                                179                 :                :     }
                                180                 :                :     else
  327 msawada@postgresql.o      181                 :UBC           0 :         nulls[i++] = true;
                                182                 :                : 
  327 msawada@postgresql.o      183                 :CBC           1 :     values[i++] = UInt32GetDatum(ondisk.builder.catchange.xcnt);
                                184         [ +  - ]:              1 :     if (ondisk.builder.catchange.xcnt > 0)
                                185                 :                :     {
                                186                 :                :         Datum      *arrayelems;
                                187                 :                : 
                                188                 :              1 :         arrayelems = (Datum *) palloc(ondisk.builder.catchange.xcnt * sizeof(Datum));
                                189                 :                : 
                                190         [ +  + ]:              3 :         for (int j = 0; j < ondisk.builder.catchange.xcnt; j++)
                                191                 :              2 :             arrayelems[j] = TransactionIdGetDatum(ondisk.builder.catchange.xip[j]);
                                192                 :                : 
                                193                 :              1 :         values[i++] = PointerGetDatum(construct_array_builtin(arrayelems,
                                194                 :              1 :                                                               ondisk.builder.catchange.xcnt,
                                195                 :                :                                                               XIDOID));
                                196                 :                :     }
                                197                 :                :     else
  327 msawada@postgresql.o      198                 :UBC           0 :         nulls[i++] = true;
                                199                 :                : 
  327 msawada@postgresql.o      200         [ -  + ]:CBC           1 :     Assert(i == PG_GET_LOGICAL_SNAPSHOT_INFO_COLS);
                                201                 :                : 
                                202                 :              1 :     tuple = heap_form_tuple(tupdesc, values, nulls);
                                203                 :                : 
                                204                 :              1 :     PG_RETURN_DATUM(HeapTupleGetDatum(tuple));
                                205                 :                : 
                                206                 :                : #undef PG_GET_LOGICAL_SNAPSHOT_INFO_COLS
                                207                 :                : }
        

Generated by: LCOV version 2.4-beta