]> granicus.if.org Git - postgresql/commitdiff
Close all cursors created during a failed subtransaction. This is needed
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 26 Jan 2005 23:20:21 +0000 (23:20 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 26 Jan 2005 23:20:21 +0000 (23:20 +0000)
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.

doc/src/sgml/ref/rollback_to.sgml
src/backend/utils/mmgr/portalmem.c

index 0b87dc1a6bb3ca01fd995f712f900665376294d8..8e3aeff643961a951e035f11c504787280140df5 100644 (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.
index eb6635f6e1a25c478472dc6aa8f6ccfbf1817083..95e1972fe30012ed3c61b77fc1a2760adfa6f441 100644 (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))