*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.249 2008/01/30 18:35:55 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.250 2008/03/04 19:54:06 tgl Exp $
*
*
* INTERFACE ROUTINES
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;
+
pgstat_initstats(r);
return r;
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;
+
pgstat_initstats(r);
return r;
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;
+
pgstat_initstats(r);
return r;
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.257 2008/01/15 18:56:59 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.258 2008/03/04 19:54:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
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
XactIsoLevel = DefaultXactIsoLevel;
XactReadOnly = DefaultXactReadOnly;
forceSyncCommit = false;
+ MyXactAccessedTempRel = false;
/*
* reinitialize within-transaction counters
/* 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();
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/lmgr/lmgr.c,v 1.96 2008/01/08 23:18:50 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/lmgr/lmgr.c,v 1.97 2008/03/04 19:54:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
#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"
/*
}
-/*
- * 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 ((LockTagType) 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 (isTempOrToastNamespace(get_rel_namespace((Oid) tag->locktag_field2)))
- return true;
- break;
- case LOCKTAG_TRANSACTION:
- case LOCKTAG_VIRTUALTRANSACTION:
- /* 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 */
-}
-
-
/*
* Append a description of a lockable object to buf.
*
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.181 2008/02/02 22:26:17 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.182 2008/03/04 19:54:06 tgl Exp $
*
* NOTES
* A lock table is a shared memory hash table. When
#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"
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.
*/
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/access/xact.h,v 1.93 2008/01/01 19:45:56 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/access/xact.h,v 1.94 2008/03/04 19:54:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
/* Asynchronous commits */
extern bool XactSyncCommit;
+/* Kluge for 2PC support */
+extern bool MyXactAccessedTempRel;
+
/*
* start- and end-of-transaction callbacks for dynamically loaded modules
*/
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/storage/lmgr.h,v 1.60 2008/01/01 19:45:59 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/storage/lmgr.h,v 1.61 2008/03/04 19:54:06 tgl Exp $
*
*-------------------------------------------------------------------------
*/
extern void UnlockSharedObject(Oid classid, Oid objid, uint16 objsubid,
LOCKMODE lockmode);
-/* Knowledge about which locktags describe temp objects */
-extern bool LockTagIsTemp(const LOCKTAG *tag);
-
/* Describe a locktag for error messages */
extern void DescribeLockTag(StringInfo buf, const LOCKTAG *tag);