LCOV - code coverage report
Current view: top level - src/backend/utils/adt - multixactfuncs.c (source / functions) Coverage Total Hit
Test: PostgreSQL 19devel Lines: 92.5 % 40 37
Test Date: 2026-03-01 15:14:58 Functions: 100.0 % 2 2
Legend: Lines:     hit not hit

            Line data    Source code
       1              : /*-------------------------------------------------------------------------
       2              :  *
       3              :  * multixactfuncs.c
       4              :  *    Functions for accessing multixact-related data.
       5              :  *
       6              :  * Portions Copyright (c) 1996-2026, PostgreSQL Global Development Group
       7              :  * Portions Copyright (c) 1994, Regents of the University of California
       8              :  *
       9              :  * IDENTIFICATION
      10              :  *    src/backend/utils/adt/multixactfuncs.c
      11              :  *
      12              :  *-------------------------------------------------------------------------
      13              :  */
      14              : 
      15              : #include "postgres.h"
      16              : 
      17              : #include "access/htup_details.h"
      18              : #include "access/multixact.h"
      19              : #include "access/multixact_internal.h"
      20              : #include "catalog/pg_authid_d.h"
      21              : #include "funcapi.h"
      22              : #include "miscadmin.h"
      23              : #include "utils/acl.h"
      24              : #include "utils/builtins.h"
      25              : 
      26              : /*
      27              :  * pg_get_multixact_members
      28              :  *
      29              :  * Returns information about the MultiXactMembers of the specified
      30              :  * MultiXactId.
      31              :  */
      32              : Datum
      33       198078 : pg_get_multixact_members(PG_FUNCTION_ARGS)
      34              : {
      35              :     typedef struct
      36              :     {
      37              :         MultiXactMember *members;
      38              :         int         nmembers;
      39              :         int         iter;
      40              :     } mxact;
      41       198078 :     MultiXactId mxid = PG_GETARG_TRANSACTIONID(0);
      42              :     mxact      *multi;
      43              :     FuncCallContext *funccxt;
      44              : 
      45       198078 :     if (mxid < FirstMultiXactId)
      46            0 :         ereport(ERROR,
      47              :                 (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
      48              :                  errmsg("invalid MultiXactId: %u", mxid)));
      49              : 
      50       198078 :     if (SRF_IS_FIRSTCALL())
      51              :     {
      52              :         MemoryContext oldcxt;
      53              :         TupleDesc   tupdesc;
      54              : 
      55         9990 :         funccxt = SRF_FIRSTCALL_INIT();
      56         9990 :         oldcxt = MemoryContextSwitchTo(funccxt->multi_call_memory_ctx);
      57              : 
      58         9990 :         multi = palloc_object(mxact);
      59              :         /* no need to allow for old values here */
      60         9990 :         multi->nmembers = GetMultiXactIdMembers(mxid, &multi->members, false,
      61              :                                                 false);
      62         9990 :         multi->iter = 0;
      63              : 
      64         9990 :         if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
      65            0 :             elog(ERROR, "return type must be a row type");
      66         9990 :         funccxt->tuple_desc = tupdesc;
      67         9990 :         funccxt->attinmeta = TupleDescGetAttInMetadata(tupdesc);
      68         9990 :         funccxt->user_fctx = multi;
      69              : 
      70         9990 :         MemoryContextSwitchTo(oldcxt);
      71              :     }
      72              : 
      73       198078 :     funccxt = SRF_PERCALL_SETUP();
      74       198078 :     multi = (mxact *) funccxt->user_fctx;
      75              : 
      76       198078 :     while (multi->iter < multi->nmembers)
      77              :     {
      78              :         HeapTuple   tuple;
      79              :         char       *values[2];
      80              : 
      81       188088 :         values[0] = psprintf("%u", multi->members[multi->iter].xid);
      82       188088 :         values[1] = mxstatus_to_string(multi->members[multi->iter].status);
      83              : 
      84       188088 :         tuple = BuildTupleFromCStrings(funccxt->attinmeta, values);
      85              : 
      86       188088 :         multi->iter++;
      87       188088 :         pfree(values[0]);
      88       188088 :         SRF_RETURN_NEXT(funccxt, HeapTupleGetDatum(tuple));
      89              :     }
      90              : 
      91         9990 :     SRF_RETURN_DONE(funccxt);
      92              : }
      93              : 
      94              : /*
      95              :  * pg_get_multixact_stats
      96              :  *
      97              :  * Returns statistics about current multixact usage.
      98              :  */
      99              : Datum
     100           12 : pg_get_multixact_stats(PG_FUNCTION_ARGS)
     101              : {
     102              :     TupleDesc   tupdesc;
     103              :     Datum       values[4];
     104              :     bool        nulls[4];
     105              :     uint64      members;
     106              :     MultiXactId oldestMultiXactId;
     107              :     uint32      multixacts;
     108              :     MultiXactOffset oldestOffset;
     109              :     MultiXactOffset nextOffset;
     110              :     uint64      membersBytes;
     111              : 
     112           12 :     if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
     113            0 :         ereport(ERROR,
     114              :                 (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
     115              :                  errmsg("return type must be a row type")));
     116              : 
     117           12 :     GetMultiXactInfo(&multixacts, &nextOffset, &oldestMultiXactId, &oldestOffset);
     118           12 :     members = nextOffset - oldestOffset;
     119              : 
     120           12 :     membersBytes = MultiXactOffsetStorageSize(nextOffset, oldestOffset);
     121              : 
     122           12 :     if (!has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS))
     123              :     {
     124              :         /*
     125              :          * Only superusers and roles with privileges of pg_read_all_stats can
     126              :          * see details.
     127              :          */
     128            3 :         memset(nulls, true, sizeof(bool) * tupdesc->natts);
     129              :     }
     130              :     else
     131              :     {
     132            9 :         values[0] = UInt32GetDatum(multixacts);
     133            9 :         values[1] = Int64GetDatum(members);
     134            9 :         values[2] = Int64GetDatum(membersBytes);
     135            9 :         values[3] = UInt32GetDatum(oldestMultiXactId);
     136            9 :         memset(nulls, false, sizeof(nulls));
     137              :     }
     138              : 
     139           12 :     return HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls));
     140              : }
        

Generated by: LCOV version 2.0-1