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 + -- 235395b90909301035v7228ce63q392931f15aa74b31@xxxxxxxxxxxxxx + 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 + -- 235395b90909301035v7228ce63q392931f15aa74b31@xxxxxxxxxxxxxx + 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@xxxxxxxxxxxxxx) To make changes to your subscription: http://www.postgresql.org/mailpref/pgsql-general