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.
This commit is contained in:
Tom Lane 2007-08-27 00:13:51 +00:00
parent 38c75ecf83
commit 56f3fb3ba1
4 changed files with 26 additions and 61 deletions

View File

@ -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:

View File

@ -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);

View File

@ -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;

View File

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