Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 7d6e6e2

Browse files
committed
Fix PREPARE TRANSACTION to reject the case where the transaction has dropped a
temporary table; we can't support that because there's no way to clean up the source backend's internal state if the eventual COMMIT PREPARED is done by another backend. This was checked correctly in 8.1 but I broke it in 8.2 :-(. Patch by Heikki Linnakangas, original trouble report by John Smith.
1 parent 9b8a93b commit 7d6e6e2

File tree

6 files changed

+49
-56
lines changed

6 files changed

+49
-56
lines changed

src/backend/access/heap/heapam.c

+13-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.249 2008/01/30 18:35:55 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.250 2008/03/04 19:54:06 tgl Exp $
1212
*
1313
*
1414
* INTERFACE ROUTINES
@@ -868,6 +868,10 @@ relation_open(Oid relationId, LOCKMODE lockmode)
868868
if (!RelationIsValid(r))
869869
elog(ERROR, "could not open relation with OID %u", relationId);
870870

871+
/* Make note that we've accessed a temporary relation */
872+
if (r->rd_istemp)
873+
MyXactAccessedTempRel = true;
874+
871875
pgstat_initstats(r);
872876

873877
return r;
@@ -912,6 +916,10 @@ try_relation_open(Oid relationId, LOCKMODE lockmode)
912916
if (!RelationIsValid(r))
913917
elog(ERROR, "could not open relation with OID %u", relationId);
914918

919+
/* Make note that we've accessed a temporary relation */
920+
if (r->rd_istemp)
921+
MyXactAccessedTempRel = true;
922+
915923
pgstat_initstats(r);
916924

917925
return r;
@@ -958,6 +966,10 @@ relation_open_nowait(Oid relationId, LOCKMODE lockmode)
958966
if (!RelationIsValid(r))
959967
elog(ERROR, "could not open relation with OID %u", relationId);
960968

969+
/* Make note that we've accessed a temporary relation */
970+
if (r->rd_istemp)
971+
MyXactAccessedTempRel = true;
972+
961973
pgstat_initstats(r);
962974

963975
return r;

src/backend/access/transam/xact.c

+29-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
*
1111
*
1212
* IDENTIFICATION
13-
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.257 2008/01/15 18:56:59 tgl Exp $
13+
* $PostgreSQL: pgsql/src/backend/access/transam/xact.c,v 1.258 2008/03/04 19:54:06 tgl Exp $
1414
*
1515
*-------------------------------------------------------------------------
1616
*/
@@ -62,6 +62,13 @@ bool XactSyncCommit = true;
6262
int CommitDelay = 0; /* precommit delay in microseconds */
6363
int CommitSiblings = 5; /* # concurrent xacts needed to sleep */
6464

65+
/*
66+
* MyXactAccessedTempRel is set when a temporary relation is accessed.
67+
* We don't allow PREPARE TRANSACTION in that case. (This is global
68+
* so that it can be set from heapam.c.)
69+
*/
70+
bool MyXactAccessedTempRel = false;
71+
6572

6673
/*
6774
* transaction states - transaction state from server perspective
@@ -1445,6 +1452,7 @@ StartTransaction(void)
14451452
XactIsoLevel = DefaultXactIsoLevel;
14461453
XactReadOnly = DefaultXactReadOnly;
14471454
forceSyncCommit = false;
1455+
MyXactAccessedTempRel = false;
14481456

14491457
/*
14501458
* reinitialize within-transaction counters
@@ -1770,6 +1778,26 @@ PrepareTransaction(void)
17701778

17711779
/* NOTIFY and flatfiles will be handled below */
17721780

1781+
/*
1782+
* Don't allow PREPARE TRANSACTION if we've accessed a temporary table
1783+
* in this transaction. Having the prepared xact hold locks on another
1784+
* backend's temp table seems a bad idea --- for instance it would prevent
1785+
* the backend from exiting. There are other problems too, such as how
1786+
* to clean up the source backend's local buffers and ON COMMIT state
1787+
* if the prepared xact includes a DROP of a temp table.
1788+
*
1789+
* We must check this after executing any ON COMMIT actions, because
1790+
* they might still access a temp relation.
1791+
*
1792+
* XXX In principle this could be relaxed to allow some useful special
1793+
* cases, such as a temp table created and dropped all within the
1794+
* transaction. That seems to require much more bookkeeping though.
1795+
*/
1796+
if (MyXactAccessedTempRel)
1797+
ereport(ERROR,
1798+
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1799+
errmsg("cannot PREPARE a transaction that has operated on temporary tables")));
1800+
17731801
/* Prevent cancel/die interrupt while cleaning up */
17741802
HOLD_INTERRUPTS();
17751803

src/backend/storage/lmgr/lmgr.c

