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