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