Skip to content

Commit aba691b

Browse files
committed
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.
1 parent b0e3dd7 commit aba691b

File tree

2 files changed

+19
-5
lines changed

2 files changed

+19
-5
lines changed

doc/src/sgml/ref/rollback_to.sgml

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/ref/rollback_to.sgml,v 1.5 2004/11/27 21:27:07 petere Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/ref/rollback_to.sgml,v 1.6 2005/01/26 23:20:20 tgl Exp $
33
PostgreSQL documentation
44
-->
55

@@ -74,11 +74,13 @@ ROLLBACK [ WORK | TRANSACTION ] TO [ SAVEPOINT ] <replaceable>savepoint_name</re
7474

7575
<para>
7676
Cursors have somewhat non-transactional behavior with respect to
77-
savepoints. Any cursor that is opened inside the savepoint is not closed
78-
when the savepoint is rolled back. If a cursor is affected by a
77+
savepoints. Any cursor that is opened inside a savepoint will be closed
78+
when the savepoint is rolled back. If a previously opened cursor is
79+
affected by a
7980
<command>FETCH</> command inside a savepoint that is later rolled
8081
back, the cursor position remains at the position that <command>FETCH</>
8182
left it pointing to (that is, <command>FETCH</> is not rolled back).
83+
Closing a cursor is not undone by rolling back, either.
8284
A cursor whose execution causes a transaction to abort is put in a
8385
can't-execute state, so while the transaction can be restored using
8486
<command>ROLLBACK TO SAVEPOINT</>, the cursor can no longer be used.

src/backend/utils/mmgr/portalmem.c

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
* Portions Copyright (c) 1994, Regents of the University of California
1313
*
1414
* IDENTIFICATION
15-
* $PostgreSQL: pgsql/src/backend/utils/mmgr/portalmem.c,v 1.76 2004/12/31 22:02:48 pgsql Exp $
15+
* $PostgreSQL: pgsql/src/backend/utils/mmgr/portalmem.c,v 1.77 2005/01/26 23:20:21 tgl Exp $
1616
*
1717
*-------------------------------------------------------------------------
1818
*/
@@ -601,9 +601,11 @@ AtSubCommit_Portals(SubTransactionId mySubid,
601601
/*
602602
* Subtransaction abort handling for portals.
603603
*
604-
* Deactivate failed portals created during the failed subtransaction.
604+
* Deactivate portals created during the failed subtransaction.
605605
* Note that per AtSubCommit_Portals, this will catch portals created
606606
* in descendants of the subtransaction too.
607+
*
608+
* We don't destroy any portals here; that's done in AtSubCleanup_Portals.
607609
*/
608610
void
609611
AtSubAbort_Portals(SubTransactionId mySubid,
@@ -628,21 +630,31 @@ AtSubAbort_Portals(SubTransactionId mySubid,
628630
* will go FAILED if the underlying cursor fails. (Note we do NOT
629631
* want to do this to upper-level portals, since they may be able
630632
* to continue.)
633+
*
634+
* This is only needed to dodge the sanity check in PortalDrop.
631635
*/
632636
if (portal->status == PORTAL_ACTIVE)
633637
portal->status = PORTAL_FAILED;
634638

635639
/*
636640
* If the portal is READY then allow it to survive into the parent
637641
* transaction; otherwise shut it down.
642+
*
643+
* Currently, we can't actually support that because the portal's
644+
* query might refer to objects created or changed in the failed
645+
* subtransaction, leading to crashes if execution is resumed.
646+
* So, even READY portals are deleted. It would be nice to detect
647+
* whether the query actually depends on any such object, instead.
638648
*/
649+
#ifdef NOT_USED
639650
if (portal->status == PORTAL_READY)
640651
{
641652
portal->createSubid = parentSubid;
642653
if (portal->resowner)
643654
ResourceOwnerNewParent(portal->resowner, parentXactOwner);
644655
}
645656
else
657+
#endif
646658
{
647659
/* let portalcmds.c clean up the state it knows about */
648660
if (PointerIsValid(portal->cleanup))

0 commit comments

Comments
 (0)