LCOV - code coverage report
Current view: top level - contrib/pg_logicalinspect - pg_logicalinspect.c (source / functions) Hit Total Coverage
Test: PostgreSQL 18devel Lines: 59 70 84.3 %
Date: 2024-12-12 20:14:52 Functions: 6 6 100.0 %
Legend: Lines: hit not hit

          Line data    Source code
       1             : /*-------------------------------------------------------------------------
       2             :  *
       3             :  * pg_logicalinspect.c
       4             :  *        Functions to inspect contents of PostgreSQL logical snapshots
       5             :  *
       6             :  * Copyright (c) 2024, 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             : 
      21           4 : PG_MODULE_MAGIC;
      22             : 
      23           4 : PG_FUNCTION_INFO_V1(pg_get_logical_snapshot_meta);
      24           4 : PG_FUNCTION_INFO_V1(pg_get_logical_snapshot_info);
      25             : 
      26             : /* Return the description of SnapBuildState */
      27             : static const char *
      28           4 : get_snapbuild_state_desc(SnapBuildState state)
      29             : {
      30           4 :     const char *stateDesc = "unknown state";
      31             : 
      32           4 :     switch (state)
      33             :     {
      34           0 :         case SNAPBUILD_START:
      35           0 :             stateDesc = "start";
      36           0 :             break;
      37           0 :         case SNAPBUILD_BUILDING_SNAPSHOT:
      38           0 :             stateDesc = "building";
      39           0 :             break;
      40           0 :         case SNAPBUILD_FULL_SNAPSHOT:
      41           0 :             stateDesc = "full";
      42           0 :             break;
      43           4 :         case SNAPBUILD_CONSISTENT:
      44           4 :             stateDesc = "consistent";
      45           4 :             break;
      46             :     }
      47             : 
      48           4 :     return stateDesc;
      49             : }
      50             : 
      51             : /*
      52             :  * Retrieve the logical snapshot file metadata.
      53             :  */
      54             : Datum
      55           4 : pg_get_logical_snapshot_meta(PG_FUNCTION_ARGS)
      56             : {
      57             : #define PG_GET_LOGICAL_SNAPSHOT_META_COLS 3
      58             :     SnapBuildOnDisk ondisk;
      59             :     HeapTuple   tuple;
      60           4 :     Datum       values[PG_GET_LOGICAL_SNAPSHOT_META_COLS] = {0};
      61           4 :     bool        nulls[PG_GET_LOGICAL_SNAPSHOT_META_COLS] = {0};
      62             :     TupleDesc   tupdesc;
      63             :     char        path[MAXPGPATH];
      64           4 :     int         i = 0;
      65           4 :     text       *filename_t = PG_GETARG_TEXT_PP(0);
      66             : 
      67             :     /* Build a tuple descriptor for our result type */
      68           4 :     if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
      69           0 :         elog(ERROR, "return type must be a row type");
      70             : 
      71           4 :     sprintf(path, "%s/%s",
      72             :             PG_LOGICAL_SNAPSHOTS_DIR,
      73             :             text_to_cstring(filename_t));
      74             : 
      75             :     /* Validate and restore the snapshot to 'ondisk' */
      76           4 :     SnapBuildRestoreSnapshot(&ondisk, path, CurrentMemoryContext, false);
      77             : 
      78           4 :     values[i++] = UInt32GetDatum(ondisk.magic);
      79           4 :     values[i++] = Int64GetDatum((int64) ondisk.checksum);
      80           4 :     values[i++] = UInt32GetDatum(ondisk.version);
      81             : 
      82             :     Assert(i == PG_GET_LOGICAL_SNAPSHOT_META_COLS);
      83             : 
      84           4 :     tuple = heap_form_tuple(tupdesc, values, nulls);
      85             : 
      86           4 :     PG_RETURN_DATUM(HeapTupleGetDatum(tuple));
      87             : 
      88             : #undef PG_GET_LOGICAL_SNAPSHOT_META_COLS
      89             : }
      90             : 
      91             : Datum
      92           4 : pg_get_logical_snapshot_info(PG_FUNCTION_ARGS)
      93             : {
      94             : #define PG_GET_LOGICAL_SNAPSHOT_INFO_COLS 14
      95             :     SnapBuildOnDisk ondisk;
      96             :     HeapTuple   tuple;
      97           4 :     Datum       values[PG_GET_LOGICAL_SNAPSHOT_INFO_COLS] = {0};
      98           4 :     bool        nulls[PG_GET_LOGICAL_SNAPSHOT_INFO_COLS] = {0};
      99             :     TupleDesc   tupdesc;
     100             :     char        path[MAXPGPATH];
     101           4 :     int         i = 0;
     102           4 :     text       *filename_t = PG_GETARG_TEXT_PP(0);
     103             : 
     104             :     /* Build a tuple descriptor for our result type */
     105           4 :     if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
     106           0 :         elog(ERROR, "return type must be a row type");
     107             : 
     108           4 :     sprintf(path, "%s/%s",
     109             :             PG_LOGICAL_SNAPSHOTS_DIR,
     110             :             text_to_cstring(filename_t));
     111             : 
     112             :     /* Validate and restore the snapshot to 'ondisk' */
     113           4 :     SnapBuildRestoreSnapshot(&ondisk, path, CurrentMemoryContext, false);
     114             : 
     115           4 :     values[i++] = CStringGetTextDatum(get_snapbuild_state_desc(ondisk.builder.state));
     116           4 :     values[i++] = TransactionIdGetDatum(ondisk.builder.xmin);
     117           4 :     values[i++] = TransactionIdGetDatum(ondisk.builder.xmax);
     118           4 :     values[i++] = LSNGetDatum(ondisk.builder.start_decoding_at);
     119           4 :     values[i++] = LSNGetDatum(ondisk.builder.two_phase_at);
     120           4 :     values[i++] = TransactionIdGetDatum(ondisk.builder.initial_xmin_horizon);
     121           4 :     values[i++] = BoolGetDatum(ondisk.builder.building_full_snapshot);
     122           4 :     values[i++] = BoolGetDatum(ondisk.builder.in_slot_creation);
     123           4 :     values[i++] = LSNGetDatum(ondisk.builder.last_serialized_snapshot);
     124           4 :     values[i++] = TransactionIdGetDatum(ondisk.builder.next_phase_at);
     125             : 
     126           4 :     values[i++] = UInt32GetDatum(ondisk.builder.committed.xcnt);
     127           4 :     if (ondisk.builder.committed.xcnt > 0)
     128             :     {
     129             :         Datum      *arrayelems;
     130             : 
     131           2 :         arrayelems = (Datum *) palloc(ondisk.builder.committed.xcnt * sizeof(Datum));
     132             : 
     133           6 :         for (int j = 0; j < ondisk.builder.committed.xcnt; j++)
     134           4 :             arrayelems[j] = TransactionIdGetDatum(ondisk.builder.committed.xip[j]);
     135             : 
     136           2 :         values[i++] = PointerGetDatum(construct_array_builtin(arrayelems,
     137           2 :                                                               ondisk.builder.committed.xcnt,
     138             :                                                               XIDOID));
     139             :     }
     140             :     else
     141           2 :         nulls[i++] = true;
     142             : 
     143           4 :     values[i++] = UInt32GetDatum(ondisk.builder.catchange.xcnt);
     144           4 :     if (ondisk.builder.catchange.xcnt > 0)
     145             :     {
     146             :         Datum      *arrayelems;
     147             : 
     148           2 :         arrayelems = (Datum *) palloc(ondisk.builder.catchange.xcnt * sizeof(Datum));
     149             : 
     150           6 :         for (int j = 0; j < ondisk.builder.catchange.xcnt; j++)
     151           4 :             arrayelems[j] = TransactionIdGetDatum(ondisk.builder.catchange.xip[j]);
     152             : 
     153           2 :         values[i++] = PointerGetDatum(construct_array_builtin(arrayelems,
     154           2 :                                                               ondisk.builder.catchange.xcnt,
     155             :                                                               XIDOID));
     156             :     }
     157             :     else
     158           2 :         nulls[i++] = true;
     159             : 
     160             :     Assert(i == PG_GET_LOGICAL_SNAPSHOT_INFO_COLS);
     161             : 
     162           4 :     tuple = heap_form_tuple(tupdesc, values, nulls);
     163             : 
     164           4 :     PG_RETURN_DATUM(HeapTupleGetDatum(tuple));
     165             : 
     166             : #undef PG_GET_LOGICAL_SNAPSHOT_INFO_COLS
     167             : }

Generated by: LCOV version 1.14