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.
This commit is contained in:
Tom Lane 2005-01-26 23:20:21 +00:00
parent b0e3dd7e61
commit aba691b728
2 changed files with 19 additions and 5 deletions

View File

@ -1,5 +1,5 @@
<!--
$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
-->
@ -74,11 +74,13 @@ ROLLBACK [ WORK | TRANSACTION ] TO [ SAVEPOINT ] <replaceable>savepoint_name</re
<para>
Cursors have somewhat non-transactional behavior with respect to
savepoints. Any cursor that is opened inside the savepoint is not closed
when the savepoint is rolled back. If a cursor is affected by a
savepoints. Any cursor that is opened inside a savepoint will be closed
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
back, the cursor position remains at the position that <command>FETCH</>
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
can't-execute state, so while the transaction can be restored using
<command>ROLLBACK TO SAVEPOINT</>, the cursor can no longer be used.

View File

@ -12,7 +12,7 @@
* Portions Copyright (c) 1994, Regents of the University of California
*
* 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,
/*
* 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
* in descendants of the subtransaction too.
*
* We don't destroy any portals here; that's done in AtSubCleanup_Portals.
*/
void
AtSubAbort_Portals(SubTransactionId mySubid,
@ -628,6 +630,8 @@ AtSubAbort_Portals(SubTransactionId mySubid,
* 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
* to continue.)
*
* This is only needed to dodge the sanity check in PortalDrop.
*/
if (portal->status == PORTAL_ACTIVE)
portal->status = PORTAL_FAILED;
@ -635,7 +639,14 @@ AtSubAbort_Portals(SubTransactionId mySubid,
/*
* If the portal is READY then allow it to survive into the parent
* 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)
{
portal->createSubid = parentSubid;
@ -643,6 +654,7 @@ AtSubAbort_Portals(SubTransactionId mySubid,
ResourceOwnerNewParent(portal->resowner, parentXactOwner);
}
else
#endif
{
/* let portalcmds.c clean up the state it knows about */
if (PointerIsValid(portal->cleanup))