OBJS = pgstattuple.o pgstatindex.o
EXTENSION = pgstattuple
-DATA = pgstattuple--1.1.sql pgstattuple--1.0--1.1.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
-- indexes should be that.
--
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
-------------
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
#include "utils/rel.h"
+/*
+ * 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.
+ */
extern Datum pgstatindex(PG_FUNCTION_ARGS);
+extern Datum pgstatindexbyid(PG_FUNCTION_ARGS);
extern Datum pg_relpages(PG_FUNCTION_ARGS);
+extern Datum pg_relpagesbyid(PG_FUNCTION_ARGS);
extern Datum pgstatginindex(PG_FUNCTION_ARGS);
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)
int64 pending_tuples;
} GinIndexStat;
+static Datum pgstatindex_impl(Relation rel, FunctionCallInfo fcinfo);
+
/* ------------------------------------------------------
* pgstatindex()
*
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,
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));
result = HeapTupleGetDatum(tuple);
}
- PG_RETURN_DATUM(result);
+ return result;
}
/* --------------------------------------------------------
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()
*
--- /dev/null
+/* 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;
-/* contrib/pgstattuple/pgstattuple--1.1.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
AS 'MODULE_PATHNAME', 'pgstattuple'
LANGUAGE C STRICT;
-CREATE FUNCTION pgstattuple(IN reloid oid,
- 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 text,
OUT version INT,
OUT tree_level INT,
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
+ 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;
# pgstattuple extension
comment = 'show tuple-level statistics'
-default_version = '1.1'
+default_version = '1.2'
module_pathname = '$libdir/pgstattuple'
relocatable = true
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);
</indexterm>
<term>
- <function>pgstattuple(text) returns record</>
+ <function>pgstattuple(regclass) returns record</>
</term>
<listitem>
<function>pgstattuple</function> returns a relation's physical length,
percentage of <quote>dead</> tuples, and other info. This may help users
to determine whether vacuum is necessary or not. The argument is the
- target relation's name (optionally schema-qualified).
+ target relation's name (optionally schema-qualified) or OID.
For example:
<programlisting>
test=> SELECT * FROM pgstattuple('pg_catalog.pg_proc');
<varlistentry>
<term>
- <function>pgstattuple(oid) returns record</>
+ <function>pgstattuple(text) returns record</>
</term>
<listitem>
<para>
- This is the same as <function>pgstattuple(text)</function>, except
- that the target relation is specified by OID.
+ This is the same as <function>pgstattuple(regclass)</function>, except
+ that the target relation is specified by TEXT. This function is kept
+ because of backward-compatibility so far, and will be deprecated in
+ the future release.
</para>
</listitem>
</varlistentry>
<indexterm>
<primary>pgstatindex</primary>
</indexterm>
- <function>pgstatindex(text) returns record</>
+ <function>pgstatindex(regclass) returns record</>
</term>
<listitem>
</listitem>
</varlistentry>
+ <varlistentry>
+ <term>
+ <function>pgstatindex(text) returns record</>
+ </term>
+
+ <listitem>
+ <para>
+ This is the same as <function>pgstatindex(regclass)</function>, except
+ that the target index is specified by TEXT. This function is kept
+ because of backward-compatibility so far, and will be deprecated in
+ the future release.
+ </para>
+ </listitem>
+ </varlistentry>
+
<varlistentry>
<term>
<indexterm>
<indexterm>
<primary>pg_relpages</primary>
</indexterm>
- <function>pg_relpages(text) returns bigint</>
+ <function>pg_relpages(regclass) returns bigint</>
</term>
<listitem>
</para>
</listitem>
</varlistentry>
+
+ <varlistentry>
+ <term>
+ <function>pg_relpages(text) returns bigint</>
+ </term>
+
+ <listitem>
+ <para>
+ This is the same as <function>pg_relpages(regclass)</function>, except
+ that the target relation is specified by TEXT. This function is kept
+ because of backward-compatibility so far, and will be deprecated in
+ the future release.
+ </para>
+ </listitem>
+ </varlistentry>
+
</variablelist>
</sect2>