Commit a8d1075f authored by Tom Lane's avatar Tom Lane

Add a time-of-preparation column to the pg_prepared_xacts view, per an

old suggestion by Oliver Jowett.  Also, add a transaction column to the
pg_locks view to show the xid of each transaction holding or awaiting
locks; this allows prepared transactions to be properly associated with
the locks they own.  There was already a column named 'transaction',
and I chose to rename it to 'transactionid' --- since this column is
new in the current devel cycle there should be no backwards compatibility
issue to worry about.
parent 66b09849
<!-- <!--
Documentation of the system catalogs, directed toward PostgreSQL developers 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"> <chapter id="catalogs">
...@@ -4090,7 +4090,7 @@ ...@@ -4090,7 +4090,7 @@
<literal>extend</>, <literal>extend</>,
<literal>page</>, <literal>page</>,
<literal>tuple</>, <literal>tuple</>,
<literal>transaction</>, <literal>transactionid</>,
<literal>object</>, or <literal>object</>, or
<literal>userlock</> <literal>userlock</>
</entry> </entry>
...@@ -4132,7 +4132,7 @@ ...@@ -4132,7 +4132,7 @@
</entry> </entry>
</row> </row>
<row> <row>
<entry><structfield>transaction</structfield></entry> <entry><structfield>transactionid</structfield></entry>
<entry><type>xid</type></entry> <entry><type>xid</type></entry>
<entry></entry> <entry></entry>
<entry> <entry>
...@@ -4168,13 +4168,21 @@ ...@@ -4168,13 +4168,21 @@
zero. NULL if the object is not a general database object zero. NULL if the object is not a general database object
</entry> </entry>
</row> </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> <row>
<entry><structfield>pid</structfield></entry> <entry><structfield>pid</structfield></entry>
<entry><type>integer</type></entry> <entry><type>integer</type></entry>
<entry></entry> <entry></entry>
<entry> <entry>
Process ID of the server process holding or awaiting this 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> </entry>
</row> </row>
<row> <row>
...@@ -4196,12 +4204,12 @@ ...@@ -4196,12 +4204,12 @@
<para> <para>
<structfield>granted</structfield> is true in a row representing a lock <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 currently waiting to acquire this lock, which implies that some other
session is holding a conflicting lock mode on the same lockable object. transaction is holding a conflicting lock mode on the same lockable object.
The waiting session will sleep until the other lock is released (or a The waiting transaction will sleep until the other lock is released (or a
deadlock situation is detected). A single session can be waiting to acquire deadlock situation is detected). A single transaction can be waiting to
at most one lock at a time. acquire at most one lock at a time.
</para> </para>
<para> <para>
...@@ -4253,6 +4261,13 @@ ...@@ -4253,6 +4261,13 @@
<structfield>procpid</structfield> column of the <structfield>procpid</structfield> column of the
<structname>pg_stat_activity</structname> view to get more <structname>pg_stat_activity</structname> view to get more
information on the session holding or waiting to hold the lock. 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> </para>
</sect1> </sect1>
...@@ -4306,6 +4321,14 @@ ...@@ -4306,6 +4321,14 @@
Global transaction identifier that was assigned to the transaction Global transaction identifier that was assigned to the transaction
</entry> </entry>
</row> </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> <row>
<entry><structfield>owner</structfield></entry> <entry><structfield>owner</structfield></entry>
<entry><type>name</type></entry> <entry><type>name</type></entry>
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * 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 * NOTES
* Each global transaction is associated with a global transaction * Each global transaction is associated with a global transaction
...@@ -104,6 +104,7 @@ int max_prepared_xacts = 50; ...@@ -104,6 +104,7 @@ int max_prepared_xacts = 50;
typedef struct GlobalTransactionData typedef struct GlobalTransactionData
{ {
PGPROC proc; /* dummy proc */ PGPROC proc; /* dummy proc */
TimestampTz prepared_at; /* time of preparation */
AclId owner; /* ID of user that executed the xact */ AclId owner; /* ID of user that executed the xact */
TransactionId locking_xid; /* top-level XID of backend working on xact */ TransactionId locking_xid; /* top-level XID of backend working on xact */
bool valid; /* TRUE if fully prepared */ bool valid; /* TRUE if fully prepared */
...@@ -202,7 +203,8 @@ TwoPhaseShmemInit(void) ...@@ -202,7 +203,8 @@ TwoPhaseShmemInit(void)
* assuming that we can use very much backend context. * assuming that we can use very much backend context.
*/ */
GlobalTransaction 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; GlobalTransaction gxact;
int i; int i;
...@@ -278,6 +280,7 @@ MarkAsPreparing(TransactionId xid, Oid databaseid, char *gid, AclId owner) ...@@ -278,6 +280,7 @@ MarkAsPreparing(TransactionId xid, Oid databaseid, char *gid, AclId owner)
gxact->proc.subxids.overflowed = false; gxact->proc.subxids.overflowed = false;
gxact->proc.subxids.nxids = 0; gxact->proc.subxids.nxids = 0;
gxact->prepared_at = prepared_at;
gxact->owner = owner; gxact->owner = owner;
gxact->locking_xid = xid; gxact->locking_xid = xid;
gxact->valid = false; gxact->valid = false;
...@@ -342,7 +345,7 @@ MarkAsPrepared(GlobalTransaction gxact) ...@@ -342,7 +345,7 @@ MarkAsPrepared(GlobalTransaction gxact)
* Locate the prepared transaction and mark it busy for COMMIT or PREPARE. * Locate the prepared transaction and mark it busy for COMMIT or PREPARE.
*/ */
static GlobalTransaction static GlobalTransaction
LockGXact(char *gid, AclId user) LockGXact(const char *gid, AclId user)
{ {
int i; int i;
...@@ -509,14 +512,16 @@ pg_prepared_xact(PG_FUNCTION_ARGS) ...@@ -509,14 +512,16 @@ pg_prepared_xact(PG_FUNCTION_ARGS)
/* build tupdesc for result tuples */ /* build tupdesc for result tuples */
/* this had better match pg_prepared_xacts view in system_views.sql */ /* 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", TupleDescInitEntry(tupdesc, (AttrNumber) 1, "transaction",
XIDOID, -1, 0); XIDOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "gid", TupleDescInitEntry(tupdesc, (AttrNumber) 2, "gid",
TEXTOID, -1, 0); TEXTOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 3, "ownerid", TupleDescInitEntry(tupdesc, (AttrNumber) 3, "prepared",
TIMESTAMPTZOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 4, "ownerid",
INT4OID, -1, 0); INT4OID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 4, "dbid", TupleDescInitEntry(tupdesc, (AttrNumber) 5, "dbid",
OIDOID, -1, 0); OIDOID, -1, 0);
funcctx->tuple_desc = BlessTupleDesc(tupdesc); funcctx->tuple_desc = BlessTupleDesc(tupdesc);
...@@ -540,8 +545,8 @@ pg_prepared_xact(PG_FUNCTION_ARGS) ...@@ -540,8 +545,8 @@ pg_prepared_xact(PG_FUNCTION_ARGS)
while (status->array != NULL && status->currIdx < status->ngxacts) while (status->array != NULL && status->currIdx < status->ngxacts)
{ {
GlobalTransaction gxact = &status->array[status->currIdx++]; GlobalTransaction gxact = &status->array[status->currIdx++];
Datum values[4]; Datum values[5];
bool nulls[4]; bool nulls[5];
HeapTuple tuple; HeapTuple tuple;
Datum result; Datum result;
...@@ -556,8 +561,9 @@ pg_prepared_xact(PG_FUNCTION_ARGS) ...@@ -556,8 +561,9 @@ pg_prepared_xact(PG_FUNCTION_ARGS)
values[0] = TransactionIdGetDatum(gxact->proc.xid); values[0] = TransactionIdGetDatum(gxact->proc.xid);
values[1] = DirectFunctionCall1(textin, CStringGetDatum(gxact->gid)); values[1] = DirectFunctionCall1(textin, CStringGetDatum(gxact->gid));
values[2] = Int32GetDatum(gxact->owner); values[2] = TimestampTzGetDatum(gxact->prepared_at);
values[3] = ObjectIdGetDatum(gxact->proc.databaseId); values[3] = Int32GetDatum(gxact->owner);
values[4] = ObjectIdGetDatum(gxact->proc.databaseId);
tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls); tuple = heap_form_tuple(funcctx->tuple_desc, values, nulls);
result = HeapTupleGetDatum(tuple); result = HeapTupleGetDatum(tuple);
...@@ -636,7 +642,7 @@ TwoPhaseGetDummyProc(TransactionId xid) ...@@ -636,7 +642,7 @@ TwoPhaseGetDummyProc(TransactionId xid)
/* /*
* Header for a 2PC state file * Header for a 2PC state file
*/ */
#define TWOPHASE_MAGIC 0x57F94530 /* format identifier */ #define TWOPHASE_MAGIC 0x57F94531 /* format identifier */
typedef struct TwoPhaseFileHeader typedef struct TwoPhaseFileHeader
{ {
...@@ -644,6 +650,7 @@ typedef struct TwoPhaseFileHeader ...@@ -644,6 +650,7 @@ typedef struct TwoPhaseFileHeader
uint32 total_len; /* actual file length */ uint32 total_len; /* actual file length */
TransactionId xid; /* original transaction XID */ TransactionId xid; /* original transaction XID */
Oid database; /* OID of database it was in */ Oid database; /* OID of database it was in */
TimestampTz prepared_at; /* time of preparation */
AclId owner; /* user running the transaction */ AclId owner; /* user running the transaction */
int32 nsubxacts; /* number of following subxact XIDs */ int32 nsubxacts; /* number of following subxact XIDs */
int32 ncommitrels; /* number of delete-on-commit rels */ int32 ncommitrels; /* number of delete-on-commit rels */
...@@ -741,8 +748,9 @@ StartPrepare(GlobalTransaction gxact) ...@@ -741,8 +748,9 @@ StartPrepare(GlobalTransaction gxact)
hdr.magic = TWOPHASE_MAGIC; hdr.magic = TWOPHASE_MAGIC;
hdr.total_len = 0; /* EndPrepare will fill this in */ hdr.total_len = 0; /* EndPrepare will fill this in */
hdr.xid = xid; hdr.xid = xid;
hdr.database = MyDatabaseId; hdr.database = gxact->proc.databaseId;
hdr.owner = GetUserId(); hdr.prepared_at = gxact->prepared_at;
hdr.owner = gxact->owner;
hdr.nsubxacts = xactGetCommittedChildren(&children); hdr.nsubxacts = xactGetCommittedChildren(&children);
hdr.ncommitrels = smgrGetPendingDeletes(true, &commitrels); hdr.ncommitrels = smgrGetPendingDeletes(true, &commitrels);
hdr.nabortrels = smgrGetPendingDeletes(false, &abortrels); hdr.nabortrels = smgrGetPendingDeletes(false, &abortrels);
...@@ -1046,7 +1054,7 @@ ReadTwoPhaseFile(TransactionId xid) ...@@ -1046,7 +1054,7 @@ ReadTwoPhaseFile(TransactionId xid)
* FinishPreparedTransaction: execute COMMIT PREPARED or ROLLBACK PREPARED * FinishPreparedTransaction: execute COMMIT PREPARED or ROLLBACK PREPARED
*/ */
void void
FinishPreparedTransaction(char *gid, bool isCommit) FinishPreparedTransaction(const char *gid, bool isCommit)
{ {
GlobalTransaction gxact; GlobalTransaction gxact;
TransactionId xid; TransactionId xid;
...@@ -1474,7 +1482,10 @@ RecoverPreparedTransactions(void) ...@@ -1474,7 +1482,10 @@ RecoverPreparedTransactions(void)
/* /*
* Reconstruct subtrans state for the transaction --- needed * 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++) for (i = 0; i < hdr->nsubxacts; i++)
SubTransSetParent(subxids[i], xid); SubTransSetParent(subxids[i], xid);
...@@ -1482,7 +1493,9 @@ RecoverPreparedTransactions(void) ...@@ -1482,7 +1493,9 @@ RecoverPreparedTransactions(void)
/* /*
* Recreate its GXACT and dummy PGPROC * 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); GXactLoadSubxactData(gxact, hdr->nsubxacts, subxids);
MarkAsPrepared(gxact); MarkAsPrepared(gxact);
......
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
* *
* *
* IDENTIFICATION * 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) ...@@ -1630,6 +1630,9 @@ PrepareTransaction(void)
TransactionState s = CurrentTransactionState; TransactionState s = CurrentTransactionState;
TransactionId xid = GetCurrentTransactionId(); TransactionId xid = GetCurrentTransactionId();
GlobalTransaction gxact; GlobalTransaction gxact;
TimestampTz prepared_at;
AbsoluteTime PreparedSec; /* integer part */
int PreparedUSec; /* microsecond part */
ShowTransactionState("PrepareTransaction"); ShowTransactionState("PrepareTransaction");
...@@ -1692,6 +1695,9 @@ PrepareTransaction(void) ...@@ -1692,6 +1695,9 @@ PrepareTransaction(void)
*/ */
s->state = TRANS_PREPARE; s->state = TRANS_PREPARE;
PreparedSec = GetCurrentAbsoluteTimeUsec(&PreparedUSec);
prepared_at = AbsoluteTimeUsecToTimestampTz(PreparedSec, PreparedUSec);
/* Tell bufmgr and smgr to prepare for commit */ /* Tell bufmgr and smgr to prepare for commit */
BufmgrCommit(); BufmgrCommit();
...@@ -1699,7 +1705,8 @@ PrepareTransaction(void) ...@@ -1699,7 +1705,8 @@ PrepareTransaction(void)
* Reserve the GID for this transaction. This could fail if the * Reserve the GID for this transaction. This could fail if the
* requested GID is invalid or already in use. * requested GID is invalid or already in use.
*/ */
gxact = MarkAsPreparing(xid, MyDatabaseId, prepareGID, GetUserId()); gxact = MarkAsPreparing(xid, prepareGID, prepared_at,
GetUserId(), MyDatabaseId);
prepareGID = NULL; prepareGID = NULL;
/* /*
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
* *
* Copyright (c) 1996-2005, PostgreSQL Global Development Group * 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 CREATE VIEW pg_user AS
...@@ -106,15 +106,16 @@ CREATE VIEW pg_locks AS ...@@ -106,15 +106,16 @@ CREATE VIEW pg_locks AS
SELECT * SELECT *
FROM pg_lock_status() AS L FROM pg_lock_status() AS L
(locktype text, database oid, relation oid, page int4, tuple int2, (locktype text, database oid, relation oid, page int4, tuple int2,
transaction xid, classid oid, objid oid, objsubid int2, transactionid xid, classid oid, objid oid, objsubid int2,
pid int4, mode text, granted boolean); transaction xid, pid int4, mode text, granted boolean);
CREATE VIEW pg_prepared_xacts AS 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 FROM pg_prepared_xact() AS P
(transaction xid, gid text, ownerid int4, dbid oid) (transaction xid, gid text, prepared timestamptz, ownerid int4, dbid oid)
LEFT JOIN pg_database D ON P.dbid = D.oid LEFT JOIN pg_shadow U ON P.ownerid = U.usesysid
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 CREATE VIEW pg_settings AS
SELECT * SELECT *
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Copyright (c) 2002-2005, PostgreSQL Global Development Group * Copyright (c) 2002-2005, PostgreSQL Global Development Group
* *
* IDENTIFICATION * 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[] = { ...@@ -26,7 +26,7 @@ static const char * const LockTagTypeNames[] = {
"extend", "extend",
"page", "page",
"tuple", "tuple",
"transaction", "transactionid",
"object", "object",
"userlock" "userlock"
}; };
...@@ -64,7 +64,7 @@ pg_lock_status(PG_FUNCTION_ARGS) ...@@ -64,7 +64,7 @@ pg_lock_status(PG_FUNCTION_ARGS)
/* build tupdesc for result tuples */ /* build tupdesc for result tuples */
/* this had better match pg_locks view in system_views.sql */ /* this had better match pg_locks view in system_views.sql */
tupdesc = CreateTemplateTupleDesc(12, false); tupdesc = CreateTemplateTupleDesc(13, false);
TupleDescInitEntry(tupdesc, (AttrNumber) 1, "locktype", TupleDescInitEntry(tupdesc, (AttrNumber) 1, "locktype",
TEXTOID, -1, 0); TEXTOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 2, "database", TupleDescInitEntry(tupdesc, (AttrNumber) 2, "database",
...@@ -75,7 +75,7 @@ pg_lock_status(PG_FUNCTION_ARGS) ...@@ -75,7 +75,7 @@ pg_lock_status(PG_FUNCTION_ARGS)
INT4OID, -1, 0); INT4OID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 5, "tuple", TupleDescInitEntry(tupdesc, (AttrNumber) 5, "tuple",
INT2OID, -1, 0); INT2OID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 6, "transaction", TupleDescInitEntry(tupdesc, (AttrNumber) 6, "transactionid",
XIDOID, -1, 0); XIDOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 7, "classid", TupleDescInitEntry(tupdesc, (AttrNumber) 7, "classid",
OIDOID, -1, 0); OIDOID, -1, 0);
...@@ -83,11 +83,13 @@ pg_lock_status(PG_FUNCTION_ARGS) ...@@ -83,11 +83,13 @@ pg_lock_status(PG_FUNCTION_ARGS)
OIDOID, -1, 0); OIDOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 9, "objsubid", TupleDescInitEntry(tupdesc, (AttrNumber) 9, "objsubid",
INT2OID, -1, 0); INT2OID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 10, "pid", TupleDescInitEntry(tupdesc, (AttrNumber) 10, "transaction",
XIDOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 11, "pid",
INT4OID, -1, 0); INT4OID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 11, "mode", TupleDescInitEntry(tupdesc, (AttrNumber) 12, "mode",
TEXTOID, -1, 0); TEXTOID, -1, 0);
TupleDescInitEntry(tupdesc, (AttrNumber) 12, "granted", TupleDescInitEntry(tupdesc, (AttrNumber) 13, "granted",
BOOLOID, -1, 0); BOOLOID, -1, 0);
funcctx->tuple_desc = BlessTupleDesc(tupdesc); funcctx->tuple_desc = BlessTupleDesc(tupdesc);
...@@ -118,8 +120,8 @@ pg_lock_status(PG_FUNCTION_ARGS) ...@@ -118,8 +120,8 @@ pg_lock_status(PG_FUNCTION_ARGS)
LOCKMODE mode = 0; LOCKMODE mode = 0;
const char *locktypename; const char *locktypename;
char tnbuf[32]; char tnbuf[32];
Datum values[12]; Datum values[13];
char nulls[12]; char nulls[13];
HeapTuple tuple; HeapTuple tuple;
Datum result; Datum result;
...@@ -249,10 +251,14 @@ pg_lock_status(PG_FUNCTION_ARGS) ...@@ -249,10 +251,14 @@ pg_lock_status(PG_FUNCTION_ARGS)
break; break;
} }
values[9] = Int32GetDatum(proc->pid); values[9] = TransactionIdGetDatum(proc->xid);
values[10] = DirectFunctionCall1(textin, if (proc->pid != 0)
values[10] = Int32GetDatum(proc->pid);
else
nulls[10] = 'n';
values[11] = DirectFunctionCall1(textin,
CStringGetDatum(GetLockmodeName(mode))); CStringGetDatum(GetLockmodeName(mode)));
values[11] = BoolGetDatum(granted); values[12] = BoolGetDatum(granted);
tuple = heap_formtuple(funcctx->tuple_desc, values, nulls); tuple = heap_formtuple(funcctx->tuple_desc, values, nulls);
result = HeapTupleGetDatum(tuple); result = HeapTupleGetDatum(tuple);
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 @@ ...@@ -15,6 +15,7 @@
#define TWOPHASE_H #define TWOPHASE_H
#include "storage/lock.h" #include "storage/lock.h"
#include "utils/timestamp.h"
/* /*
...@@ -31,8 +32,9 @@ extern void TwoPhaseShmemInit(void); ...@@ -31,8 +32,9 @@ extern void TwoPhaseShmemInit(void);
extern PGPROC *TwoPhaseGetDummyProc(TransactionId xid); extern PGPROC *TwoPhaseGetDummyProc(TransactionId xid);
extern GlobalTransaction MarkAsPreparing(TransactionId xid, Oid databaseid, extern GlobalTransaction MarkAsPreparing(TransactionId xid, const char *gid,
char *gid, AclId owner); TimestampTz prepared_at,
AclId owner, Oid databaseid);
extern void MarkAsPrepared(GlobalTransaction gxact); extern void MarkAsPrepared(GlobalTransaction gxact);
extern void StartPrepare(GlobalTransaction gxact); extern void StartPrepare(GlobalTransaction gxact);
...@@ -44,6 +46,6 @@ extern void RecoverPreparedTransactions(void); ...@@ -44,6 +46,6 @@ extern void RecoverPreparedTransactions(void);
extern void RecreateTwoPhaseFile(TransactionId xid, void *content, int len); extern void RecreateTwoPhaseFile(TransactionId xid, void *content, int len);
extern void RemoveTwoPhaseFile(TransactionId xid, bool giveWarning); 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 */ #endif /* TWOPHASE_H */
...@@ -37,7 +37,7 @@ ...@@ -37,7 +37,7 @@
* Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * 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 @@ ...@@ -53,6 +53,6 @@
*/ */
/* yyyymmddN */ /* yyyymmddN */
#define CATALOG_VERSION_NO 200506171 #define CATALOG_VERSION_NO 200506181
#endif #endif
...@@ -1278,8 +1278,8 @@ SELECT viewname, definition FROM pg_views WHERE schemaname <> 'information_schem ...@@ -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); 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_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_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, 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_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_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_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)); 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));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment