Restrict pgstattuple functions to superusers. (This might be too strict,
authorTom Lane <tgl@sss.pgh.pa.us>
Sun, 26 Aug 2007 23:59:50 +0000 (23:59 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sun, 26 Aug 2007 23:59:50 +0000 (23:59 +0000)
but no permissions check at all is certainly no good.)  Clean up usage
of some deprecated APIs.

contrib/pgstattuple/pgstatindex.c
contrib/pgstattuple/pgstattuple.c
contrib/pgstattuple/pgstattuple.sql.in
contrib/pgstattuple/uninstall_pgstattuple.sql

index 0c2c9a14484f55cd294d42ce298315b6fb7af3b1..3018b6aedd1c54e7e42b9c7c576245243c3163ac 100644 (file)
 
 #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) { \
@@ -97,15 +91,20 @@ pgstatindex(PG_FUNCTION_ARGS)
    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);
@@ -194,11 +193,12 @@ pgstatindex(PG_FUNCTION_ARGS)
    {
        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);
@@ -229,7 +229,7 @@ pgstatindex(PG_FUNCTION_ARGS)
        tuple = BuildTupleFromCStrings(TupleDescGetAttInMetadata(tupleDesc),
                                       values);
 
-       result = TupleGetDatum(TupleDescGetSlot(tupleDesc), tuple);
+       result = HeapTupleGetDatum(tuple);
    }
 
    PG_RETURN_DATUM(result);
@@ -238,7 +238,7 @@ pgstatindex(PG_FUNCTION_ARGS)
 /* --------------------------------------------------------
  * 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');
@@ -248,11 +248,15 @@ Datum
 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);
 
index 64e7f982fba55caa3953006c25ec08c33640a681..9072a37aa91cf0de91db084bc4366eed811af920 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * $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"
 
 
@@ -99,9 +98,6 @@ build_pgstattuple_type(pgstattuple_type * stat, FunctionCallInfo fcinfo)
    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
@@ -163,6 +159,11 @@ pgstattuple(PG_FUNCTION_ARGS)
    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);
@@ -176,6 +177,11 @@ pgstattuplebyid(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"))));
+
    /* open relation */
    rel = relation_open(relid, AccessShareLock);
 
index 77a5e2d4b2de6069b0b0c866dff98a4ae89e2b1e..ec8f8b1bbe0704e9bd075170fd3f4fb6afa62d1b 100644 (file)
@@ -1,48 +1,48 @@
 -- 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()
@@ -50,4 +50,4 @@ LANGUAGE 'C' STRICT;
 CREATE OR REPLACE FUNCTION pg_relpages(text)
 RETURNS int
 AS 'MODULE_PATHNAME', 'pg_relpages'
-LANGUAGE 'C' STRICT;
+LANGUAGE C STRICT;
index 16f3d9aa321b1212a0d66ae5413dc59edc2e8b23..6d97590d4d69997aca63f1458f1559cb5e085129 100644 (file)
@@ -1,11 +1,7 @@
 -- 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);