diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 1889d09784c..aade7a29c13 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.222.2.1 2007/02/04 20:00:49 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.222.2.2 2008/03/04 19:54:23 tgl Exp $ * * * INTERFACE ROUTINES @@ -699,6 +699,10 @@ relation_open(Oid relationId, LOCKMODE lockmode) if (!RelationIsValid(r)) elog(ERROR, "could not open relation with OID %u", relationId); + /* Make note that we've accessed a temporary relation */ + if (r->rd_istemp) + MyXactAccessedTempRel = true; + return r; } @@ -741,6 +745,10 @@ try_relation_open(Oid relationId, LOCKMODE lockmode) if (!RelationIsValid(r)) elog(ERROR, "could not open relation with OID %u", relationId); + /* Make note that we've accessed a temporary relation */ + if (r->rd_istemp) + MyXactAccessedTempRel = true; + return r; } @@ -785,6 +793,10 @@ relation_open_nowait(Oid relationId, LOCKMODE lockmode) if (!RelationIsValid(r)) elog(ERROR, "could not open relation with OID %u", relationId); + /* Make note that we've accessed a temporary relation */ + if (r->rd_istemp) + MyXactAccessedTempRel = true; + return r; } diff --git a/src/backend/access/transam/xact.c b/src/backend/access/transam/xact.c index e000547b327..6ef1f5a7420 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.229.2.3 2008/01/03 21:23:45 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.229.2.4 2008/03/04 19:54:23 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -57,6 +57,13 @@ bool XactReadOnly; int CommitDelay = 0; /* precommit delay in microseconds */ int CommitSiblings = 5; /* # concurrent xacts needed to sleep */ +/* + * MyXactAccessedTempRel is set when a temporary relation is accessed. + * We don't allow PREPARE TRANSACTION in that case. (This is global + * so that it can be set from heapam.c.) + */ +bool MyXactAccessedTempRel = false; + /* * transaction states - transaction state from server perspective @@ -1389,6 +1396,7 @@ StartTransaction(void) FreeXactSnapshot(); XactIsoLevel = DefaultXactIsoLevel; XactReadOnly = DefaultXactReadOnly; + MyXactAccessedTempRel = false; /* * reinitialize within-transaction counters @@ -1715,6 +1723,26 @@ PrepareTransaction(void) /* NOTIFY and flatfiles will be handled below */ + /* + * Don't allow PREPARE TRANSACTION if we've accessed a temporary table + * in this transaction. Having the prepared xact hold locks on another + * backend's temp table seems a bad idea --- for instance it would prevent + * the backend from exiting. There are other problems too, such as how + * to clean up the source backend's local buffers and ON COMMIT state + * if the prepared xact includes a DROP of a temp table. + * + * We must check this after executing any ON COMMIT actions, because + * they might still access a temp relation. + * + * XXX In principle this could be relaxed to allow some useful special + * cases, such as a temp table created and dropped all within the + * transaction. That seems to require much more bookkeeping though. + */ + if (MyXactAccessedTempRel) + ereport(ERROR, + (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), + errmsg("cannot PREPARE a transaction that has operated on temporary tables"))); + /* Prevent cancel/die interrupt while cleaning up */ HOLD_INTERRUPTS(); diff --git a/src/backend/storage/lmgr/lmgr.c b/src/backend/storage/lmgr/lmgr.c index 4a4c0990ad2..25cd40cd1bd 100644 --- a/src/backend/storage/lmgr/lmgr.c +++ b/src/backend/storage/lmgr/lmgr.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/lmgr/lmgr.c,v 1.89 2006/10/04 00:29:57 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/storage/lmgr/lmgr.c,v 1.89.2.1 2008/03/04 19:54:23 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -19,12 +19,10 @@ #include "access/transam.h" #include "access/xact.h" #include "catalog/catalog.h" -#include "catalog/namespace.h" #include "miscadmin.h" #include "storage/lmgr.h" #include "storage/procarray.h" #include "utils/inval.h" -#include "utils/lsyscache.h" /* @@ -598,40 +596,3 @@ UnlockSharedObject(Oid classid, Oid objid, uint16 objsubid, LockRelease(&tag, lockmode, false); } - - -/* - * LockTagIsTemp - * Determine whether a locktag is for a lock on a temporary object - * - * We need this because 2PC cannot deal with temp objects - */ -bool -LockTagIsTemp(const LOCKTAG *tag) -{ - switch (tag->locktag_type) - { - case LOCKTAG_RELATION: - case LOCKTAG_RELATION_EXTEND: - case LOCKTAG_PAGE: - case LOCKTAG_TUPLE: - /* check for lock on a temp relation */ - /* field1 is dboid, field2 is reloid for all of these */ - if ((Oid) tag->locktag_field1 == InvalidOid) - return false; /* shared, so not temp */ - if (isTempNamespace(get_rel_namespace((Oid) tag->locktag_field2))) - return true; - break; - case LOCKTAG_TRANSACTION: - /* there are no temp transactions */ - break; - case LOCKTAG_OBJECT: - /* there are currently no non-table temp objects */ - break; - case LOCKTAG_USERLOCK: - case LOCKTAG_ADVISORY: - /* assume these aren't temp */ - break; - } - return false; /* default case */ -} diff --git a/src/backend/storage/lmgr/lock.c b/src/backend/storage/lmgr/lock.c index a8d2ad01d9f..a49002e4d07 100644 --- a/src/backend/storage/lmgr/lock.c +++ b/src/backend/storage/lmgr/lock.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.174.2.1 2008/02/02 22:26:23 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.174.2.2 2008/03/04 19:54:23 tgl Exp $ * * NOTES * A lock table is a shared memory hash table. When @@ -37,7 +37,6 @@ #include "access/twophase_rmgr.h" #include "miscadmin.h" #include "pgstat.h" -#include "storage/lmgr.h" #include "utils/memutils.h" #include "utils/ps_status.h" #include "utils/resowner.h" @@ -1849,12 +1848,6 @@ AtPrepare_Locks(void) elog(ERROR, "cannot PREPARE when session locks exist"); } - /* Can't handle it if the lock is on a temporary object */ - if (LockTagIsTemp(&locallock->tag.lock)) - ereport(ERROR, - (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), - errmsg("cannot PREPARE a transaction that has operated on temporary tables"))); - /* * Create a 2PC record. */ diff --git a/src/include/access/xact.h b/src/include/access/xact.h index 5b4411d77be..ede75c6518a 100644 --- a/src/include/access/xact.h +++ b/src/include/access/xact.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/xact.h,v 1.83 2006/07/11 18:26:11 momjian Exp $ + * $PostgreSQL: pgsql/src/include/access/xact.h,v 1.83.2.1 2008/03/04 19:54:23 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -41,6 +41,9 @@ extern int XactIsoLevel; extern bool DefaultXactReadOnly; extern bool XactReadOnly; +/* Kluge for 2PC support */ +extern bool MyXactAccessedTempRel; + /* * start- and end-of-transaction callbacks for dynamically loaded modules */ diff --git a/src/include/storage/lmgr.h b/src/include/storage/lmgr.h index ea7a1bf948f..832f3e201bc 100644 --- a/src/include/storage/lmgr.h +++ b/src/include/storage/lmgr.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/storage/lmgr.h,v 1.56 2006/08/18 16:09:13 tgl Exp $ + * $PostgreSQL: pgsql/src/include/storage/lmgr.h,v 1.56.2.1 2008/03/04 19:54:23 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -66,7 +66,4 @@ extern void LockSharedObject(Oid classid, Oid objid, uint16 objsubid, extern void UnlockSharedObject(Oid classid, Oid objid, uint16 objsubid, LOCKMODE lockmode); -/* Knowledge about which locktags describe temp objects */ -extern bool LockTagIsTemp(const LOCKTAG *tag); - #endif /* LMGR_H */