+1-41
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lmgr.c,v 1.96 2008/01/08 23:18:50 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lmgr.c,v 1.97 2008/03/04 19:54:06 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -19,12 +19,10 @@
1919
#include "access/transam.h"
2020
#include "access/xact.h"
2121
#include "catalog/catalog.h"
22-
#include "catalog/namespace.h"
2322
#include "miscadmin.h"
2423
#include "storage/lmgr.h"
2524
#include "storage/procarray.h"
2625
#include "utils/inval.h"
27-
#include "utils/lsyscache.h"
2826

2927

3028
/*
@@ -663,44 +661,6 @@ UnlockSharedObject(Oid classid, Oid objid, uint16 objsubid,
663661
}
664662

665663

666-
/*
667-
* LockTagIsTemp
668-
* Determine whether a locktag is for a lock on a temporary object
669-
*
670-
* We need this because 2PC cannot deal with temp objects
671-
*/
672-
bool
673-
LockTagIsTemp(const LOCKTAG *tag)
674-
{
675-
switch ((LockTagType) tag->locktag_type)
676-
{
677-
case LOCKTAG_RELATION:
678-
case LOCKTAG_RELATION_EXTEND:
679-
case LOCKTAG_PAGE:
680-
case LOCKTAG_TUPLE:
681-
/* check for lock on a temp relation */
682-
/* field1 is dboid, field2 is reloid for all of these */
683-
if ((Oid) tag->locktag_field1 == InvalidOid)
684-
return false; /* shared, so not temp */
685-
if (isTempOrToastNamespace(get_rel_namespace((Oid) tag->locktag_field2)))
686-
return true;
687-
break;
688-
case LOCKTAG_TRANSACTION:
689-
case LOCKTAG_VIRTUALTRANSACTION:
690-
/* there are no temp transactions */
691-
break;
692-
case LOCKTAG_OBJECT:
693-
/* there are currently no non-table temp objects */
694-
break;
695-
case LOCKTAG_USERLOCK:
696-
case LOCKTAG_ADVISORY:
697-
/* assume these aren't temp */
698-
break;
699-
}
700-
return false; /* default case */
701-
}
702-
703-
704664
/*
705665
* Append a description of a lockable object to buf.
706666
*

src/backend/storage/lmgr/lock.c

+1-8
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.181 2008/02/02 22:26:17 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/storage/lmgr/lock.c,v 1.182 2008/03/04 19:54:06 tgl Exp $
1212
*
1313
* NOTES
1414
* A lock table is a shared memory hash table. When
@@ -37,7 +37,6 @@
3737
#include "access/twophase_rmgr.h"
3838
#include "miscadmin.h"
3939
#include "pgstat.h"
40-
#include "storage/lmgr.h"
4140
#include "utils/memutils.h"
4241
#include "utils/ps_status.h"
4342
#include "utils/resowner.h"
@@ -1871,12 +1870,6 @@ AtPrepare_Locks(void)
18711870
elog(ERROR, "cannot PREPARE when session locks exist");
18721871
}
18731872

1874-
/* Can't handle it if the lock is on a temporary object */
1875-
if (LockTagIsTemp(&locallock->tag.lock))
1876-
ereport(ERROR,
1877-
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1878-
errmsg("cannot PREPARE a transaction that has operated on temporary tables")));
1879-
18801873
/*
18811874
* Create a 2PC record.
18821875
*/

src/include/access/xact.h

+4-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/access/xact.h,v 1.93 2008/01/01 19:45:56 momjian Exp $
10+
* $PostgreSQL: pgsql/src/include/access/xact.h,v 1.94 2008/03/04 19:54:06 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -44,6 +44,9 @@ extern bool XactReadOnly;
4444
/* Asynchronous commits */
4545
extern bool XactSyncCommit;
4646

47+
/* Kluge for 2PC support */
48+
extern bool MyXactAccessedTempRel;
49+
4750
/*
4851
* start- and end-of-transaction callbacks for dynamically loaded modules
4952
*/

src/include/storage/lmgr.h

+1-4
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/storage/lmgr.h,v 1.60 2008/01/01 19:45:59 momjian Exp $
10+
* $PostgreSQL: pgsql/src/include/storage/lmgr.h,v 1.61 2008/03/04 19:54:06 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -72,9 +72,6 @@ extern void LockSharedObject(Oid classid, Oid objid, uint16 objsubid,
7272
extern void UnlockSharedObject(Oid classid, Oid objid, uint16 objsubid,
7373
LOCKMODE lockmode);
7474

75-
/* Knowledge about which locktags describe temp objects */
76-
extern bool LockTagIsTemp(const LOCKTAG *tag);
77-
7875
/* Describe a locktag for error messages */
7976
extern void DescribeLockTag(StringInfo buf, const LOCKTAG *tag);
8077

0 commit comments

Comments
 (0)