summaryrefslogtreecommitdiff
path: root/contrib/pgstattuple
diff options
context:
space:
mode:
authorPavan Deolasee2015-05-05 09:19:18 +0000
committerPavan Deolasee2015-05-05 09:19:18 +0000
commit73fa25c67cbfa24c03e28c96bf356f2592671730 (patch)
tree10ded7e26abd78d93658cb72fc5cb9d4672eff2a /contrib/pgstattuple
parentda4d108859bcd7a308ca75aba54281e32968822c (diff)
parent4a9ab6d8619817f9e3989c99b65140e19041dab7 (diff)
Merge branch 'XL_MASTER_MERGE_9_4' into XL_NEW_MASTER
Conflicts: src/test/regress/expected/aggregates.out src/test/regress/expected/create_index.out src/test/regress/expected/inherit.out src/test/regress/expected/join.out src/test/regress/expected/window.out src/test/regress/expected/with.out
Diffstat (limited to 'contrib/pgstattuple')
-rw-r--r--contrib/pgstattuple/Makefile2
-rw-r--r--contrib/pgstattuple/expected/pgstattuple.out94
-rw-r--r--contrib/pgstattuple/pgstatindex.c214
-rw-r--r--contrib/pgstattuple/pgstattuple--1.0--1.1.sql11
-rw-r--r--contrib/pgstattuple/pgstattuple--1.1--1.2.sql39
-rw-r--r--contrib/pgstattuple/pgstattuple--1.2.sql (renamed from contrib/pgstattuple/pgstattuple--1.0.sql)42
-rw-r--r--contrib/pgstattuple/pgstattuple.c11
-rw-r--r--contrib/pgstattuple/pgstattuple.control2
-rw-r--r--contrib/pgstattuple/sql/pgstattuple.sql20
9 files changed, 380 insertions, 55 deletions
diff --git a/contrib/pgstattuple/Makefile b/contrib/pgstattuple/Makefile
index 6ac277598c..d991c3a803 100644
--- a/contrib/pgstattuple/Makefile
+++ b/contrib/pgstattuple/Makefile
@@ -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.2.sql pgstattuple--1.1--1.2.sql pgstattuple--1.0--1.1.sql pgstattuple--unpackaged--1.0.sql
REGRESS = pgstattuple
diff --git a/contrib/pgstattuple/expected/pgstattuple.out b/contrib/pgstattuple/expected/pgstattuple.out
index 7f28177890..d769f6d494 100644
--- a/contrib/pgstattuple/expected/pgstattuple.out
+++ b/contrib/pgstattuple/expected/pgstattuple.out
@@ -4,26 +4,79 @@ CREATE EXTENSION pgstattuple;
-- the pgstattuple functions, but the results for empty tables and
-- indexes should be that.
--
-create table test (a int primary key);
-NOTICE: CREATE TABLE / PRIMARY KEY will create implicit index "test_pkey" for table "test"
+create table test (a int primary key, b int[]);
+select * from pgstattuple('test');
+ table_len | tuple_count | tuple_len | tuple_percent | dead_tuple_count | dead_tuple_len | dead_tuple_percent | free_space | free_percent
+-----------+-------------+-----------+---------------+------------------+----------------+--------------------+------------+--------------
+ 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
+(1 row)
+
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
-----------+-------------+-----------+---------------+------------------+----------------+--------------------+------------+--------------
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
(1 row)
+select * from pgstattuple('test'::name);
+ table_len | tuple_count | tuple_len | tuple_percent | dead_tuple_count | dead_tuple_len | dead_tuple_percent | free_space | free_percent
+-----------+-------------+-----------+---------------+------------------+----------------+--------------------+------------+--------------
+ 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
+(1 row)
+
select * from pgstattuple('test'::regclass);
table_len | tuple_count | tuple_len | tuple_percent | dead_tuple_count | dead_tuple_len | dead_tuple_percent | free_space | free_percent
-----------+-------------+-----------+---------------+------------------+----------------+--------------------+------------+--------------
0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0
(1 row)
+select pgstattuple(oid) from pg_class where relname = 'test';
+ pgstattuple
+---------------------
+ (0,0,0,0,0,0,0,0,0)
+(1 row)
+
+select pgstattuple(relname) from pg_class where relname = 'test';
+ pgstattuple
+---------------------
+ (0,0,0,0,0,0,0,0,0)
+(1 row)
+
select * from pgstatindex('test_pkey');
version | tree_level | index_size | root_block_no | internal_pages | leaf_pages | empty_pages | deleted_pages | avg_leaf_density | leaf_fragmentation
---------+------------+------------+---------------+----------------+------------+-------------+---------------+------------------+--------------------
2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | NaN | NaN
(1 row)
+select * from pgstatindex('test_pkey'::text);
+ version | tree_level | index_size | root_block_no | internal_pages | leaf_pages | empty_pages | deleted_pages | avg_leaf_density | leaf_fragmentation
+---------+------------+------------+---------------+----------------+------------+-------------+---------------+------------------+--------------------
+ 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | NaN | NaN
+(1 row)
+
+select * from pgstatindex('test_pkey'::name);
+ version | tree_level | index_size | root_block_no | internal_pages | leaf_pages | empty_pages | deleted_pages | avg_leaf_density | leaf_fragmentation
+---------+------------+------------+---------------+----------------+------------+-------------+---------------+------------------+--------------------
+ 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | NaN | NaN
+(1 row)
+
+select * from pgstatindex('test_pkey'::regclass);
+ version | tree_level | index_size | root_block_no | internal_pages | leaf_pages | empty_pages | deleted_pages | avg_leaf_density | leaf_fragmentation
+---------+------------+------------+---------------+----------------+------------+-------------+---------------+------------------+--------------------
+ 2 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | NaN | NaN
+(1 row)
+
+select pgstatindex(oid) from pg_class where relname = 'test_pkey';
+ pgstatindex
+---------------------------
+ (2,0,0,0,0,0,0,0,NaN,NaN)
+(1 row)
+
+select pgstatindex(relname) from pg_class where relname = 'test_pkey';
+ pgstatindex
+---------------------------
+ (2,0,0,0,0,0,0,0,NaN,NaN)
+(1 row)
+
select pg_relpages('test');
pg_relpages
-------------
@@ -36,3 +89,40 @@ select pg_relpages('test_pkey');
1
(1 row)
+select pg_relpages('test_pkey'::text);
+ pg_relpages
+-------------
+ 1
+(1 row)
+
+select pg_relpages('test_pkey'::name);
+ pg_relpages
+-------------
+ 1
+(1 row)
+
+select pg_relpages('test_pkey'::regclass);
+ pg_relpages
+-------------
+ 1
+(1 row)
+
+select pg_relpages(oid) from pg_class where relname = 'test_pkey';
+ pg_relpages
+-------------
+ 1
+(1 row)
+
+select pg_relpages(relname) from pg_class where relname = 'test_pkey';
+ pg_relpages
+-------------
+ 1
+(1 row)
+
+create index test_ginidx on test using gin (b);
+select * from pgstatginindex('test_ginidx');
+ version | pending_pages | pending_tuples
+---------+---------------+----------------
+ 2 | 0 | 0
+(1 row)
+
diff --git a/contrib/pgstattuple/pgstatindex.c b/contrib/pgstattuple/pgstatindex.c
index d4fc8a0fd6..a2ea5d709c 100644
--- a/contrib/pgstattuple/pgstatindex.c
+++ b/contrib/pgstattuple/pgstatindex.c
@@ -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"
@@ -37,14 +39,23 @@
#include "utils/rel.h"
-extern Datum pgstatindex(PG_FUNCTION_ARGS);
-extern Datum pg_relpages(PG_FUNCTION_ARGS);
-
+/*
+ * Because of backward-compatibility issue, we have decided to have
+ * two types of interfaces, with regclass-type input arg and text-type
+ * input arg, for each function.
+ *
+ * Those functions which have text-type input arg will be deprecated
+ * in the future release.
+ */
PG_FUNCTION_INFO_V1(pgstatindex);
+PG_FUNCTION_INFO_V1(pgstatindexbyid);
PG_FUNCTION_INFO_V1(pg_relpages);
+PG_FUNCTION_INFO_V1(pg_relpagesbyid);
+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 +90,21 @@ 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;
+
+static Datum pgstatindex_impl(Relation rel, FunctionCallInfo fcinfo);
+
/* ------------------------------------------------------
* pgstatindex()
*
@@ -91,11 +117,6 @@ pgstatindex(PG_FUNCTION_ARGS)
text *relname = PG_GETARG_TEXT_P(0);
Relation rel;
RangeVar *relrv;
- Datum result;
- BlockNumber nblocks;
- BlockNumber blkno;
- BTIndexStat indexStat;
- BufferAccessStrategy bstrategy = GetAccessStrategy(BAS_BULKREAD);
if (!superuser())
ereport(ERROR,
@@ -105,6 +126,34 @@ pgstatindex(PG_FUNCTION_ARGS)
relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
rel = relation_openrv(relrv, AccessShareLock);
+ PG_RETURN_DATUM(pgstatindex_impl(rel, fcinfo));
+}
+
+Datum
+pgstatindexbyid(PG_FUNCTION_ARGS)
+{
+ Oid relid = PG_GETARG_OID(0);
+ Relation rel;
+
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ (errmsg("must be superuser to use pgstattuple functions"))));
+
+ rel = relation_open(relid, AccessShareLock);
+
+ PG_RETURN_DATUM(pgstatindex_impl(rel, fcinfo));
+}
+
+static Datum
+pgstatindex_impl(Relation rel, FunctionCallInfo fcinfo)
+{
+ Datum result;
+ BlockNumber nblocks;
+ BlockNumber blkno;
+ BTIndexStat indexStat;
+ BufferAccessStrategy bstrategy = GetAccessStrategy(BAS_BULKREAD);
+
if (!IS_INDEX(rel) || !IS_BTREE(rel))
elog(ERROR, "relation \"%s\" is not a btree index",
RelationGetRelationName(rel));
@@ -216,39 +265,29 @@ pgstatindex(PG_FUNCTION_ARGS)
elog(ERROR, "return type must be a row type");
j = 0;
- values[j] = palloc(32);
- snprintf(values[j++], 32, "%d", indexStat.version);
- values[j] = palloc(32);
- snprintf(values[j++], 32, "%d", indexStat.level);
- values[j] = palloc(32);
- snprintf(values[j++], 32, INT64_FORMAT,
- (indexStat.root_pages +
- indexStat.leaf_pages +
- indexStat.internal_pages +
- indexStat.deleted_pages +
- indexStat.empty_pages) * BLCKSZ);
- values[j] = palloc(32);
- snprintf(values[j++], 32, "%u", indexStat.root_blkno);
- values[j] = palloc(32);
- snprintf(values[j++], 32, INT64_FORMAT, indexStat.internal_pages);
- values[j] = palloc(32);
- snprintf(values[j++], 32, INT64_FORMAT, indexStat.leaf_pages);
- values[j] = palloc(32);
- snprintf(values[j++], 32, INT64_FORMAT, indexStat.empty_pages);
- values[j] = palloc(32);
- snprintf(values[j++], 32, INT64_FORMAT, indexStat.deleted_pages);
- values[j] = palloc(32);
+ values[j++] = psprintf("%d", indexStat.version);
+ values[j++] = psprintf("%d", indexStat.level);
+ values[j++] = psprintf(INT64_FORMAT,
+ (indexStat.root_pages +
+ indexStat.leaf_pages +
+ indexStat.internal_pages +
+ indexStat.deleted_pages +
+ indexStat.empty_pages) * BLCKSZ);
+ values[j++] = psprintf("%u", indexStat.root_blkno);
+ values[j++] = psprintf(INT64_FORMAT, indexStat.internal_pages);
+ values[j++] = psprintf(INT64_FORMAT, indexStat.leaf_pages);
+ values[j++] = psprintf(INT64_FORMAT, indexStat.empty_pages);
+ values[j++] = psprintf(INT64_FORMAT, indexStat.deleted_pages);
if (indexStat.max_avail > 0)
- snprintf(values[j++], 32, "%.2f",
- 100.0 - (double) indexStat.free_space / (double) indexStat.max_avail * 100.0);
+ values[j++] = psprintf("%.2f",
+ 100.0 - (double) indexStat.free_space / (double) indexStat.max_avail * 100.0);
else
- snprintf(values[j++], 32, "NaN");
- values[j] = palloc(32);
+ values[j++] = pstrdup("NaN");
if (indexStat.leaf_pages > 0)
- snprintf(values[j++], 32, "%.2f",
- (double) indexStat.fragments / (double) indexStat.leaf_pages * 100.0);
+ values[j++] = psprintf("%.2f",
+ (double) indexStat.fragments / (double) indexStat.leaf_pages * 100.0);
else
- snprintf(values[j++], 32, "NaN");
+ values[j++] = pstrdup("NaN");
tuple = BuildTupleFromCStrings(TupleDescGetAttInMetadata(tupleDesc),
values);
@@ -256,7 +295,7 @@ pgstatindex(PG_FUNCTION_ARGS)
result = HeapTupleGetDatum(tuple);
}
- PG_RETURN_DATUM(result);
+ return result;
}
/* --------------------------------------------------------
@@ -292,3 +331,102 @@ pg_relpages(PG_FUNCTION_ARGS)
PG_RETURN_INT64(relpages);
}
+
+Datum
+pg_relpagesbyid(PG_FUNCTION_ARGS)
+{
+ Oid relid = PG_GETARG_OID(0);
+ int64 relpages;
+ Relation rel;
+
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ (errmsg("must be superuser to use pgstattuple functions"))));
+
+ rel = relation_open(relid, AccessShareLock);
+
+ /* note: this will work OK on non-local temp tables */
+
+ relpages = RelationGetNumberOfBlocks(rel);
+
+ relation_close(rel, AccessShareLock);
+
+ 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
index 0000000000..cf582a0b81
--- /dev/null
+++ b/contrib/pgstattuple/pgstattuple--1.0--1.1.sql
@@ -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;
diff --git a/contrib/pgstattuple/pgstattuple--1.1--1.2.sql b/contrib/pgstattuple/pgstattuple--1.1--1.2.sql
new file mode 100644
index 0000000000..2783a63fb1
--- /dev/null
+++ b/contrib/pgstattuple/pgstattuple--1.1--1.2.sql
@@ -0,0 +1,39 @@
+/* contrib/pgstattuple/pgstattuple--1.1--1.2.sql */
+
+-- complain if script is sourced in psql, rather than via ALTER EXTENSION
+\echo Use "ALTER EXTENSION pgstattuple UPDATE TO '1.2'" to load this file. \quit
+
+ALTER EXTENSION pgstattuple DROP FUNCTION pgstattuple(oid);
+DROP FUNCTION pgstattuple(oid);
+
+CREATE FUNCTION pgstattuple(IN reloid regclass,
+ OUT table_len BIGINT, -- physical table length in bytes
+ OUT tuple_count BIGINT, -- number of live tuples
+ OUT tuple_len BIGINT, -- total tuples length in bytes
+ OUT tuple_percent FLOAT8, -- live tuples in %
+ OUT dead_tuple_count BIGINT, -- number of dead tuples
+ OUT dead_tuple_len BIGINT, -- total dead tuples length in bytes
+ OUT dead_tuple_percent FLOAT8, -- dead tuples in %
+ OUT free_space BIGINT, -- free space in bytes
+ OUT free_percent FLOAT8) -- free space in %
+AS 'MODULE_PATHNAME', 'pgstattuplebyid'
+LANGUAGE C STRICT;
+
+CREATE FUNCTION pgstatindex(IN relname regclass,
+ OUT version INT,
+ OUT tree_level INT,
+ OUT index_size BIGINT,
+ OUT root_block_no BIGINT,
+ OUT internal_pages BIGINT,
+ OUT leaf_pages BIGINT,
+ OUT empty_pages BIGINT,
+ OUT deleted_pages BIGINT,
+ OUT avg_leaf_density FLOAT8,
+ OUT leaf_fragmentation FLOAT8)
+AS 'MODULE_PATHNAME', 'pgstatindexbyid'
+LANGUAGE C STRICT;
+
+CREATE FUNCTION pg_relpages(IN relname regclass)
+RETURNS BIGINT
+AS 'MODULE_PATHNAME', 'pg_relpagesbyid'
+LANGUAGE C STRICT;
diff --git a/contrib/pgstattuple/pgstattuple--1.0.sql b/contrib/pgstattuple/pgstattuple--1.2.sql
index f7e03083ad..e5fa2f58da 100644
--- a/contrib/pgstattuple/pgstattuple--1.0.sql
+++ b/contrib/pgstattuple/pgstattuple--1.2.sql
@@ -1,4 +1,4 @@
-/* contrib/pgstattuple/pgstattuple--1.0.sql */
+/* contrib/pgstattuple/pgstattuple--1.2.sql */
-- complain if script is sourced in psql, rather than via CREATE EXTENSION
\echo Use "CREATE EXTENSION pgstattuple" to load this file. \quit
@@ -16,7 +16,37 @@ CREATE FUNCTION pgstattuple(IN relname text,
AS 'MODULE_PATHNAME', 'pgstattuple'
LANGUAGE C STRICT;
-CREATE FUNCTION pgstattuple(IN reloid oid,
+CREATE FUNCTION pgstatindex(IN relname text,
+ OUT version INT,
+ OUT tree_level INT,
+ OUT index_size BIGINT,
+ OUT root_block_no BIGINT,
+ OUT internal_pages BIGINT,
+ OUT leaf_pages BIGINT,
+ OUT empty_pages BIGINT,
+ OUT deleted_pages BIGINT,
+ OUT avg_leaf_density FLOAT8,
+ OUT leaf_fragmentation FLOAT8)
+AS 'MODULE_PATHNAME', 'pgstatindex'
+LANGUAGE C STRICT;
+
+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;
+
+/* New stuff in 1.2 begins here */
+
+CREATE FUNCTION pgstattuple(IN reloid regclass,
OUT table_len BIGINT, -- physical table length in bytes
OUT tuple_count BIGINT, -- number of live tuples
OUT tuple_len BIGINT, -- total tuples length in bytes
@@ -29,7 +59,7 @@ CREATE FUNCTION pgstattuple(IN reloid oid,
AS 'MODULE_PATHNAME', 'pgstattuplebyid'
LANGUAGE C STRICT;
-CREATE FUNCTION pgstatindex(IN relname text,
+CREATE FUNCTION pgstatindex(IN relname regclass,
OUT version INT,
OUT tree_level INT,
OUT index_size BIGINT,
@@ -40,10 +70,10 @@ CREATE FUNCTION pgstatindex(IN relname text,
OUT deleted_pages BIGINT,
OUT avg_leaf_density FLOAT8,
OUT leaf_fragmentation FLOAT8)
-AS 'MODULE_PATHNAME', 'pgstatindex'
+AS 'MODULE_PATHNAME', 'pgstatindexbyid'
LANGUAGE C STRICT;
-CREATE FUNCTION pg_relpages(IN relname text)
+CREATE FUNCTION pg_relpages(IN relname regclass)
RETURNS BIGINT
-AS 'MODULE_PATHNAME', 'pg_relpages'
+AS 'MODULE_PATHNAME', 'pg_relpagesbyid'
LANGUAGE C STRICT;
diff --git a/contrib/pgstattuple/pgstattuple.c b/contrib/pgstattuple/pgstattuple.c
index 2b62b78506..edc603f6a1 100644
--- a/contrib/pgstattuple/pgstattuple.c
+++ b/contrib/pgstattuple/pgstattuple.c
@@ -42,9 +42,6 @@ PG_MODULE_MAGIC;
PG_FUNCTION_INFO_V1(pgstattuple);
PG_FUNCTION_INFO_V1(pgstattuplebyid);
-extern Datum pgstattuple(PG_FUNCTION_ARGS);
-extern Datum pgstattuplebyid(PG_FUNCTION_ARGS);
-
/*
* struct pgstattuple_type
*
@@ -216,8 +213,8 @@ pgstat_relation(Relation rel, FunctionCallInfo fcinfo)
switch (rel->rd_rel->relkind)
{
case RELKIND_RELATION:
+ case RELKIND_MATVIEW:
case RELKIND_TOASTVALUE:
- case RELKIND_UNCATALOGED:
case RELKIND_SEQUENCE:
return pgstat_heap(rel, fcinfo);
case RELKIND_INDEX:
@@ -278,9 +275,11 @@ pgstat_heap(Relation rel, FunctionCallInfo fcinfo)
Buffer buffer;
pgstattuple_type stat = {0};
BufferAccessStrategy bstrategy;
+ SnapshotData SnapshotDirty;
/* Disable syncscan because we assume we scan from block zero upwards */
scan = heap_beginscan_strat(rel, SnapshotAny, 0, NULL, true, false);
+ InitDirtySnapshot(SnapshotDirty);
nblocks = scan->rs_nblocks; /* # blocks to be scanned */
@@ -296,7 +295,7 @@ pgstat_heap(Relation rel, FunctionCallInfo fcinfo)
/* must hold a buffer lock to call HeapTupleSatisfiesVisibility */
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
- if (HeapTupleSatisfiesVisibility(tuple, SnapshotNow, scan->rs_cbuf))
+ if (HeapTupleSatisfiesVisibility(tuple, &SnapshotDirty, scan->rs_cbuf))
{
stat.tuple_len += tuple->t_len;
stat.tuple_count++;
@@ -311,7 +310,7 @@ pgstat_heap(Relation rel, FunctionCallInfo fcinfo)
/*
* To avoid physically reading the table twice, try to do the
- * free-space scan in parallel with the heap scan. However,
+ * free-space scan in parallel with the heap scan. However,
* heap_getnext may find no tuples on a given page, so we cannot
* simply examine the pages returned by the heap scan.
*/
diff --git a/contrib/pgstattuple/pgstattuple.control b/contrib/pgstattuple/pgstattuple.control
index 7b5129b2f2..a7cf47fd92 100644
--- a/contrib/pgstattuple/pgstattuple.control
+++ b/contrib/pgstattuple/pgstattuple.control
@@ -1,5 +1,5 @@
# pgstattuple extension
comment = 'show tuple-level statistics'
-default_version = '1.0'
+default_version = '1.2'
module_pathname = '$libdir/pgstattuple'
relocatable = true
diff --git a/contrib/pgstattuple/sql/pgstattuple.sql b/contrib/pgstattuple/sql/pgstattuple.sql
index 2fd1152e8c..0e0ad0e15d 100644
--- a/contrib/pgstattuple/sql/pgstattuple.sql
+++ b/contrib/pgstattuple/sql/pgstattuple.sql
@@ -6,12 +6,30 @@ 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');
select * from pgstattuple('test'::text);
+select * from pgstattuple('test'::name);
select * from pgstattuple('test'::regclass);
+select pgstattuple(oid) from pg_class where relname = 'test';
+select pgstattuple(relname) from pg_class where relname = 'test';
select * from pgstatindex('test_pkey');
+select * from pgstatindex('test_pkey'::text);
+select * from pgstatindex('test_pkey'::name);
+select * from pgstatindex('test_pkey'::regclass);
+select pgstatindex(oid) from pg_class where relname = 'test_pkey';
+select pgstatindex(relname) from pg_class where relname = 'test_pkey';
select pg_relpages('test');
select pg_relpages('test_pkey');
+select pg_relpages('test_pkey'::text);
+select pg_relpages('test_pkey'::name);
+select pg_relpages('test_pkey'::regclass);
+select pg_relpages(oid) from pg_class where relname = 'test_pkey';
+select pg_relpages(relname) from pg_class where relname = 'test_pkey';
+
+create index test_ginidx on test using gin (b);
+
+select * from pgstatginindex('test_ginidx');