static void mXactCachePut(MultiXactId multi, int nmembers,
MultiXactMember *members);
-static char *mxstatus_to_string(MultiXactStatus status);
-
/* management of SLRU infrastructure */
static bool MultiXactOffsetPagePrecedes(int64 page1, int64 page2);
static bool MultiXactMemberPagePrecedes(int64 page1, int64 page2);
}
}
-static char *
+char *
mxstatus_to_string(MultiXactStatus status)
{
switch (status)
elog(PANIC, "multixact_redo: unknown op code %u", info);
}
-Datum
-pg_get_multixact_members(PG_FUNCTION_ARGS)
-{
- typedef struct
- {
- MultiXactMember *members;
- int nmembers;
- int iter;
- } mxact;
- MultiXactId mxid = PG_GETARG_TRANSACTIONID(0);
- mxact *multi;
- FuncCallContext *funccxt;
-
- if (mxid < FirstMultiXactId)
- ereport(ERROR,
- (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
- errmsg("invalid MultiXactId: %u", mxid)));
-
- if (SRF_IS_FIRSTCALL())
- {
- MemoryContext oldcxt;
- TupleDesc tupdesc;
-
- funccxt = SRF_FIRSTCALL_INIT();
- oldcxt = MemoryContextSwitchTo(funccxt->multi_call_memory_ctx);
-
- multi = palloc(sizeof(mxact));
- /* no need to allow for old values here */
- multi->nmembers = GetMultiXactIdMembers(mxid, &multi->members, false,
- false);
- multi->iter = 0;
-
- if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
- elog(ERROR, "return type must be a row type");
- funccxt->tuple_desc = tupdesc;
- funccxt->attinmeta = TupleDescGetAttInMetadata(tupdesc);
- funccxt->user_fctx = multi;
-
- MemoryContextSwitchTo(oldcxt);
- }
-
- funccxt = SRF_PERCALL_SETUP();
- multi = (mxact *) funccxt->user_fctx;
-
- while (multi->iter < multi->nmembers)
- {
- HeapTuple tuple;
- char *values[2];
-
- values[0] = psprintf("%u", multi->members[multi->iter].xid);
- values[1] = mxstatus_to_string(multi->members[multi->iter].status);
-
- tuple = BuildTupleFromCStrings(funccxt->attinmeta, values);
-
- multi->iter++;
- pfree(values[0]);
- SRF_RETURN_NEXT(funccxt, HeapTupleGetDatum(tuple));
- }
-
- SRF_RETURN_DONE(funccxt);
-}
-
/*
* Entrypoint for sync.c to sync offsets files.
*/
misc.o \
multirangetypes.o \
multirangetypes_selfuncs.o \
+ multixactfuncs.o \
name.o \
network.o \
network_gist.o \
'misc.c',
'multirangetypes.c',
'multirangetypes_selfuncs.c',
+ 'multixactfuncs.c',
'name.c',
'network.c',
'network_gist.c',
--- /dev/null
+/*-------------------------------------------------------------------------
+ *
+ * multixactfuncs.c
+ * Functions for accessing multixact-related data.
+ *
+ * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ * src/backend/utils/adt/multixactfuncs.c
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "access/multixact.h"
+#include "funcapi.h"
+#include "utils/builtins.h"
+
+/*
+ * pg_get_multixact_members
+ *
+ * Returns information about the MultiXactMembers of the specified
+ * MultiXactId.
+ */
+Datum
+pg_get_multixact_members(PG_FUNCTION_ARGS)
+{
+ typedef struct
+ {
+ MultiXactMember *members;
+ int nmembers;
+ int iter;
+ } mxact;
+ MultiXactId mxid = PG_GETARG_TRANSACTIONID(0);
+ mxact *multi;
+ FuncCallContext *funccxt;
+
+ if (mxid < FirstMultiXactId)
+ ereport(ERROR,
+ (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
+ errmsg("invalid MultiXactId: %u", mxid)));
+
+ if (SRF_IS_FIRSTCALL())
+ {
+ MemoryContext oldcxt;
+ TupleDesc tupdesc;
+
+ funccxt = SRF_FIRSTCALL_INIT();
+ oldcxt = MemoryContextSwitchTo(funccxt->multi_call_memory_ctx);
+
+ multi = palloc(sizeof(mxact));
+ /* no need to allow for old values here */
+ multi->nmembers = GetMultiXactIdMembers(mxid, &multi->members, false,
+ false);
+ multi->iter = 0;
+
+ if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
+ elog(ERROR, "return type must be a row type");
+ funccxt->tuple_desc = tupdesc;
+ funccxt->attinmeta = TupleDescGetAttInMetadata(tupdesc);
+ funccxt->user_fctx = multi;
+
+ MemoryContextSwitchTo(oldcxt);
+ }
+
+ funccxt = SRF_PERCALL_SETUP();
+ multi = (mxact *) funccxt->user_fctx;
+
+ while (multi->iter < multi->nmembers)
+ {
+ HeapTuple tuple;
+ char *values[2];
+
+ values[0] = psprintf("%u", multi->members[multi->iter].xid);
+ values[1] = mxstatus_to_string(multi->members[multi->iter].status);
+
+ tuple = BuildTupleFromCStrings(funccxt->attinmeta, values);
+
+ multi->iter++;
+ pfree(values[0]);
+ SRF_RETURN_NEXT(funccxt, HeapTupleGetDatum(tuple));
+ }
+
+ SRF_RETURN_DONE(funccxt);
+}
extern const char *multixact_identify(uint8 info);
extern char *mxid_to_string(MultiXactId multi, int nmembers,
MultiXactMember *members);
+extern char *mxstatus_to_string(MultiXactStatus status);
#endif /* MULTIXACT_H */