diff options
author | Pavan Deolasee | 2015-05-05 09:19:18 +0000 |
---|---|---|
committer | Pavan Deolasee | 2015-05-05 09:19:18 +0000 |
commit | 73fa25c67cbfa24c03e28c96bf356f2592671730 (patch) | |
tree | 10ded7e26abd78d93658cb72fc5cb9d4672eff2a /contrib/pgstattuple | |
parent | da4d108859bcd7a308ca75aba54281e32968822c (diff) | |
parent | 4a9ab6d8619817f9e3989c99b65140e19041dab7 (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/Makefile | 2 | ||||
-rw-r--r-- | contrib/pgstattuple/expected/pgstattuple.out | 94 | ||||
-rw-r--r-- | contrib/pgstattuple/pgstatindex.c | 214 | ||||
-rw-r--r-- | contrib/pgstattuple/pgstattuple--1.0--1.1.sql | 11 | ||||
-rw-r--r-- | contrib/pgstattuple/pgstattuple--1.1--1.2.sql | 39 | ||||
-rw-r--r-- | contrib/pgstattuple/pgstattuple--1.2.sql (renamed from contrib/pgstattuple/pgstattuple--1.0.sql) | 42 | ||||
-rw-r--r-- | contrib/pgstattuple/pgstattuple.c | 11 | ||||
-rw-r--r-- | contrib/pgstattuple/pgstattuple.control | 2 | ||||
-rw-r--r-- | contrib/pgstattuple/sql/pgstattuple.sql | 20 |
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'); |