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 : }
|