Restrict pgrowlocks function to superusers. (This might be too strict,

but no permissions check at all is certainly no good.)  Clean up usage
of some deprecated APIs.
REL8_3_STABLE
Tom Lane 18 years ago
parent 38c75ecf83
commit 56f3fb3ba1
  1. 14
      contrib/pgrowlocks/README.pgrowlocks
  2. 50
      contrib/pgrowlocks/pgrowlocks.c
  3. 21
      contrib/pgrowlocks/pgrowlocks.sql.in
  4. 2
      contrib/pgrowlocks/uninstall_pgrowlocks.sql

@ -1,4 +1,4 @@
$PostgreSQL: pgsql/contrib/pgrowlocks/README.pgrowlocks,v 1.1 2006/04/23 01:12:58 ishii Exp $
$PostgreSQL: pgsql/contrib/pgrowlocks/README.pgrowlocks,v 1.2 2007/08/27 00:13:51 tgl Exp $
pgrowlocks README Tatsuo Ishii
@ -6,16 +6,14 @@ pgrowlocks README Tatsuo Ishii
pgrowlocks shows row locking information for specified table.
pgrowlocks returns following data type:
pgrowlocks returns following columns:
CREATE TYPE pgrowlocks_type AS (
locked_row TID, -- row TID
lock_type TEXT, -- lock type
locker XID, -- locking XID
multi bool, -- multi XID?
xids xid[], -- multi XIDs
pids INTEGER[] -- locker's process id
);
Here is a sample execution of pgrowlocks:
@ -62,14 +60,6 @@ test=# SELECT * FROM pgrowlocks('t1');
3. How to use pgrowlocks
The calling sequence for pgrowlocks is as follows:
CREATE OR REPLACE FUNCTION pgrowlocks(text) RETURNS pgrowlocks_type
AS 'MODULE_PATHNAME', 'pgrowlocks'
LANGUAGE 'c' WITH (isstrict);
The parameter is a name of table. pgrowlocks returns type pgrowlocks_type.
pgrowlocks grab AccessShareLock for the target table and read each
row one by one to get the row locking information. You should
notice that:

@ -1,5 +1,5 @@
/*
* $PostgreSQL: pgsql/contrib/pgrowlocks/pgrowlocks.c,v 1.5 2006/10/04 00:29:46 momjian Exp $
* $PostgreSQL: pgsql/contrib/pgrowlocks/pgrowlocks.c,v 1.6 2007/08/27 00:13:51 tgl Exp $
*
* Copyright (c) 2005-2006 Tatsuo Ishii
*
@ -24,19 +24,15 @@
#include "postgres.h"
#include "funcapi.h"
#include "access/heapam.h"
#include "access/transam.h"
#include "access/multixact.h"
#include "access/xact.h"
#include "catalog/namespace.h"
#include "catalog/pg_type.h"
#include "storage/proc.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "storage/procarray.h"
#include "utils/builtins.h"
#ifdef HEAP_XMAX_SHARED_LOCK
#include "access/multixact.h"
#include "storage/procarray.h"
#endif
PG_MODULE_MAGIC;
@ -47,22 +43,11 @@ extern Datum pgrowlocks(PG_FUNCTION_ARGS);
/* ----------
* pgrowlocks:
* returns tids of rows being locked
*
* C FUNCTION definition
* pgrowlocks(text) returns set of pgrowlocks_type
* see pgrowlocks.sql for pgrowlocks_type
* ----------
*/
#define DUMMY_TUPLE "public.pgrowlocks_type"
#define NCHARS 32
/*
* define this if makeRangeVarFromNameList() has two arguments. As far
* as I know, this only happens in 8.0.x.
*/
#undef MAKERANGEVARFROMNAMELIST_HAS_TWO_ARGS
typedef struct
{
Relation rel;
@ -82,6 +67,11 @@ pgrowlocks(PG_FUNCTION_ARGS)
MyData *mydata;
Relation rel;
if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
(errmsg("must be superuser to use pgrowlocks"))));
if (SRF_IS_FIRSTCALL())
{
text *relname;
@ -91,17 +81,17 @@ pgrowlocks(PG_FUNCTION_ARGS)
funcctx = SRF_FIRSTCALL_INIT();
oldcontext = MemoryContextSwitchTo(funcctx->multi_call_memory_ctx);
tupdesc = RelationNameGetTupleDesc(DUMMY_TUPLE);
/* Build a tuple descriptor for our result type */
if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
elog(ERROR, "return type must be a row type");
attinmeta = TupleDescGetAttInMetadata(tupdesc);
funcctx->attinmeta = attinmeta;
relname = PG_GETARG_TEXT_P(0);
#ifdef MAKERANGEVARFROMNAMELIST_HAS_TWO_ARGS
relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname, "pgrowlocks"));
#else
relrv = makeRangeVarFromNameList(textToQualifiedNameList(relname));
#endif
rel = heap_openrv(relrv, AccessShareLock);
scan = heap_beginscan(rel, SnapshotNow, 0, NULL);
mydata = palloc(sizeof(*mydata));
mydata->rel = rel;
@ -135,17 +125,12 @@ pgrowlocks(PG_FUNCTION_ARGS)
i = 0;
values[i++] = (char *) DirectFunctionCall1(tidout, PointerGetDatum(&tuple->t_self));
#ifdef HEAP_XMAX_SHARED_LOCK
if (tuple->t_data->t_infomask & HEAP_XMAX_SHARED_LOCK)
values[i++] = pstrdup("Shared");
else
values[i++] = pstrdup("Exclusive");
#else
values[i++] = pstrdup("Exclusive");
#endif
values[i] = palloc(NCHARS * sizeof(char));
snprintf(values[i++], NCHARS, "%d", HeapTupleHeaderGetXmax(tuple->t_data));
#ifdef HEAP_XMAX_SHARED_LOCK
if (tuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI)
{
TransactionId *xids;
@ -198,11 +183,6 @@ pgrowlocks(PG_FUNCTION_ARGS)
values[i] = palloc(NCHARS * sizeof(char));
snprintf(values[i++], NCHARS, "{%d}", BackendXidGetPid(HeapTupleHeaderGetXmax(tuple->t_data)));
}
#else
values[i++] = pstrdup("false");
values[i++] = pstrdup("{}");
values[i++] = pstrdup("{}");
#endif
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_UNLOCK);

@ -1,16 +1,13 @@
-- Adjust this setting to control where the objects get created.
SET search_path = public;
CREATE TYPE pgrowlocks_type AS (
locked_row TID, -- row TID
lock_type TEXT, -- lock type
locker XID, -- locking XID
multi bool, -- multi XID?
xids xid[], -- multi XIDs
pids INTEGER[] -- locker's process id
);
CREATE OR REPLACE FUNCTION pgrowlocks(text)
RETURNS setof pgrowlocks_type
CREATE OR REPLACE FUNCTION pgrowlocks(IN relname text,
OUT locked_row TID, -- row TID
OUT lock_type TEXT, -- lock type
OUT locker XID, -- locking XID
OUT multi bool, -- multi XID?
OUT xids xid[], -- multi XIDs
OUT pids INTEGER[]) -- locker's process id
RETURNS SETOF record
AS 'MODULE_PATHNAME', 'pgrowlocks'
LANGUAGE 'C' STRICT;
LANGUAGE C STRICT;

@ -1,5 +1,3 @@
SET search_path = public;
DROP FUNCTION pgrowlocks(text);
DROP TYPE pgrowlocks_type;

Loading…
Cancel
Save