diff options
author | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2009-10-02 17:58:21 +0000 |
---|---|---|
committer | Alvaro Herrera <alvherre@alvh.no-ip.org> | 2009-10-02 17:58:21 +0000 |
commit | ae35363dced47a99178b4a4129e3ea1f990b829c (patch) | |
tree | c0a113330d1b9039764b82a1e59820c420b6fe7a /src/backend | |
parent | d4bd8423c9939a30f0f29e70745917e4635b4973 (diff) | |
download | postgresql-ae35363dced47a99178b4a4129e3ea1f990b829c.tar.gz postgresql-ae35363dced47a99178b4a4129e3ea1f990b829c.zip |
Ensure that a cursor has an immutable snapshot throughout its lifespan.
The old coding was using a regular snapshot, referenced elsewhere, that was
subject to having its command counter updated. Fix by creating a private copy
of the snapshot exclusively for the cursor.
Backpatch to 8.4, which is when the bug was introduced during the snapshot
management rewrite.
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/commands/portalcmds.c | 13 | ||||
-rw-r--r-- | src/backend/executor/spi.c | 7 | ||||
-rw-r--r-- | src/backend/utils/time/snapmgr.c | 5 |
3 files changed, 15 insertions, 10 deletions
diff --git a/src/backend/commands/portalcmds.c b/src/backend/commands/portalcmds.c index 17192341739..d31fde65b6b 100644 --- a/src/backend/commands/portalcmds.c +++ b/src/backend/commands/portalcmds.c @@ -14,7 +14,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/commands/portalcmds.c,v 1.79 2009/06/11 14:48:56 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/commands/portalcmds.c,v 1.79.2.1 2009/10/02 17:58:21 alvherre Exp $ * *------------------------------------------------------------------------- */ @@ -47,6 +47,7 @@ PerformCursorOpen(PlannedStmt *stmt, ParamListInfo params, 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,9 +120,17 @@ PerformCursorOpen(PlannedStmt *stmt, ParamListInfo params, } /* + * 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, GetActiveSnapshot()); + PortalStart(portal, params, snapshot); Assert(portal->strategy == PORTAL_ONE_SELECT); diff --git a/src/backend/executor/spi.c b/src/backend/executor/spi.c index 40f43ee011b..3cffc2ad72b 100644 --- a/src/backend/executor/spi.c +++ b/src/backend/executor/spi.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.208 2009/06/11 14:48:57 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/executor/spi.c,v 1.208.2.1 2009/10/02 17:58:21 alvherre Exp $ * *------------------------------------------------------------------------- */ @@ -1211,10 +1211,7 @@ SPI_cursor_open_internal(const char *name, SPIPlanPtr plan, } } - /* - * Set up the snapshot to use. (PortalStart will do PushActiveSnapshot, - * so we skip that here.) - */ + /* Set up the snapshot to use. */ if (read_only) snapshot = GetActiveSnapshot(); else diff --git a/src/backend/utils/time/snapmgr.c b/src/backend/utils/time/snapmgr.c index 73d597d7b37..12ca81616d1 100644 --- a/src/backend/utils/time/snapmgr.c +++ b/src/backend/utils/time/snapmgr.c @@ -19,7 +19,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/time/snapmgr.c,v 1.10 2009/06/11 14:49:06 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/utils/time/snapmgr.c,v 1.10.2.1 2009/10/02 17:58:21 alvherre Exp $ * *------------------------------------------------------------------------- */ @@ -104,7 +104,6 @@ bool FirstSnapshotSet = false; static bool registered_serializable = false; -static Snapshot CopySnapshot(Snapshot snapshot); static void FreeSnapshot(Snapshot snapshot); static void SnapshotResetXmin(void); @@ -192,7 +191,7 @@ SnapshotSetCommandId(CommandId curcid) * The copy is palloc'd in TopTransactionContext and has initial refcounts set * to 0. The returned snapshot has the copied flag set. */ -static Snapshot +Snapshot CopySnapshot(Snapshot snapshot) { Snapshot newsnap; |