]> granicus.if.org Git - postgresql/commitdiff
Add pgstatginindex() function to get the size of the GIN pending list.
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>
Wed, 5 Dec 2012 07:58:03 +0000 (09:58 +0200)
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>
Wed, 5 Dec 2012 07:58:03 +0000 (09:58 +0200)
Fujii Masao, reviewed by Kyotaro Horiguchi.

contrib/pgstattuple/Makefile
contrib/pgstattuple/expected/pgstattuple.out
contrib/pgstattuple/pgstatindex.c
contrib/pgstattuple/pgstattuple--1.0--1.1.sql [new file with mode: 0644]
contrib/pgstattuple/pgstattuple--1.1.sql [moved from contrib/pgstattuple/pgstattuple--1.0.sql with 87% similarity]
contrib/pgstattuple/pgstattuple.control
contrib/pgstattuple/sql/pgstattuple.sql
doc/src/sgml/pgstattuple.sgml

index 6ac277598c85c0a19345bb3e0f80d32ff2e68207..fc893d8c8556ef1b18c293a4c9b6c8f9473dc17b 100644 (file)
@@ -4,7 +4,7 @@ MODULE_big      = pgstattuple
 OBJS           = pgstattuple.o pgstatindex.o
 
 EXTENSION = pgstattuple
-DATA = pgstattuple--1.0.sql pgstattuple--unpackaged--1.0.sql
+DATA = pgstattuple--1.1.sql pgstattuple--1.0--1.1.sql pgstattuple--unpackaged--1.0.sql
 
 REGRESS = pgstattuple
 
index 2d8dd5e19c9aa72f33ef05ac2c75780795760fca..ab28f50cb086a4ff297b9f47813d87efbf28d432 100644 (file)
@@ -4,7 +4,7 @@ CREATE EXTENSION pgstattuple;
 -- the pgstattuple functions, but the results for empty tables and
 -- indexes should be that.
 --
-create table test (a int primary key);
+create table test (a int primary key, b int[]);
 select * from pgstattuple('test'::text);
  table_len | tuple_count | tuple_len | tuple_percent | dead_tuple_count | dead_tuple_len | dead_tuple_percent | free_space | free_percent 
 -----------+-------------+-----------+---------------+------------------+----------------+--------------------+------------+--------------
@@ -35,3 +35,10 @@ select pg_relpages('test_pkey');
            1
 (1 row)
 
+create index test_ginidx on test using gin (b);
+select * from pgstatginindex('test_ginidx');
+ version | pending_pages | pending_tuples 
+---------+---------------+----------------
+       1 |             0 |              0
+(1 row)
+
index d4fc8a0fd609f359c1cfba928f140519c99a17da..984ff7c45a063580774eaad6276b31790c9334ed 100644 (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"
 
 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);
+}
diff --git a/contrib/pgstattuple/pgstattuple--1.0--1.1.sql b/contrib/pgstattuple/pgstattuple--1.0--1.1.sql
new file mode 100644 (file)
index 0000000..cf582a0
--- /dev/null
@@ -0,0 +1,11 @@
+/* contrib/pgstattuple/pgstattuple--1.0--1.1.sql */
+
+-- complain if script is sourced in psql, rather than via ALTER EXTENSION
+\echo Use "ALTER EXTENSION pgstattuple UPDATE TO '1.1'" to load this file. \quit
+
+CREATE FUNCTION pgstatginindex(IN relname regclass,
+    OUT version INT4,
+    OUT pending_pages INT4,
+    OUT pending_tuples BIGINT)
+AS 'MODULE_PATHNAME', 'pgstatginindex'
+LANGUAGE C STRICT;
similarity index 87%
rename from contrib/pgstattuple/pgstattuple--1.0.sql
rename to contrib/pgstattuple/pgstattuple--1.1.sql
index f7e03083ad7e90844d0270724dce625a12052cbc..b21fbf83e466484069f2715e8576a6d2e1206b38 100644 (file)
@@ -1,4 +1,4 @@
-/* contrib/pgstattuple/pgstattuple--1.0.sql */
+/* contrib/pgstattuple/pgstattuple--1.1.sql */
 
 -- complain if script is sourced in psql, rather than via CREATE EXTENSION
 \echo Use "CREATE EXTENSION pgstattuple" to load this file. \quit
