#include "postgres.h"
-#include "fmgr.h"
-#include "funcapi.h"
#include "access/heapam.h"
-#include "access/itup.h"
#include "access/nbtree.h"
-#include "access/transam.h"
#include "catalog/namespace.h"
-#include "catalog/pg_type.h"
+#include "funcapi.h"
+#include "miscadmin.h"
#include "utils/builtins.h"
-#include "utils/inval.h"
-PG_FUNCTION_INFO_V1(pgstatindex);
-PG_FUNCTION_INFO_V1(pg_relpages);
extern Datum pgstatindex(PG_FUNCTION_ARGS);
extern Datum pg_relpages(PG_FUNCTION_ARGS);
-#define PGSTATINDEX_TYPE "public.pgstatindex_type"
-#define PGSTATINDEX_NCOLUMNS 10
+PG_FUNCTION_INFO_V1(pgstatindex);
+PG_FUNCTION_INFO_V1(pg_relpages);
-#define IS_INDEX(r) ((r)->rd_rel->relkind == 'i')
+#define IS_INDEX(r) ((r)->rd_rel->relkind == RELKIND_INDEX)
#define IS_BTREE(r) ((r)->rd_rel->relam == BTREE_AM_OID)
#define CHECK_PAGE_OFFSET_RANGE(pg, offnum) { \
uint32 blkno;
BTIndexStat indexStat;
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ (errmsg("must be superuser to use pgstattuple functions"))));
+
relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
rel = relation_openrv(relrv, AccessShareLock);
if (!IS_INDEX(rel) || !IS_BTREE(rel))
- elog(ERROR, "pgstatindex() can only be used on b-tree index");
+ elog(ERROR, "relation \"%s\" is not a btree index",
+ RelationGetRelationName(rel));
- /*-------------------
- * Read a metapage
- *-------------------
+ /*
+ * Read metapage
*/
{
Buffer buffer = ReadBuffer(rel, 0);
{
TupleDesc tupleDesc;
int j;
- char *values[PGSTATINDEX_NCOLUMNS];
-
+ char *values[10];
HeapTuple tuple;
- tupleDesc = RelationNameGetTupleDesc(PGSTATINDEX_TYPE);
+ /* 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");
j = 0;
values[j] = palloc(32);
tuple = BuildTupleFromCStrings(TupleDescGetAttInMetadata(tupleDesc),
values);
- result = TupleGetDatum(TupleDescGetSlot(tupleDesc), tuple);
+ result = HeapTupleGetDatum(tuple);
}
PG_RETURN_DATUM(result);
/* --------------------------------------------------------
* pg_relpages()
*
- * Get a number of pages of the table/index.
+ * Get the number of pages of the table/index.
*
* Usage: SELECT pg_relpages('t1');
* SELECT pg_relpages('t1_pkey');
pg_relpages(PG_FUNCTION_ARGS)
{
text *relname = PG_GETARG_TEXT_P(0);
-
Relation rel;
RangeVar *relrv;
int4 relpages;
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ (errmsg("must be superuser to use pgstattuple functions"))));
+
relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
rel = relation_openrv(relrv, AccessShareLock);
/*
- * $PostgreSQL: pgsql/contrib/pgstattuple/pgstattuple.c,v 1.27 2007/05/03 16:45:58 tgl Exp $
+ * $PostgreSQL: pgsql/contrib/pgstattuple/pgstattuple.c,v 1.28 2007/08/26 23:59:50 tgl Exp $
*
* Copyright (c) 2001,2002 Tatsuo Ishii
*
#include "postgres.h"
-#include "fmgr.h"
-#include "funcapi.h"
#include "access/gist_private.h"
#include "access/hash.h"
#include "access/heapam.h"
#include "access/nbtree.h"
-#include "access/transam.h"
#include "catalog/namespace.h"
+#include "funcapi.h"
+#include "miscadmin.h"
#include "utils/builtins.h"
if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
elog(ERROR, "return type must be a row type");
- /* make sure we have a persistent copy of the tupdesc */
- tupdesc = CreateTupleDescCopy(tupdesc);
-
/*
* Generate attribute metadata needed later to produce tuples from raw C
* strings
RangeVar *relrv;
Relation rel;
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ (errmsg("must be superuser to use pgstattuple functions"))));
+
/* open relation */
relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
rel = relation_openrv(relrv, AccessShareLock);
Oid relid = PG_GETARG_OID(0);
Relation rel;
+ if (!superuser())
+ ereport(ERROR,
+ (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ (errmsg("must be superuser to use pgstattuple functions"))));
+
/* open relation */
rel = relation_open(relid, AccessShareLock);
-- Adjust this setting to control where the objects get created.
SET search_path = public;
-CREATE TYPE pgstattuple_type AS (
- table_len BIGINT, -- physical table length in bytes
- tuple_count BIGINT, -- number of live tuples
- tuple_len BIGINT, -- total tuples length in bytes
- tuple_percent FLOAT, -- live tuples in %
- dead_tuple_count BIGINT, -- number of dead tuples
- dead_tuple_len BIGINT, -- total dead tuples length in bytes
- dead_tuple_percent FLOAT, -- dead tuples in %
- free_space BIGINT, -- free space in bytes
- free_percent FLOAT -- free space in %
-);
-
-CREATE OR REPLACE FUNCTION pgstattuple(text)
-RETURNS pgstattuple_type
+CREATE OR REPLACE FUNCTION pgstattuple(IN relname text,
+ 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 FLOAT, -- 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 FLOAT, -- dead tuples in %
+ OUT free_space BIGINT, -- free space in bytes
+ OUT free_percent FLOAT) -- free space in %
AS 'MODULE_PATHNAME', 'pgstattuple'
LANGUAGE C STRICT;
-CREATE OR REPLACE FUNCTION pgstattuple(oid)
-RETURNS pgstattuple_type
+CREATE OR REPLACE 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 FLOAT, -- 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 FLOAT, -- dead tuples in %
+ OUT free_space BIGINT, -- free space in bytes
+ OUT free_percent FLOAT) -- free space in %
AS 'MODULE_PATHNAME', 'pgstattuplebyid'
LANGUAGE C STRICT;
--
-- pgstatindex
--
-CREATE TYPE pgstatindex_type AS (
- version int4,
- tree_level int4,
- index_size int4,
- root_block_no int4,
- internal_pages int4,
- leaf_pages int4,
- empty_pages int4,
- deleted_pages int4,
- avg_leaf_density float8,
- leaf_fragmentation float8
-);
-
-CREATE OR REPLACE FUNCTION pgstatindex(text)
-RETURNS pgstatindex_type
+CREATE OR REPLACE FUNCTION pgstatindex(IN relname text,
+ OUT version int4,
+ OUT tree_level int4,
+ OUT index_size int4,
+ OUT root_block_no int4,
+ OUT internal_pages int4,
+ OUT leaf_pages int4,
+ OUT empty_pages int4,
+ OUT deleted_pages int4,
+ OUT avg_leaf_density float8,
+ OUT leaf_fragmentation float8)
AS 'MODULE_PATHNAME', 'pgstatindex'
-LANGUAGE 'C' STRICT;
+LANGUAGE C STRICT;
--
-- pg_relpages()
CREATE OR REPLACE FUNCTION pg_relpages(text)
RETURNS int
AS 'MODULE_PATHNAME', 'pg_relpages'
-LANGUAGE 'C' STRICT;
+LANGUAGE C STRICT;
-- Adjust this setting to control where the objects get created.
SET search_path = public;
-DROP FUNCTION pgstattuple(oid);
DROP FUNCTION pgstattuple(text);
-DROP TYPE pgstattuple_type;
-
+DROP FUNCTION pgstattuple(oid);
DROP FUNCTION pgstatindex(text);
-DROP TYPE pgstatindex_type;
-
DROP FUNCTION pg_relpages(text);