Age Owner Branch data TLA 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
209 michael@paquier.xyz 33 :GNC 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)
209 michael@paquier.xyz 46 [ # # ]:UNC 0 : ereport(ERROR,
47 : : (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
48 : : errmsg("invalid MultiXactId: %u", mxid)));
49 : :
209 michael@paquier.xyz 50 [ + + ]:GNC 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 : :
95 58 : 9990 : multi = palloc_object(mxact);
59 : : /* no need to allow for old values here */
209 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)
209 michael@paquier.xyz 65 [ # # ]:UNC 0 : elog(ERROR, "return type must be a row type");
209 michael@paquier.xyz 66 :GNC 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
75 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)
75 michael@paquier.xyz 113 [ # # ]:UNC 0 : ereport(ERROR,
114 : : (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
115 : : errmsg("return type must be a row type")));
116 : :
75 michael@paquier.xyz 117 :GNC 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 : : }
|