@@ -47,3 +47,12 @@ CREATE FUNCTION pg_relpages(IN relname text)
 RETURNS BIGINT
 AS 'MODULE_PATHNAME', 'pg_relpages'
 LANGUAGE C STRICT;
+
+/* New stuff in 1.1 begins here */
+
+CREATE FUNCTION pgstatginindex(IN relname regclass,
+    OUT version INT4,
+    OUT pending_pages INT4,
+    OUT pending_tuples BIGINT)
+AS 'MODULE_PATHNAME', 'pgstatginindex'
+LANGUAGE C STRICT;
index 7b5129b2f215665f04742e9d36e9bf243474fef0..fcfd36f1b1ab39eecd86234643b2fca88a25ae09 100644 (file)
@@ -1,5 +1,5 @@
 # pgstattuple extension
 comment = 'show tuple-level statistics'
-default_version = '1.0'
+default_version = '1.1'
 module_pathname = '$libdir/pgstattuple'
 relocatable = true
index 2fd1152e8cee0c99525c753d5d3cf6f386b7afb9..8cb350d6ee1ae8a5efb5525dd231a4bd82416438 100644 (file)
@@ -6,7 +6,7 @@ CREATE EXTENSION pgstattuple;
 -- indexes should be that.
 --
 
-create table test (a int primary key);
+create table test (a int primary key, b int[]);
 
 select * from pgstattuple('test'::text);
 select * from pgstattuple('test'::regclass);
@@ -15,3 +15,7 @@ select * from pgstatindex('test_pkey');
 
 select pg_relpages('test');
 select pg_relpages('test_pkey');
+
+create index test_ginidx on test using gin (b);
+
+select * from pgstatginindex('test_ginidx');
index a55b35cb3f1b0e49bbead372a537b02fe36455b1..9f98448d7bc242c3fa09d2d026e3e09ae6e403c0 100644 (file)
@@ -244,6 +244,63 @@ leaf_fragmentation | 0
     </listitem>
    </varlistentry>
 
+   <varlistentry>
+    <term>
+     <function>pgstatginindex(regclass) returns record</>
+    </term>
+
+    <listitem>
+     <para>
+      <function>pgstatginindex</function> returns a record showing information
+      about a GIN index.  For example:
+<programlisting>
+test=> SELECT * FROM pgstatginindex('test_gin_index');
+-[ RECORD 1 ]--+--
+version        | 1
+pending_pages  | 0
+pending_tuples | 0
+</programlisting>
+     </para>
+
+    <para>
+     The output columns are:
+
+    <informaltable>
+     <tgroup cols="3">
+      <thead>
+       <row>
+        <entry>Column</entry>
+        <entry>Type</entry>
+        <entry>Description</entry>
+       </row>
+      </thead>
+
+      <tbody>
+       <row>
+        <entry><structfield>version</structfield></entry>
+        <entry><type>integer</type></entry>
+        <entry>GIN version number</entry>
+       </row>
+
+       <row>
+        <entry><structfield>pending_pages</structfield></entry>
+        <entry><type>integer</type></entry>
+        <entry>Number of pages in the pending list</entry>
+       </row>
+
+       <row>
+        <entry><structfield>pending_tuples</structfield></entry>
+        <entry><type>bigint</type></entry>
+        <entry>Number of tuples in the pending list</entry>
+       </row>
+
+      </tbody>
+     </tgroup>
+    </informaltable>
+    </para>
+    </listitem>
+   </varlistentry>
+
    <varlistentry>
     <term>
      <function>pg_relpages(text) returns bigint</>