Heikki Linnakangas wrote:
Attached is a simple patch to fix that by disallowing CREATE+DROP+PREPARE TRANSACTION more reliably.

That patch was missing changes to header files. New patch attached.

--
  Heikki Linnakangas
  EnterpriseDB   http://www.enterprisedb.com
Index: src/backend/access/transam/twophase.c
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/backend/access/transam/twophase.c,v
retrieving revision 1.39
diff -c -r1.39 twophase.c
*** src/backend/access/transam/twophase.c	1 Jan 2008 19:45:48 -0000	1.39
--- src/backend/access/transam/twophase.c	29 Feb 2008 13:05:24 -0000
***************
*** 793,798 ****
--- 793,799 ----
  	TransactionId *children;
  	RelFileNode *commitrels;
  	RelFileNode *abortrels;
+ 	bool haveTempCommit, haveTempAbort;
  
  	/* Initialize linked list */
  	records.head = palloc0(sizeof(XLogRecData));
***************
*** 815,824 ****
  	hdr.prepared_at = gxact->prepared_at;
  	hdr.owner = gxact->owner;
  	hdr.nsubxacts = xactGetCommittedChildren(&children);
! 	hdr.ncommitrels = smgrGetPendingDeletes(true, &commitrels, NULL);
! 	hdr.nabortrels = smgrGetPendingDeletes(false, &abortrels, NULL);
  	StrNCpy(hdr.gid, gxact->gid, GIDSIZE);
  
  	save_state_data(&hdr, sizeof(TwoPhaseFileHeader));
  
  	/* Add the additional info about subxacts and deletable files */
--- 816,830 ----
  	hdr.prepared_at = gxact->prepared_at;
  	hdr.owner = gxact->owner;
  	hdr.nsubxacts = xactGetCommittedChildren(&children);
! 	hdr.ncommitrels = smgrGetPendingDeletes(true, &commitrels, NULL, &haveTempCommit);
! 	hdr.nabortrels = smgrGetPendingDeletes(false, &abortrels, NULL, &haveTempAbort);
  	StrNCpy(hdr.gid, gxact->gid, GIDSIZE);
  
+ 	if (haveTempCommit || haveTempAbort)
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ 				 errmsg("cannot PREPARE a transaction that has operated on temporary tables")));
+ 
  	save_state_data(&hdr, sizeof(TwoPhaseFileHeader));
  
  	/* Add the additional info about subxacts and deletable files */
Index: src/backend/access/transam/xact.c
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/backend/access/transam/xact.c,v
retrieving revision 1.257
diff -c -r1.257 xact.c
*** src/backend/access/transam/xact.c	15 Jan 2008 18:56:59 -0000	1.257
--- src/backend/access/transam/xact.c	29 Feb 2008 13:05:24 -0000
***************
*** 802,808 ****
  	TransactionId *children;
  
  	/* Get data needed for commit record */
! 	nrels = smgrGetPendingDeletes(true, &rels, &haveNonTemp);
  	nchildren = xactGetCommittedChildren(&children);
  
  	/*
--- 802,808 ----
  	TransactionId *children;
  
  	/* Get data needed for commit record */
! 	nrels = smgrGetPendingDeletes(true, &rels, &haveNonTemp, NULL);
  	nchildren = xactGetCommittedChildren(&children);
  
  	/*
***************
*** 1174,1180 ****
  			 xid);
  
  	/* Fetch the data we need for the abort record */
! 	nrels = smgrGetPendingDeletes(false, &rels, NULL);
  	nchildren = xactGetCommittedChildren(&children);
  
  	/* XXX do we really need a critical section here? */
--- 1174,1180 ----
  			 xid);
  
  	/* Fetch the data we need for the abort record */
! 	nrels = smgrGetPendingDeletes(false, &rels, NULL, NULL);
  	nchildren = xactGetCommittedChildren(&children);
  
  	/* XXX do we really need a critical section here? */
Index: src/backend/storage/smgr/smgr.c
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/backend/storage/smgr/smgr.c,v
retrieving revision 1.109
diff -c -r1.109 smgr.c
*** src/backend/storage/smgr/smgr.c	1 Jan 2008 19:45:52 -0000	1.109
--- src/backend/storage/smgr/smgr.c	29 Feb 2008 13:05:24 -0000
***************
*** 678,689 ****
   *
   * If haveNonTemp isn't NULL, the bool it points to gets set to true if
   * there is any non-temp table pending to be deleted; false if not.
   *
   * Note that the list does not include anything scheduled for termination
   * by upper-level transactions.
   */
  int
! smgrGetPendingDeletes(bool forCommit, RelFileNode **ptr, bool *haveNonTemp)
  {
  	int			nestLevel = GetCurrentTransactionNestLevel();
  	int			nrels;
--- 678,692 ----
   *
   * If haveNonTemp isn't NULL, the bool it points to gets set to true if
   * there is any non-temp table pending to be deleted; false if not.
+  * haveTemp is similar, but gets set if there is any temp table deletions
+  * pending.
   *
   * Note that the list does not include anything scheduled for termination
   * by upper-level transactions.
   */
  int
! smgrGetPendingDeletes(bool forCommit, RelFileNode **ptr, 
! 					  bool *haveNonTemp, bool *haveTemp)
  {
  	int			nestLevel = GetCurrentTransactionNestLevel();
  	int			nrels;
***************
*** 693,698 ****
--- 696,703 ----
  	nrels = 0;
  	if (haveNonTemp)
  		*haveNonTemp = false;
+ 	if (haveTemp)
+ 		*haveTemp = false;
  	for (pending = pendingDeletes; pending != NULL; pending = pending->next)
  	{
  		if (pending->nestLevel >= nestLevel && pending->atCommit == forCommit)
***************
*** 711,716 ****
--- 716,723 ----
  			*rptr++ = pending->relnode;
  		if (haveNonTemp && !pending->isTemp)
  			*haveNonTemp = true;
+ 		if (haveTemp && pending->isTemp)
+ 			*haveTemp = true;
  	}
  	return nrels;
  }
Index: src/include/storage/smgr.h
===================================================================
RCS file: /home/hlinnaka/pgcvsrepository/pgsql/src/include/storage/smgr.h,v
retrieving revision 1.62
diff -c -r1.62 smgr.h
*** src/include/storage/smgr.h	1 Jan 2008 19:45:59 -0000	1.62
--- src/include/storage/smgr.h	29 Feb 2008 09:47:24 -0000
***************
*** 77,83 ****
  extern void smgrimmedsync(SMgrRelation reln);
  extern void smgrDoPendingDeletes(bool isCommit);
  extern int smgrGetPendingDeletes(bool forCommit, RelFileNode **ptr,
! 					  bool *haveNonTemp);
  extern void AtSubCommit_smgr(void);
  extern void AtSubAbort_smgr(void);
  extern void PostPrepare_smgr(void);
--- 77,83 ----
  extern void smgrimmedsync(SMgrRelation reln);
  extern void smgrDoPendingDeletes(bool isCommit);
  extern int smgrGetPendingDeletes(bool forCommit, RelFileNode **ptr,
! 					  bool *haveNonTemp, bool *haveTemp);
  extern void AtSubCommit_smgr(void);
  extern void AtSubAbort_smgr(void);
  extern void PostPrepare_smgr(void);
---------------------------(end of broadcast)---------------------------
TIP 3: Have you checked our extensive FAQ?

               http://www.postgresql.org/docs/faq

Reply via email to