/
githubmirror
/
postgres
Обзор
Документация
Войти
/
githubmirror
/
postgres
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
master
src/backend/utils/adt/multixactfuncs.c
140 строк
3 KB
Michael Paquier
Avoid useless calls in pg_get_multixact_stats()
01 июл 2026, 06:17
01 июл 2026, 06:17
b542d55
Код
Авторство
О чём код?
/*------------------------------------------------------------------------- * * multixactfuncs.c * Functions for accessing multixact-related data. * * Portions Copyright (c) 1996-2026, 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/htup_details.h" #include "access/multixact.h" #include "access/multixact_internal.h" #include "catalog/pg_authid_d.h" #include "funcapi.h" #include "miscadmin.h" #include "utils/acl.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_object(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); } /* * pg_get_multixact_stats * * Returns statistics about current multixact usage. */ Datum pg_get_multixact_stats(PG_FUNCTION_ARGS) { TupleDesc tupdesc; Datum values[4]; bool nulls[4]; if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE) ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("return type must be a row type"))); if (!has_privs_of_role(GetUserId(), ROLE_PG_READ_ALL_STATS)) { /* * Only superusers and roles with privileges of pg_read_all_stats can * see details. */ memset(nulls, true, sizeof(bool) * tupdesc->natts); } else { uint64 members; MultiXactId oldestMultiXactId; uint32 multixacts; MultiXactOffset oldestOffset; MultiXactOffset nextOffset; uint64 membersBytes; GetMultiXactInfo(&multixacts, &nextOffset, &oldestMultiXactId, &oldestOffset); members = nextOffset - oldestOffset; membersBytes = MultiXactOffsetStorageSize(nextOffset, oldestOffset); values[0] = UInt32GetDatum(multixacts); values[1] = Int64GetDatum(members); values[2] = Int64GetDatum(membersBytes); values[3] = UInt32GetDatum(oldestMultiXactId); memset(nulls, false, sizeof(nulls)); } return HeapTupleGetDatum(heap_form_tuple(tupdesc, values, nulls)); }