Skip to content

Commit 357cbaa

Browse files
committed
Add pgstatginindex() function to get the size of the GIN pending list.
Fujii Masao, reviewed by Kyotaro Horiguchi.
1 parent cdf498c commit 357cbaa

File tree

8 files changed

+187
-5
lines changed

8 files changed

+187
-5
lines changed

contrib/pgstattuple/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ MODULE_big = pgstattuple
44
OBJS = pgstattuple.o pgstatindex.o
55

66
EXTENSION = pgstattuple
7-
DATA = pgstattuple--1.0.sql pgstattuple--unpackaged--1.0.sql
7+
DATA = pgstattuple--1.1.sql pgstattuple--1.0--1.1.sql pgstattuple--unpackaged--1.0.sql
88

99
REGRESS = pgstattuple
1010

contrib/pgstattuple/expected/pgstattuple.out

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ CREATE EXTENSION pgstattuple;
44
-- the pgstattuple functions, but the results for empty tables and
55
-- indexes should be that.
66
--
7-
create table test (a int primary key);
7+
create table test (a int primary key, b int[]);
88
select * from pgstattuple('test'::text);
99
table_len | tuple_count | tuple_len | tuple_percent | dead_tuple_count | dead_tuple_len | dead_tuple_percent | free_space | free_percent
1010
-----------+-------------+-----------+---------------+------------------+----------------+--------------------+------------+--------------
@@ -35,3 +35,10 @@ select pg_relpages('test_pkey');
3535
1
3636
(1 row)
3737

38+
create index test_ginidx on test using gin (b);
39+
select * from pgstatginindex('test_ginidx');
40+
version | pending_pages | pending_tuples
41+
---------+---------------+----------------
42+
1 | 0 | 0
43+
(1 row)
44+

contrib/pgstattuple/pgstatindex.c

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,9 @@
2727

2828
#include "postgres.h"
2929

30+
#include "access/gin_private.h"
3031
#include "access/heapam.h"
32+
#include "access/htup_details.h"
3133
#include "access/nbtree.h"
3234
#include "catalog/namespace.h"
3335
#include "funcapi.h"
@@ -39,12 +41,15 @@
3941

4042
extern Datum pgstatindex(PG_FUNCTION_ARGS);
4143
extern Datum pg_relpages(PG_FUNCTION_ARGS);
44+
extern Datum pgstatginindex(PG_FUNCTION_ARGS);
4245

4346
PG_FUNCTION_INFO_V1(pgstatindex);
4447
PG_FUNCTION_INFO_V1(pg_relpages);
48+
PG_FUNCTION_INFO_V1(pgstatginindex);
4549

4650
#define IS_INDEX(r) ((r)->rd_rel->relkind == RELKIND_INDEX)
4751
#define IS_BTREE(r) ((r)->rd_rel->relam == BTREE_AM_OID)
52+
#define IS_GIN(r) ((r)->rd_rel->relam == GIN_AM_OID)
4853

4954
#define CHECK_PAGE_OFFSET_RANGE(pg, offnum) { \
5055
if ( !(FirstOffsetNumber <= (offnum) && \
@@ -79,6 +84,19 @@ typedef struct BTIndexStat
7984
uint64 fragments;
8085
} BTIndexStat;
8186

87+
/* ------------------------------------------------
88+
* A structure for a whole GIN index statistics
89+
* used by pgstatginindex().
90+
* ------------------------------------------------
91+
*/
92+
typedef struct GinIndexStat
93+
{
94+
int32 version;
95+
96+
BlockNumber pending_pages;
97+
int64 pending_tuples;
98+
} GinIndexStat;
99+
82100
/* ------------------------------------------------------
83101
* pgstatindex()
84102
*
@@ -292,3 +310,79 @@ pg_relpages(PG_FUNCTION_ARGS)
292310

293311
PG_RETURN_INT64(relpages);
294312
}
313+
314+
/* ------------------------------------------------------
315+
* pgstatginindex()
316+
*
317+
* Usage: SELECT * FROM pgstatginindex('ginindex');
318+
* ------------------------------------------------------
319+
*/
320+
Datum
321+
pgstatginindex(PG_FUNCTION_ARGS)
322+
{
323+
Oid relid = PG_GETARG_OID(0);
324+
Relation rel;
325+
Buffer buffer;
326+
Page page;
327+
GinMetaPageData *metadata;
328+
GinIndexStat stats;
329+
HeapTuple tuple;
330+
TupleDesc tupleDesc;
331+
Datum values[3];
332+
bool nulls[3] = {false, false, false};
333+
Datum result;
334+
335+
if (!superuser())
336+
ereport(ERROR,
337+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
338+
(errmsg("must be superuser to use pgstattuple functions"))));
339+
340+
rel = relation_open(relid, AccessShareLock);
341+
342+
if (!IS_INDEX(rel) || !IS_GIN(rel))
343+
elog(ERROR, "relation \"%s\" is not a GIN index",
344+
RelationGetRelationName(rel));
345+
346+
/*
347+
* Reject attempts to read non-local temporary relations; we would be
348+
* likely to get wrong data since we have no visibility into the owning
349+
* session's local buffers.
350+
*/
351+
if (RELATION_IS_OTHER_TEMP(rel))
352+
ereport(ERROR,
353+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
354+
errmsg("cannot access temporary indexes of other sessions")));
355+
356+
/*
357+
* Read metapage
358+
*/
359+
buffer = ReadBuffer(rel, GIN_METAPAGE_BLKNO);
360+
LockBuffer(buffer, GIN_SHARE);
361+
page = BufferGetPage(buffer);
362+
metadata = GinPageGetMeta(page);
363+
364+
stats.version = metadata->ginVersion;
365+
stats.pending_pages = metadata->nPendingPages;
366+
stats.pending_tuples = metadata->nPendingHeapTuples;
367+
368+
UnlockReleaseBuffer(buffer);
369+
relation_close(rel, AccessShareLock);
370+
371+
/*
372+
* Build a tuple descriptor for our result type
373+
*/
374+
if (get_call_result_type(fcinfo, NULL, &tupleDesc) != TYPEFUNC_COMPOSITE)
375+
elog(ERROR, "return type must be a row type");
376+
377+
values[0] = Int32GetDatum(stats.version);
378+
values[1] = UInt32GetDatum(stats.pending_pages);
379+
values[2] = Int64GetDatum(stats.pending_tuples);
380+
381+
/*
382+
* Build and return the tuple
383+
*/
384+
tuple = heap_form_tuple(tupleDesc, values, nulls);
385+
result = HeapTupleGetDatum(tuple);
386+
387+
PG_RETURN_DATUM(result);
388+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
/* contrib/pgstattuple/pgstattuple--1.0--1.1.sql */
2+
3+
-- complain if script is sourced in psql, rather than via ALTER EXTENSION
4+
\echo Use "ALTER EXTENSION pgstattuple UPDATE TO '1.1'" to load this file. \quit
5+
6+
CREATE FUNCTION pgstatginindex(IN relname regclass,
7+
OUT version INT4,
8+
OUT pending_pages INT4,
9+
OUT pending_tuples BIGINT)
10+
AS 'MODULE_PATHNAME', 'pgstatginindex'
11+
LANGUAGE C STRICT;

contrib/pgstattuple/pgstattuple--1.0.sql renamed to contrib/pgstattuple/pgstattuple--1.1.sql

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/* contrib/pgstattuple/pgstattuple--1.0.sql */
1+
/* contrib/pgstattuple/pgstattuple--1.1.sql */
22

33
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
44
\echo Use "CREATE EXTENSION pgstattuple" to load this file. \quit
@@ -47,3 +47,12 @@ CREATE FUNCTION pg_relpages(IN relname text)
4747
RETURNS BIGINT
4848
AS 'MODULE_PATHNAME', 'pg_relpages'
4949
LANGUAGE C STRICT;
50+
51+
/* New stuff in 1.1 begins here */
52+
53+
CREATE FUNCTION pgstatginindex(IN relname regclass,
54+
OUT version INT4,
55+
OUT pending_pages INT4,
56+
OUT pending_tuples BIGINT)
57+
AS 'MODULE_PATHNAME', 'pgstatginindex'
58+
LANGUAGE C STRICT;
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
# pgstattuple extension
22
comment = 'show tuple-level statistics'
3-
default_version = '1.0'
3+
default_version = '1.1'
44
module_pathname = '$libdir/pgstattuple'
55
relocatable = true

contrib/pgstattuple/sql/pgstattuple.sql

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ CREATE EXTENSION pgstattuple;
66
-- indexes should be that.
77
--
88

9-
create table test (a int primary key);
9+
create table test (a int primary key, b int[]);
1010

1111
select * from pgstattuple('test'::text);
1212
select * from pgstattuple('test'::regclass);
@@ -15,3 +15,7 @@ select * from pgstatindex('test_pkey');
1515

1616
select pg_relpages('test');
1717
select pg_relpages('test_pkey');
18+
19+
create index test_ginidx on test using gin (b);
20+
21+
select * from pgstatginindex('test_ginidx');

doc/src/sgml/pgstattuple.sgml

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -244,6 +244,63 @@ leaf_fragmentation | 0
244244
</listitem>
245245
</varlistentry>
246246

247+
<varlistentry>
248+
<term>
249+
<function>pgstatginindex(regclass) returns record</>
250+
</term>
251+
252+
<listitem>
253+
<para>
254+
<function>pgstatginindex</function> returns a record showing information
255+
about a GIN index. For example:
256+
<programlisting>
257+
test=> SELECT * FROM pgstatginindex('test_gin_index');
258+
-[ RECORD 1 ]--+--
259+
version | 1
260+
pending_pages | 0
261+
pending_tuples | 0
262+
</programlisting>
263+
</para>
264+
265+
<para>
266+
The output columns are:
267+
268+
<informaltable>
269+
<tgroup cols="3">
270+
<thead>
271+
<row>
272+
<entry>Column</entry>
273+
<entry>Type</entry>
274+
<entry>Description</entry>
275+
</row>
276+
</thead>
277+
278+
<tbody>
279+
<row>
280+
<entry><structfield>version</structfield></entry>
281+
<entry><type>integer</type></entry>
282+
<entry>GIN version number</entry>
283+
</row>
284+
285+
<row>
286+
<entry><structfield>pending_pages</structfield></entry>
287+
<entry><type>integer</type></entry>
288+
<entry>Number of pages in the pending list</entry>
289+
</row>
290+
291+
<row>
292+
<entry><structfield>pending_tuples</structfield></entry>
293+
<entry><type>bigint</type></entry>
294+
<entry>Number of tuples in the pending list</entry>
295+
</row>
296+
297+
</tbody>
298+
</tgroup>
299+
</informaltable>
300+
</para>
301+
</listitem>
302+
</varlistentry>
303+
247304
<varlistentry>
248305
<term>
249306
<function>pg_relpages(text) returns bigint</>

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy