diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index c5473b9501b29958f25c3e24f3dfb3bec8ed63bf..2b1318b05e4f87b6832063ff1ae491e3ae200696 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -1,6 +1,6 @@ <!-- Documentation of the system catalogs, directed toward PostgreSQL developers - $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.104 2005/06/17 22:32:41 tgl Exp $ + $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.105 2005/06/18 19:33:41 tgl Exp $ --> <chapter id="catalogs"> @@ -4090,7 +4090,7 @@ <literal>extend</>, <literal>page</>, <literal>tuple</>, - <literal>transaction</>, + <literal>transactionid</>, <literal>object</>, or <literal>userlock</> </entry> @@ -4132,7 +4132,7 @@ </entry> </row> <row> - <entry><structfield>transaction</structfield></entry> + <entry><structfield>transactionid</structfield></entry> <entry><type>xid</type></entry> <entry></entry> <entry> @@ -4168,13 +4168,21 @@ zero. NULL if the object is not a general database object </entry> </row> + <row> + <entry><structfield>transaction</structfield></entry> + <entry><type>xid</type></entry> + <entry></entry> + <entry> + ID of the transaction that is holding or awaiting this lock. + </entry> + </row> <row> <entry><structfield>pid</structfield></entry> <entry><type>integer</type></entry> <entry></entry> <entry> Process ID of the server process holding or awaiting this - lock. Zero if the lock is held by a prepared transaction. + lock. Null if the lock is held by a prepared transaction. </entry> </row> <row> @@ -4196,12 +4204,12 @@ <para> <structfield>granted</structfield> is true in a row representing a lock - held by the indicated session. False indicates that this session is + held by the indicated transaction. False indicates that this transaction is currently waiting to acquire this lock, which implies that some other - session is holding a conflicting lock mode on the same lockable object. - The waiting session will sleep until the other lock is released (or a - deadlock situation is detected). A single session can be waiting to acquire - at most one lock at a time. + transaction is holding a conflicting lock mode on the same lockable object. + The waiting transaction will sleep until the other lock is released (or a + deadlock situation is detected). A single transaction can be waiting to + acquire at most one lock at a time. </para> <para> @@ -4253,6 +4261,13 @@ <structfield>procpid</structfield> column of the <structname>pg_stat_activity</structname> view to get more information on the session holding or waiting to hold the lock. + Also, if you are using prepared transactions, the + <structfield>transaction</> column can be joined to the + <structfield>transaction</structfield> column of the + <structname>pg_prepared_xacts</structname> view to get more + information on prepared transactions that hold locks. + (A prepared transaction can never be waiting for a lock, + but it continues to hold the locks it acquired while running.) </para> </sect1> @@ -4306,6 +4321,14 @@ Global transaction identifier that was assigned to the transaction </entry> </row> + <row> + <entry><structfield>prepared</structfield></entry> + <entry><type>timestamp with time zone</type></entry> + <entry></entry> + <entry> + Time at which the transaction was prepared for commit + </entry> + </row> <row> <entry><structfield>owner</structfield></entry> <entry><type>name</type></entry> diff --git a/src/backend/access/transam/twophase.c b/src/backend/access/transam/twophase.c index 388d9352ce962b9ff26e030ecc4ea051a0d77bc1..30bc21b5244971a417f8543ec0643db176183f73 100644 --- a/src/backend/access/transam/twophase.c +++ b/src/backend/access/transam/twophase.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/transam/twophase.c,v 1.2 2005/06/18 05:21:09 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/twophase.c,v 1.3 2005/06/18 19:33:41 tgl Exp $ * * NOTES * Each global transaction is associated with a global transaction @@ -104,6 +104,7 @@ int max_prepared_xacts = 50; typedef struct GlobalTransactionData { PGPROC proc; /* dummy proc */ + TimestampTz prepared_at; /* time of preparation */ AclId owner; /* ID of user that executed the xact */ TransactionId locking_xid; /* top-level XID of backend working on xact */ bool valid; /* TRUE if fully prepared */ @@ -202,7 +203,8 @@ TwoPhaseShmemInit(void) * assuming that we can use very much backend context. */ GlobalTransaction -MarkAsPreparing(TransactionId xid, Oid databaseid, char *gid, AclId owner) +MarkAsPreparing(TransactionId xid, const char *gid, + TimestampTz prepared_at, AclId owner, Oid databaseid) { GlobalTransaction gxact; int i; @@ -278,6 +280,7 @@ MarkAsPreparing(TransactionId xid, Oid databaseid, char *gid, AclId owner) gxact->proc.subxids.overflowed = false; gxact->proc.subxids.nxids = 0; + gxact->prepared_at = prepared_at; gxact->owner = owner; gxact->locking_xid = xid; gxact->valid = false; @@ -342,7 +345,7 @@ MarkAsPrepared(GlobalTransaction gxact) * Locate the prepared transaction and mark it busy for COMMIT or PREPARE. */ static GlobalTransaction -LockGXact(char *gid, AclId user) +LockGXact(const char *gid, AclId user) { int i; @@ -509,14 +512,16 @@ pg_prepared_xact(PG_FUNCTION_ARGS) /* build tupdesc for result tuples */ /* this had better match pg_prepared_xacts view in system_views.sql */ - tupdesc = CreateTemplateTupleDesc(4, false); + tupdesc = CreateTemplateTupleDesc(5, false); TupleDescInitEntry(tupdesc, (AttrNumber) 1, "transaction", XIDOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 2, "gid", TEXTOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 3, "ownerid", + TupleDescInitEntry(tupdesc, (AttrNumber) 3, "prepared", + TIMESTAMPTZOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 4, "ownerid", INT4OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 4, "dbid", + TupleDescInitEntry(tupdesc, (AttrNumber) 5, "dbid", OIDOID, -1, 0); funcctx->tuple_desc = BlessTupleDesc(tupdesc); @@ -540,8 +545,8 @@ pg_prepared_xact(PG_FUNCTION_ARGS) while (status->array != NULL && status->currIdx < status->ngxacts) { GlobalTransaction gxact = &status->array[status->currIdx++]; - Datum values[4]; - bool nulls[4]; + Datum values[5]; + bool nulls[5]; HeapTuple tuple; Datum result; @@ -556,8 +561,9 @@ pg_prepared_xact(PG_FUNCTION_ARGS) values[0] = TransactionIdGetDatum(gxact->proc.xid); values[1] = DirectFunctionCall1(textin, CStringGetDatum(gxact->gid)); - values[2] = Int32GetDatum(gxact->owner); - values[3] = ObjectIdGetDatum(gxact->proc.databaseId); + values[2] = TimestampTzGetDatum(gxact->prepared_at); + values[3] = Int32GetDatum(gxact->owner); + values[4] = ObjectIdGetDatum(gxact->proc.databaseId); tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); result = HeapTupleGetDatum(tuple); @@ -636,7 +642,7 @@ TwoPhaseGetDummyProc(TransactionId xid) /* * Header for a 2PC state file */ -#define TWOPHASE_MAGIC 0x57F94530 /* format identifier */ +#define TWOPHASE_MAGIC 0x57F94531 /* format identifier */ typedef struct TwoPhaseFileHeader { @@ -644,6 +650,7 @@ typedef struct TwoPhaseFileHeader uint32 total_len; /* actual file length */ TransactionId xid; /* original transaction XID */ Oid database; /* OID of database it was in */ + TimestampTz prepared_at; /* time of preparation */ AclId owner; /* user running the transaction */ int32 nsubxacts; /* number of following subxact XIDs */ int32 ncommitrels; /* number of delete-on-commit rels */ @@ -741,8 +748,9 @@ StartPrepare(GlobalTransaction gxact) hdr.magic = TWOPHASE_MAGIC; hdr.total_len = 0; /* EndPrepare will fill this in */ hdr.xid = xid; - hdr.database = MyDatabaseId; - hdr.owner = GetUserId(); + hdr.database = gxact->proc.databaseId; + hdr.prepared_at = gxact->prepared_at; + hdr.owner = gxact->owner; hdr.nsubxacts = xactGetCommittedChildren(&children); hdr.ncommitrels = smgrGetPendingDeletes(true, &commitrels); hdr.nabortrels = smgrGetPendingDeletes(false, &abortrels); @@ -1046,7 +1054,7 @@ ReadTwoPhaseFile(TransactionId xid) * FinishPreparedTransaction: execute COMMIT PREPARED or ROLLBACK PREPARED */ void -FinishPreparedTransaction(char *gid, bool isCommit) +FinishPreparedTransaction(const char *gid, bool isCommit) { GlobalTransaction gxact; TransactionId xid; @@ -1474,7 +1482,10 @@ RecoverPreparedTransactions(void) /* * Reconstruct subtrans state for the transaction --- needed - * because pg_subtrans is not preserved over a restart + * because pg_subtrans is not preserved over a restart. Note + * that we are linking all the subtransactions directly to the + * top-level XID; there may originally have been a more complex + * hierarchy, but there's no need to restore that exactly. */ for (i = 0; i < hdr->nsubxacts; i++) SubTransSetParent(subxids[i], xid); @@ -1482,7 +1493,9 @@ RecoverPreparedTransactions(void) /* * Recreate its GXACT and dummy PGPROC */ - gxact = MarkAsPreparing(xid, hdr->database, hdr->gid, hdr->owner); + gxact = MarkAsPreparing(xid, hdr->gid, + hdr->prepared_at, + hdr->owner, hdr->database); GXactLoadSubxactData(gxact, hdr->nsubxacts, subxids); MarkAsPrepared(gxact); diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index 74163b7f576f4bda6f2589a9305c89b6a267efa5..2f73ee10c063f60c35c7776765a04a003b0ba7af 100644 --- a/src/backend/access/transam/xact.c +++ b/src/backend/access/transam/xact.c @@ -10,7 +10,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.205 2005/06/17 22:32:42 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.206 2005/06/18 19:33:41 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -1630,6 +1630,9 @@ PrepareTransaction(void) TransactionState s = CurrentTransactionState; TransactionId xid = GetCurrentTransactionId(); GlobalTransaction gxact; + TimestampTz prepared_at; + AbsoluteTime PreparedSec; /* integer part */ + int PreparedUSec; /* microsecond part */ ShowTransactionState("PrepareTransaction"); @@ -1692,6 +1695,9 @@ PrepareTransaction(void) */ s->state = TRANS_PREPARE; + PreparedSec = GetCurrentAbsoluteTimeUsec(&PreparedUSec); + prepared_at = AbsoluteTimeUsecToTimestampTz(PreparedSec, PreparedUSec); + /* Tell bufmgr and smgr to prepare for commit */ BufmgrCommit(); @@ -1699,7 +1705,8 @@ PrepareTransaction(void) * Reserve the GID for this transaction. This could fail if the * requested GID is invalid or already in use. */ - gxact = MarkAsPreparing(xid, MyDatabaseId, prepareGID, GetUserId()); + gxact = MarkAsPreparing(xid, prepareGID, prepared_at, + GetUserId(), MyDatabaseId); prepareGID = NULL; /* diff --git a/src/backend/catalog/system_views.sql b/src/backend/catalog/system_views.sql index 2e9a3ecf7c704e16c827bd24c259eac52dd20811..f757e21039d716e0a5aaef9739355e3e754868f2 100644 --- a/src/backend/catalog/system_views.sql +++ b/src/backend/catalog/system_views.sql @@ -3,7 +3,7 @@ * * Copyright (c) 1996-2005, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.14 2005/06/17 22:32:43 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/catalog/system_views.sql,v 1.15 2005/06/18 19:33:42 tgl Exp $ */ CREATE VIEW pg_user AS @@ -106,15 +106,16 @@ CREATE VIEW pg_locks AS SELECT * FROM pg_lock_status() AS L (locktype text, database oid, relation oid, page int4, tuple int2, - transaction xid, classid oid, objid oid, objsubid int2, - pid int4, mode text, granted boolean); + transactionid xid, classid oid, objid oid, objsubid int2, + transaction xid, pid int4, mode text, granted boolean); CREATE VIEW pg_prepared_xacts AS - SELECT P.transaction, P.gid, U.usename AS owner, D.datname AS database + SELECT P.transaction, P.gid, P.prepared, + U.usename AS owner, D.datname AS database FROM pg_prepared_xact() AS P - (transaction xid, gid text, ownerid int4, dbid oid) - LEFT JOIN pg_database D ON P.dbid = D.oid - LEFT JOIN pg_shadow U ON P.ownerid = U.usesysid; + (transaction xid, gid text, prepared timestamptz, ownerid int4, dbid oid) + LEFT JOIN pg_shadow U ON P.ownerid = U.usesysid + LEFT JOIN pg_database D ON P.dbid = D.oid; CREATE VIEW pg_settings AS SELECT * diff --git a/src/backend/utils/adt/lockfuncs.c b/src/backend/utils/adt/lockfuncs.c index e941ec2d3d86fba99b664687c7c11794039e95d3..0bdf918e475f330520a8db4a9cca46fba156afd0 100644 --- a/src/backend/utils/adt/lockfuncs.c +++ b/src/backend/utils/adt/lockfuncs.c @@ -6,7 +6,7 @@ * Copyright (c) 2002-2005, PostgreSQL Global Development Group * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/lockfuncs.c,v 1.18 2005/05/17 21:46:10 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/lockfuncs.c,v 1.19 2005/06/18 19:33:42 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -26,7 +26,7 @@ static const char * const LockTagTypeNames[] = { "extend", "page", "tuple", - "transaction", + "transactionid", "object", "userlock" }; @@ -64,7 +64,7 @@ pg_lock_status(PG_FUNCTION_ARGS) /* build tupdesc for result tuples */ /* this had better match pg_locks view in system_views.sql */ - tupdesc = CreateTemplateTupleDesc(12, false); + tupdesc = CreateTemplateTupleDesc(13, false); TupleDescInitEntry(tupdesc, (AttrNumber) 1, "locktype", TEXTOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 2, "database", @@ -75,7 +75,7 @@ pg_lock_status(PG_FUNCTION_ARGS) INT4OID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 5, "tuple", INT2OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 6, "transaction", + TupleDescInitEntry(tupdesc, (AttrNumber) 6, "transactionid", XIDOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 7, "classid", OIDOID, -1, 0); @@ -83,11 +83,13 @@ pg_lock_status(PG_FUNCTION_ARGS) OIDOID, -1, 0); TupleDescInitEntry(tupdesc, (AttrNumber) 9, "objsubid", INT2OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 10, "pid", + TupleDescInitEntry(tupdesc, (AttrNumber) 10, "transaction", + XIDOID, -1, 0); + TupleDescInitEntry(tupdesc, (AttrNumber) 11, "pid", INT4OID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 11, "mode", + TupleDescInitEntry(tupdesc, (AttrNumber) 12, "mode", TEXTOID, -1, 0); - TupleDescInitEntry(tupdesc, (AttrNumber) 12, "granted", + TupleDescInitEntry(tupdesc, (AttrNumber) 13, "granted", BOOLOID, -1, 0); funcctx->tuple_desc = BlessTupleDesc(tupdesc); @@ -118,8 +120,8 @@ pg_lock_status(PG_FUNCTION_ARGS) LOCKMODE mode = 0; const char *locktypename; char tnbuf[32]; - Datum values[12]; - char nulls[12]; + Datum values[13]; + char nulls[13]; HeapTuple tuple; Datum result; @@ -249,10 +251,14 @@ pg_lock_status(PG_FUNCTION_ARGS) break; } - values[9] = Int32GetDatum(proc->pid); - values[10] = DirectFunctionCall1(textin, + values[9] = TransactionIdGetDatum(proc->xid); + if (proc->pid != 0) + values[10] = Int32GetDatum(proc->pid); + else + nulls[10] = 'n'; + values[11] = DirectFunctionCall1(textin, CStringGetDatum(GetLockmodeName(mode))); - values[11] = BoolGetDatum(granted); + values[12] = BoolGetDatum(granted); tuple = heap_formtuple(funcctx->tuple_desc, values, nulls); result = HeapTupleGetDatum(tuple); diff --git a/src/include/access/twophase.h b/src/include/access/twophase.h index ac2e05f33ce68223b2a7825c4972c3398ee3e261..d7c64f2b12edd3134612a750873c5675128d30f8 100644 --- a/src/include/access/twophase.h +++ b/src/include/access/twophase.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/twophase.h,v 1.1 2005/06/17 22:32:48 tgl Exp $ + * $PostgreSQL: pgsql/src/include/access/twophase.h,v 1.2 2005/06/18 19:33:42 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -15,6 +15,7 @@ #define TWOPHASE_H #include "storage/lock.h" +#include "utils/timestamp.h" /* @@ -31,8 +32,9 @@ extern void TwoPhaseShmemInit(void); extern PGPROC *TwoPhaseGetDummyProc(TransactionId xid); -extern GlobalTransaction MarkAsPreparing(TransactionId xid, Oid databaseid, - char *gid, AclId owner); +extern GlobalTransaction MarkAsPreparing(TransactionId xid, const char *gid, + TimestampTz prepared_at, + AclId owner, Oid databaseid); extern void MarkAsPrepared(GlobalTransaction gxact); extern void StartPrepare(GlobalTransaction gxact); @@ -44,6 +46,6 @@ extern void RecoverPreparedTransactions(void); extern void RecreateTwoPhaseFile(TransactionId xid, void *content, int len); extern void RemoveTwoPhaseFile(TransactionId xid, bool giveWarning); -extern void FinishPreparedTransaction(char *gid, bool isCommit); +extern void FinishPreparedTransaction(const char *gid, bool isCommit); #endif /* TWOPHASE_H */ diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index de422a41a9f3ddb0bac5cc53cc2dac5a704f7fdd..bdbaa83ace87e0694ef9cd951079bfb8a42f5176 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.277 2005/06/17 22:32:48 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.278 2005/06/18 19:33:42 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200506171 +#define CATALOG_VERSION_NO 200506181 #endif diff --git a/src/test/regress/expected/rules.out b/src/test/regress/expected/rules.out index acd2d25b35de296439accebd28eb28b9d5831baa..384ce37d9c29046d988155906723cb202daf9eda 100644 --- a/src/test/regress/expected/rules.out +++ b/src/test/regress/expected/rules.out @@ -1278,8 +1278,8 @@ SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schem --------------------------+----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- iexit | SELECT ih.name, ih.thepath, interpt_pp(ih.thepath, r.thepath) AS exit FROM ihighway ih, ramp r WHERE (ih.thepath ## r.thepath); pg_indexes | SELECT n.nspname AS schemaname, c.relname AS tablename, i.relname AS indexname, t.spcname AS "tablespace", pg_get_indexdef(i.oid) AS indexdef FROM ((((pg_index x JOIN pg_class c ON ((c.oid = x.indrelid))) JOIN pg_class i ON ((i.oid = x.indexrelid))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) LEFT JOIN pg_tablespace t ON ((t.oid = i.reltablespace))) WHERE ((c.relkind = 'r'::"char") AND (i.relkind = 'i'::"char")); - pg_locks | SELECT l.locktype, l."database", l.relation, l.page, l.tuple, l."transaction", l.classid, l.objid, l.objsubid, l.pid, l."mode", l.granted FROM pg_lock_status() l(locktype text, "database" oid, relation oid, page integer, tuple smallint, "transaction" xid, classid oid, objid oid, objsubid smallint, pid integer, "mode" text, granted boolean); - pg_prepared_xacts | SELECT p."transaction", p.gid, u.usename AS "owner", d.datname AS "database" FROM ((pg_prepared_xact() p("transaction" xid, gid text, ownerid integer, dbid oid) LEFT JOIN pg_database d ON ((p.dbid = d.oid))) LEFT JOIN pg_shadow u ON ((p.ownerid = u.usesysid))); + pg_locks | SELECT l.locktype, l."database", l.relation, l.page, l.tuple, l.transactionid, l.classid, l.objid, l.objsubid, l."transaction", l.pid, l."mode", l.granted FROM pg_lock_status() l(locktype text, "database" oid, relation oid, page integer, tuple smallint, transactionid xid, classid oid, objid oid, objsubid smallint, "transaction" xid, pid integer, "mode" text, granted boolean); + pg_prepared_xacts | SELECT p."transaction", p.gid, p."prepared", u.usename AS "owner", d.datname AS "database" FROM ((pg_prepared_xact() p("transaction" xid, gid text, "prepared" timestamp with time zone, ownerid integer, dbid oid) LEFT JOIN pg_shadow u ON ((p.ownerid = u.usesysid))) LEFT JOIN pg_database d ON ((p.dbid = d.oid))); pg_rules | SELECT n.nspname AS schemaname, c.relname AS tablename, r.rulename, pg_get_ruledef(r.oid) AS definition FROM ((pg_rewrite r JOIN pg_class c ON ((c.oid = r.ev_class))) LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))) WHERE (r.rulename <> '_RETURN'::name); pg_settings | SELECT a.name, a.setting, a.category, a.short_desc, a.extra_desc, a.context, a.vartype, a.source, a.min_val, a.max_val FROM pg_show_all_settings() a(name text, setting text, category text, short_desc text, extra_desc text, context text, vartype text, source text, min_val text, max_val text); pg_stat_activity | SELECT d.oid AS datid, d.datname, pg_stat_get_backend_pid(s.backendid) AS procpid, pg_stat_get_backend_userid(s.backendid) AS usesysid, u.usename, pg_stat_get_backend_activity(s.backendid) AS current_query, pg_stat_get_backend_activity_start(s.backendid) AS query_start, pg_stat_get_backend_start(s.backendid) AS backend_start, pg_stat_get_backend_client_addr(s.backendid) AS client_addr, pg_stat_get_backend_client_port(s.backendid) AS client_port FROM pg_database d, (SELECT pg_stat_get_backend_idset() AS backendid) s, pg_shadow u WHERE ((pg_stat_get_backend_dbid(s.backendid) = d.oid) AND (pg_stat_get_backend_userid(s.backendid) = u.usesysid));