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 "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 : 0 : pg_get_multixact_members(PG_FUNCTION_ARGS)
34 : : {
35 : : typedef struct
36 : : {
37 : : MultiXactMember *members;
38 : : int nmembers;
39 : : int iter;
40 : : } mxact;
41 : 0 : MultiXactId mxid = PG_GETARG_TRANSACTIONID(0);
42 : 0 : mxact *multi;
43 : 0 : FuncCallContext *funccxt;
44 : :
45 [ # # ]: 0 : if (mxid < FirstMultiXactId)
46 [ # # # # ]: 0 : ereport(ERROR,
47 : : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
48 : : errmsg("invalid MultiXactId: %u", mxid)));
49 : :
50 [ # # ]: 0 : if (SRF_IS_FIRSTCALL())
51 : : {
52 : 0 : MemoryContext oldcxt;
53 : 0 : TupleDesc tupdesc;
54 : :
55 : 0 : funccxt = SRF_FIRSTCALL_INIT();
56 : 0 : oldcxt = MemoryContextSwitchTo(funccxt->multi_call_memory_ctx);
57 : :
58 : 0 : multi = palloc_object(mxact);
59 : : /* no need to allow for old values here */
60 : 0 : multi->nmembers = GetMultiXactIdMembers(mxid, &multi->members, false,
61 : : false);
62 : 0 : multi->iter = 0;
63 : :
64 [ # # ]: 0 : if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
65 [ # # # # ]: 0 : elog(ERROR, "return type must be a row type");
66 : 0 : funccxt->tuple_desc = tupdesc;
67 : 0 : funccxt->attinmeta = TupleDescGetAttInMetadata(tupdesc);
68 : 0 : funccxt->user_fctx = multi;
69 : :
70 : 0 : MemoryContextSwitchTo(oldcxt);
71 : 0 : }
72 : :
73 : 0 : funccxt = SRF_PERCALL_SETUP();
74 : 0 : multi = (mxact *) funccxt->user_fctx;
75 : :
76 [ # # ]: 0 : while (multi->iter < multi->nmembers)
77 : : {
78 : 0 : HeapTuple tuple;
79 : 0 : char *values[2];
80 : :
81 : 0 : values[0] = psprintf("%u", multi->members[multi->iter].xid);
82 : 0 : values[1] = mxstatus_to_string(multi->members[multi->iter].status);
83 : :
84 : 0 : tuple = BuildTupleFromCStrings(funccxt->attinmeta, values);
85 : :
86 : 0 : multi->iter++;
87 : 0 : pfree(values[0]);
88 : 0 : SRF_RETURN_NEXT(funccxt, HeapTupleGetDatum(tuple));
89 [ # # ]: 0 : }
90 : :
91 [ # # ]: 0 : SRF_RETURN_DONE(funccxt);
92 [ # # ]: 0 : }
93 : :
94 : : /*
95 : : * pg_get_multixact_stats
96 : : *
97 : : * Returns statistics about current multixact usage.
98 : : */
99 : : Datum
100 : 3 : pg_get_multixact_stats(PG_FUNCTION_ARGS)
101 : : {
102 : 3 : TupleDesc tupdesc;
103 : 3 : Datum values[4];
104 : 3 : bool nulls[4];
105 : 3 : uint64 members;
106 : 3 : MultiXactId oldestMultiXactId;
107 : 3 : uint32 multixacts;
108 : 3 : MultiXactOffset oldestOffset;
109 : 3 : MultiXactOffset nextOffset;
110 : 3 : uint64 membersBytes;
111 : :
112 [ + - ]: 3 : 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 : 3 : GetMultiXactInfo(&multixacts, &nextOffset, &oldestMultiXactId, &oldestOffset);
118 : 3 : members = nextOffset - oldestOffset;
119 : :
120 : 3 : membersBytes = MultiXactOffsetStorageSize(nextOffset, oldestOffset);
121 : :
122 [ + + ]: 3 : 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 : 1 : memset(nulls, true, sizeof(bool) * tupdesc->natts);
129 : 1 : }
130 : : else
131 : : {
132 : 2 : values[0] = UInt32GetDatum(multixacts);
133 : 2 : values[1] = Int64GetDatum(members);
134 : 2 : values[2] = Int64GetDatum(membersBytes);
135 : 2 : values[3] = UInt32GetDatum(oldestMultiXactId);
136 : 2 : memset(nulls, false, sizeof(nulls));
137 : : }
138 : :
139 : 6 : return HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls));
140 : 3 : }
|