Commit aba691b7 authored by Tom Lane's avatar Tom Lane

Close all cursors created during a failed subtransaction. This is needed

to avoid problems when a cursor depends on objects created or changed in
the same subtransaction.  We'd like to do better someday, but this seems
the only workable answer for 8.0.1.
parent b0e3dd7e
<!-- <!--
$PostgreSQL: pgsql/doc/src/sgml/ref/rollback_to.sgml,v 1.5 2004/11/27 21:27:07 petere Exp $ $PostgreSQL: pgsql/doc/src/sgml/ref/rollback_to.sgml,v 1.6 2005/01/26 23:20:20 tgl Exp $
PostgreSQL documentation PostgreSQL documentation
--> -->
...@@ -74,11 +74,13 @@ ROLLBACK [ WORK | TRANSACTION ] TO [ SAVEPOINT ] <replaceable>savepoint_name</re ...@@ -74,11 +74,13 @@ ROLLBACK [ WORK | TRANSACTION ] TO [ SAVEPOINT ] <replaceable>savepoint_name</re
<para> <para>
Cursors have somewhat non-transactional behavior with respect to Cursors have somewhat non-transactional behavior with respect to
savepoints. Any cursor that is opened inside the savepoint is not closed savepoints. Any cursor that is opened inside a savepoint will be closed
when the savepoint is rolled back. If a cursor is affected by a when the savepoint is rolled back. If a previously opened cursor is
affected by a
<command>FETCH</> command inside a savepoint that is later rolled <command>FETCH</> command inside a savepoint that is later rolled
back, the cursor position remains at the position that <command>FETCH</> back, the cursor position remains at the position that <command>FETCH</>
left it pointing to (that is, <command>FETCH</> is not rolled back). left it pointing to (that is, <command>FETCH</> is not rolled back).
Closing a cursor is not undone by rolling back, either.
A cursor whose execution causes a transaction to abort is put in a A cursor whose execution causes a transaction to abort is put in a
can't-execute state, so while the transaction can be restored using can't-execute state, so while the transaction can be restored using
<command>ROLLBACK TO SAVEPOINT</>, the cursor can no longer be used. <command>ROLLBACK TO SAVEPOINT</>, the cursor can no longer be used.
......
...@@ -12,7 +12,7 @@ ...@@ -12,7 +12,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/mmgr/portalmem.c,v 1.76 2004/12/31 22:02:48 pgsql Exp $ * $PostgreSQL: pgsql/src/backend/utils/mmgr/portalmem.c,v 1.77 2005/01/26 23:20:21 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -601,9 +601,11 @@ AtSubCommit_Portals(SubTransactionId mySubid, ...@@ -601,9 +601,11 @@ AtSubCommit_Portals(SubTransactionId mySubid,
/* /*
* Subtransaction abort handling for portals. * Subtransaction abort handling for portals.
* *
* Deactivate failed portals created during the failed subtransaction. * Deactivate portals created during the failed subtransaction.
* Note that per AtSubCommit_Portals, this will catch portals created * Note that per AtSubCommit_Portals, this will catch portals created
* in descendants of the subtransaction too. * in descendants of the subtransaction too.
*
* We don't destroy any portals here; that's done in AtSubCleanup_Portals.
*/ */
void void
AtSubAbort_Portals(SubTransactionId mySubid, AtSubAbort_Portals(SubTransactionId mySubid,
...@@ -628,6 +630,8 @@ AtSubAbort_Portals(SubTransactionId mySubid, ...@@ -628,6 +630,8 @@ AtSubAbort_Portals(SubTransactionId mySubid,
* will go FAILED if the underlying cursor fails. (Note we do NOT * will go FAILED if the underlying cursor fails. (Note we do NOT
* want to do this to upper-level portals, since they may be able * want to do this to upper-level portals, since they may be able
* to continue.) * to continue.)
*
* This is only needed to dodge the sanity check in PortalDrop.
*/ */
if (portal->status == PORTAL_ACTIVE) if (portal->status == PORTAL_ACTIVE)
portal->status = PORTAL_FAILED; portal->status = PORTAL_FAILED;
...@@ -635,7 +639,14 @@ AtSubAbort_Portals(SubTransactionId mySubid, ...@@ -635,7 +639,14 @@ AtSubAbort_Portals(SubTransactionId mySubid,
/* /*
* If the portal is READY then allow it to survive into the parent * If the portal is READY then allow it to survive into the parent
* transaction; otherwise shut it down. * transaction; otherwise shut it down.
*
* Currently, we can't actually support that because the portal's
* query might refer to objects created or changed in the failed
* subtransaction, leading to crashes if execution is resumed.
* So, even READY portals are deleted. It would be nice to detect
* whether the query actually depends on any such object, instead.
*/ */
#ifdef NOT_USED
if (portal->status == PORTAL_READY) if (portal->status == PORTAL_READY)
{ {
portal->createSubid = parentSubid; portal->createSubid = parentSubid;
...@@ -643,6 +654,7 @@ AtSubAbort_Portals(SubTransactionId mySubid, ...@@ -643,6 +654,7 @@ AtSubAbort_Portals(SubTransactionId mySubid,
ResourceOwnerNewParent(portal->resowner, parentXactOwner); ResourceOwnerNewParent(portal->resowner, parentXactOwner);
} }
else else
#endif
{ {
/* let portalcmds.c clean up the state it knows about */ /* let portalcmds.c clean up the state it knows about */
if (PointerIsValid(portal->cleanup)) if (PointerIsValid(portal->cleanup))
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment