1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-28 23:42:10 +03:00

Add pgstatginindex() function to get the size of the GIN pending list.

Fujii Masao, reviewed by Kyotaro Horiguchi.
This commit is contained in:
Heikki Linnakangas
2012-12-05 09:58:03 +02:00
parent cdf498c5d7
commit 357cbaaeae
8 changed files with 187 additions and 5 deletions

View File

@ -27,7 +27,9 @@
#include "postgres.h"
#include "access/gin_private.h"
#include "access/heapam.h"
#include "access/htup_details.h"
#include "access/nbtree.h"
#include "catalog/namespace.h"
#include "funcapi.h"
@ -39,12 +41,15 @@
extern Datum pgstatindex(PG_FUNCTION_ARGS);
extern Datum pg_relpages(PG_FUNCTION_ARGS);
extern Datum pgstatginindex(PG_FUNCTION_ARGS);
PG_FUNCTION_INFO_V1(pgstatindex);
PG_FUNCTION_INFO_V1(pg_relpages);
PG_FUNCTION_INFO_V1(pgstatginindex);
#define IS_INDEX(r) ((r)->rd_rel->relkind == RELKIND_INDEX)
#define IS_BTREE(r) ((r)->rd_rel->relam == BTREE_AM_OID)
#define IS_GIN(r) ((r)->rd_rel->relam == GIN_AM_OID)
#define CHECK_PAGE_OFFSET_RANGE(pg, offnum) { \
if ( !(FirstOffsetNumber <= (offnum) && \
@ -79,6 +84,19 @@ typedef struct BTIndexStat
uint64 fragments;
} BTIndexStat;
/* ------------------------------------------------
* A structure for a whole GIN index statistics
* used by pgstatginindex().
* ------------------------------------------------
*/
typedef struct GinIndexStat
{
int32 version;
BlockNumber pending_pages;
int64 pending_tuples;
} GinIndexStat;
/* ------------------------------------------------------
* pgstatindex()
*
@ -292,3 +310,79 @@ pg_relpages(PG_FUNCTION_ARGS)
PG_RETURN_INT64(relpages);
}
/* ------------------------------------------------------
* pgstatginindex()
*
* Usage: SELECT * FROM pgstatginindex('ginindex');
* ------------------------------------------------------
*/
Datum
pgstatginindex(PG_FUNCTION_ARGS)
{
Oid relid = PG_GETARG_OID(0);
Relation rel;
Buffer buffer;
Page page;
GinMetaPageData *metadata;
GinIndexStat stats;
HeapTuple tuple;
TupleDesc tupleDesc;
Datum values[3];
bool nulls[3] = {false, false, false};
Datum result;
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
(errmsg("must be superuser to use pgstattuple functions"))));
rel = relation_open(relid, AccessShareLock);
if (!IS_INDEX(rel) || !IS_GIN(rel))
elog(ERROR, "relation \"%s\" is not a GIN index",
RelationGetRelationName(rel));
/*
* Reject attempts to read non-local temporary relations; we would be
* likely to get wrong data since we have no visibility into the owning
* session's local buffers.
*/
if (RELATION_IS_OTHER_TEMP(rel))
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot access temporary indexes of other sessions")));
/*
* Read metapage
*/
buffer = ReadBuffer(rel, GIN_METAPAGE_BLKNO);
LockBuffer(buffer, GIN_SHARE);
page = BufferGetPage(buffer);
metadata = GinPageGetMeta(page);
stats.version = metadata->ginVersion;
stats.pending_pages = metadata->nPendingPages;
stats.pending_tuples = metadata->nPendingHeapTuples;
UnlockReleaseBuffer(buffer);
relation_close(rel, AccessShareLock);
/*
* Build a tuple descriptor for our result type
*/
if (get_call_result_type(fcinfo, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
elog(ERROR, "return type must be a row type");
values[0] = Int32GetDatum(stats.version);
values[1] = UInt32GetDatum(stats.pending_pages);
values[2] = Int64GetDatum(stats.pending_tuples);
/*
* Build and return the tuple
*/
tuple = heap_form_tuple(tupleDesc, values, nulls);
result = HeapTupleGetDatum(tuple);
PG_RETURN_DATUM(result);
}