This one really works and includes a basic test case.  You were right
that the extra Register was bogus :-(  I had to expose CopySnapshot,
which I still don't like but ...  (I could have added an extra
Unregister somewhere during portal close, but it would have meant making
everything messier).

-- 
Alvaro Herrera                                http://www.CommandPrompt.com/
PostgreSQL Replication, Consulting, Custom Development, 24x7 support
*** src/backend/commands/portalcmds.c	11 Jun 2009 14:48:56 -0000	1.79
--- src/backend/commands/portalcmds.c	1 Oct 2009 23:24:33 -0000
***************
*** 47,52 ****
--- 47,53 ----
  	DeclareCursorStmt *cstmt = (DeclareCursorStmt *) stmt->utilityStmt;
  	Portal		portal;
  	MemoryContext oldContext;
+ 	Snapshot	snapshot;
  
  	if (cstmt == NULL || !IsA(cstmt, DeclareCursorStmt))
  		elog(ERROR, "PerformCursorOpen called for non-cursor query");
***************
*** 119,127 ****
  	}
  
  	/*
  	 * Start execution, inserting parameters if any.
  	 */
! 	PortalStart(portal, params, GetActiveSnapshot());
  
  	Assert(portal->strategy == PORTAL_ONE_SELECT);
  
--- 120,136 ----
  	}
  
  	/*
+ 	 * Set up snapshot for portal.  Note that we need a fresh, independent copy
+ 	 * of the snapshot because we don't want it to be modified by future
+ 	 * CommandCounterIncrement calls.  We do not register it, because
+ 	 * portalmem.c will take care of that internally.
+ 	 */
+ 	snapshot = CopySnapshot(GetActiveSnapshot());
+ 
+ 	/*
  	 * Start execution, inserting parameters if any.
  	 */
! 	PortalStart(portal, params, snapshot);
  
  	Assert(portal->strategy == PORTAL_ONE_SELECT);
  
*** src/backend/executor/spi.c	11 Jun 2009 14:48:57 -0000	1.208
--- src/backend/executor/spi.c	1 Oct 2009 23:26:31 -0000
***************
*** 1211,1220 ****
  		}
  	}
  
! 	/*
! 	 * Set up the snapshot to use.	(PortalStart will do PushActiveSnapshot,
! 	 * so we skip that here.)
! 	 */
  	if (read_only)
  		snapshot = GetActiveSnapshot();
  	else
--- 1211,1217 ----
  		}
  	}
  
! 	/* Set up the snapshot to use. */
  	if (read_only)
  		snapshot = GetActiveSnapshot();
  	else
*** src/backend/utils/time/snapmgr.c	11 Jun 2009 14:49:06 -0000	1.10
--- src/backend/utils/time/snapmgr.c	1 Oct 2009 23:29:05 -0000
***************
*** 104,110 ****
  static bool registered_serializable = false;
  
  
- static Snapshot CopySnapshot(Snapshot snapshot);
  static void FreeSnapshot(Snapshot snapshot);
  static void SnapshotResetXmin(void);
  
--- 104,109 ----
***************
*** 192,198 ****
   * The copy is palloc'd in TopTransactionContext and has initial refcounts set
   * to 0.  The returned snapshot has the copied flag set.
   */
! static Snapshot
  CopySnapshot(Snapshot snapshot)
  {
  	Snapshot	newsnap;
--- 191,197 ----
   * The copy is palloc'd in TopTransactionContext and has initial refcounts set
   * to 0.  The returned snapshot has the copied flag set.
   */
! Snapshot
  CopySnapshot(Snapshot snapshot)
  {
  	Snapshot	newsnap;
*** src/include/utils/snapmgr.h	11 Jun 2009 14:49:13 -0000	1.5
--- src/include/utils/snapmgr.h	1 Oct 2009 23:28:19 -0000
***************
*** 26,31 ****
--- 26,32 ----
  extern Snapshot GetTransactionSnapshot(void);
  extern Snapshot GetLatestSnapshot(void);
  extern void SnapshotSetCommandId(CommandId curcid);
+ extern Snapshot CopySnapshot(Snapshot snapshot);
  
  extern void PushActiveSnapshot(Snapshot snapshot);
  extern void PushUpdatedSnapshot(Snapshot snapshot);
*** src/test/regress/expected/portals.out	27 Jan 2009 12:40:15 -0000	1.21
--- src/test/regress/expected/portals.out	1 Oct 2009 23:44:17 -0000
***************
*** 1242,1244 ****
--- 1242,1259 ----
  DELETE FROM ucview WHERE CURRENT OF c1; -- fail, views not supported
  ERROR:  WHERE CURRENT OF on a view is not implemented
  ROLLBACK;
+ -- Make sure snapshot management works okay, per bug report in
+ -- 235395b90909301035v7228ce63q392931f15aa74...@mail.gmail.com
+ BEGIN; 
+ SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 
+ CREATE TABLE cursor (a int); 
+ INSERT INTO cursor VALUES (1); 
+ DECLARE c1 NO SCROLL CURSOR FOR SELECT * FROM cursor FOR UPDATE; 
+ UPDATE cursor SET a = 2; 
+ FETCH ALL FROM c1; 
+  a 
+ ---
+ (0 rows)
+ 
+ COMMIT; 
+ DROP TABLE cursor;
*** src/test/regress/sql/portals.sql	16 Nov 2008 17:34:28 -0000	1.16
--- src/test/regress/sql/portals.sql	1 Oct 2009 23:39:08 -0000
***************
*** 458,460 ****
--- 458,472 ----
  FETCH FROM c1;
  DELETE FROM ucview WHERE CURRENT OF c1; -- fail, views not supported
  ROLLBACK;
+ 
+ -- Make sure snapshot management works okay, per bug report in
+ -- 235395b90909301035v7228ce63q392931f15aa74...@mail.gmail.com
+ BEGIN; 
+ SET TRANSACTION ISOLATION LEVEL SERIALIZABLE; 
+ CREATE TABLE cursor (a int); 
+ INSERT INTO cursor VALUES (1); 
+ DECLARE c1 NO SCROLL CURSOR FOR SELECT * FROM cursor FOR UPDATE; 
+ UPDATE cursor SET a = 2; 
+ FETCH ALL FROM c1; 
+ COMMIT; 
+ DROP TABLE cursor;
-- 
Sent via pgsql-general mailing list (pgsql-general@postgresql.org)
To make changes to your subscription:
http://www.postgresql.org/mailpref/pgsql-general

Reply via email to