/* * Pre-commit processing for portals. * * Any holdable cursors created in this transaction need to be converted to * materialized form, since we are going to close down the executor and * release locks. Other portals are not touched yet. * * Returns TRUE if any holdable cursors were processed, FALSE if not. */ bool CommitHoldablePortals(void) { bool result = false; HASH_SEQ_STATUS status; PortalHashEnt *hentry; hash_seq_init(&status, PortalHashTable); while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL) { Portal portal = hentry->portal; /* Is it a holdable portal created in the current xact? */ if ((portal->cursorOptions & CURSOR_OPT_HOLD) && portal->createSubid != InvalidSubTransactionId && portal->status == PORTAL_READY) { /* * We are exiting the transaction that created a holdable * cursor. Instead of dropping the portal, prepare it for * access by later transactions. * * Note that PersistHoldablePortal() must release all resources * used by the portal that are local to the creating * transaction. */ PortalCreateHoldStore(portal); PersistHoldablePortal(portal); /* * Any resources belonging to the portal will be released in * the upcoming transaction-wide cleanup; the portal will no * longer have its own resources. */ portal->resowner = NULL; /* * Having successfully exported the holdable cursor, mark it * as not belonging to this transaction. */ portal->createSubid = InvalidSubTransactionId; result = true; } } return result; }
/* * Pre-commit processing for portals. * * Any holdable cursors created in this transaction need to be converted to * materialized form, since we are going to close down the executor and * release locks. Remove all other portals created in this transaction. * Portals remaining from prior transactions should be left untouched. * * XXX This assumes that portals can be deleted in a random order, ie, * no portal has a reference to any other (at least not one that will be * exercised during deletion). I think this is okay at the moment, but * we've had bugs of that ilk in the past. Keep a close eye on cursor * references... */ void AtCommit_Portals(void) { HASH_SEQ_STATUS status; PortalHashEnt *hentry; TransactionId xact = GetCurrentTransactionId(); hash_seq_init(&status, PortalHashTable); while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL) { Portal portal = hentry->portal; /* * Do not touch active portals --- this can only happen in the * case of a multi-transaction utility command, such as VACUUM. */ if (portal->portalActive) continue; if (portal->cursorOptions & CURSOR_OPT_HOLD) { /* * Do nothing to cursors held over from a previous * transaction. */ if (portal->createXact != xact) continue; /* * We are exiting the transaction that created a holdable * cursor. Instead of dropping the portal, prepare it for * access by later transactions. * * Note that PersistHoldablePortal() must release all resources * used by the portal that are local to the creating * transaction. */ PortalCreateHoldStore(portal); PersistHoldablePortal(portal); } else { /* Zap all non-holdable portals */ PortalDrop(portal, false); } } }