#include "datatype/timestamp.h"#include "executor/execdesc.h"#include "utils/plancache.h"#include "utils/resowner.h"

Go to the source code of this file.
| #define PortalGetHeapMemory | ( | portal | ) | ((portal)->heap) |
Definition at line 190 of file portal.h.
Referenced by AtAbort_Portals(), AtSubAbort_Portals(), exec_bind_message(), ExecuteQuery(), PerformCursorOpen(), PersistHoldablePortal(), PortalDrop(), PortalRun(), PortalRunFetch(), PortalRunMulti(), PortalRunUtility(), PortalSetResultFormat(), PortalStart(), and SPI_cursor_open_internal().
| #define PortalGetPrimaryStmt | ( | portal | ) | PortalListGetPrimaryStmt((portal)->stmts) |
Definition at line 191 of file portal.h.
Referenced by FetchPortalTargetList(), and PortalStart().
| #define PortalGetQueryDesc | ( | portal | ) | ((portal)->queryDesc) |
Definition at line 189 of file portal.h.
Referenced by DoPortalRewind(), execCurrentOf(), PersistHoldablePortal(), PortalCleanup(), and PortalRunSelect().
| #define PortalIsValid | ( | p | ) | PointerIsValid(p) |
Definition at line 184 of file portal.h.
Referenced by _SPI_cursor_operation(), CreatePortal(), exec_describe_portal_message(), exec_execute_message(), exec_simple_query(), execCurrentOf(), FetchStatementTargetList(), PerformPortalClose(), PerformPortalFetch(), PLy_cursor_close(), PLy_cursor_dealloc(), PLy_cursor_fetch(), PLy_cursor_iternext(), PortalCleanup(), PortalDefineQuery(), PortalDrop(), PortalRun(), PortalRunFetch(), PortalStart(), PostgresMain(), SPI_cursor_close(), UtilityReturnsTuples(), and UtilityTupleDescriptor().
| typedef struct PortalData* Portal |
| typedef struct PortalData PortalData |
| typedef enum PortalStatus PortalStatus |
| typedef enum PortalStrategy PortalStrategy |
| enum PortalStatus |
Definition at line 102 of file portal.h.
{
PORTAL_NEW, /* freshly created */
PORTAL_DEFINED, /* PortalDefineQuery done */
PORTAL_READY, /* PortalStart complete, can run it */
PORTAL_ACTIVE, /* portal is running (can't delete it) */
PORTAL_DONE, /* portal is finished (don't re-run it) */
PORTAL_FAILED /* portal got error (can't re-run it) */
} PortalStatus;
| enum PortalStrategy |
| PORTAL_ONE_SELECT | |
| PORTAL_ONE_RETURNING | |
| PORTAL_ONE_MOD_WITH | |
| PORTAL_UTIL_SELECT | |
| PORTAL_MULTI_QUERY |
Definition at line 88 of file portal.h.
{
PORTAL_ONE_SELECT,
PORTAL_ONE_RETURNING,
PORTAL_ONE_MOD_WITH,
PORTAL_UTIL_SELECT,
PORTAL_MULTI_QUERY
} PortalStrategy;
| void AtAbort_Portals | ( | void | ) |
Definition at line 736 of file portalmem.c.
References PortalData::cleanup, PortalData::createSubid, hash_seq_init(), hash_seq_search(), InvalidSubTransactionId, MarkPortalFailed(), MemoryContextDeleteChildren(), NULL, PointerIsValid, portalhashent::portal, PORTAL_ACTIVE, PORTAL_READY, PortalGetHeapMemory, PortalReleaseCachedPlan(), PortalData::resowner, and PortalData::status.
Referenced by AbortTransaction().
{
HASH_SEQ_STATUS status;
PortalHashEnt *hentry;
hash_seq_init(&status, PortalHashTable);
while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)
{
Portal portal = hentry->portal;
/* Any portal that was actually running has to be considered broken */
if (portal->status == PORTAL_ACTIVE)
MarkPortalFailed(portal);
/*
* Do nothing else to cursors held over from a previous transaction.
*/
if (portal->createSubid == InvalidSubTransactionId)
continue;
/*
* If it was created in the current transaction, we can't do normal
* shutdown on a READY portal either; it might refer to objects
* created in the failed transaction. See comments in
* AtSubAbort_Portals.
*/
if (portal->status == PORTAL_READY)
MarkPortalFailed(portal);
/*
* Allow portalcmds.c to clean up the state it knows about, if we
* haven't already.
*/
if (PointerIsValid(portal->cleanup))
{
(*portal->cleanup) (portal);
portal->cleanup = NULL;
}
/* drop cached plan reference, if any */
PortalReleaseCachedPlan(portal);
/*
* Any resources belonging to the portal will be released in the
* upcoming transaction-wide cleanup; they will be gone before we run
* PortalDrop.
*/
portal->resowner = NULL;
/*
* Although we can't delete the portal data structure proper, we can
* release any memory in subsidiary contexts, such as executor state.
* The cleanup hook was the last thing that might have needed data
* there.
*/
MemoryContextDeleteChildren(PortalGetHeapMemory(portal));
}
}
| void AtCleanup_Portals | ( | void | ) |
Definition at line 801 of file portalmem.c.
References Assert, PortalData::cleanup, PortalData::createSubid, hash_seq_init(), hash_seq_search(), InvalidSubTransactionId, NULL, portalhashent::portal, PORTAL_ACTIVE, PortalDrop(), PortalData::portalPinned, PortalData::resowner, and PortalData::status.
Referenced by CleanupTransaction().
{
HASH_SEQ_STATUS status;
PortalHashEnt *hentry;
hash_seq_init(&status, PortalHashTable);
while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)
{
Portal portal = hentry->portal;
/* Do nothing to cursors held over from a previous transaction */
if (portal->createSubid == InvalidSubTransactionId)
{
Assert(portal->status != PORTAL_ACTIVE);
Assert(portal->resowner == NULL);
continue;
}
/*
* If a portal is still pinned, forcibly unpin it. PortalDrop will not
* let us drop the portal otherwise. Whoever pinned the portal was
* interrupted by the abort too and won't try to use it anymore.
*/
if (portal->portalPinned)
portal->portalPinned = false;
/* We had better not be calling any user-defined code here */
Assert(portal->cleanup == NULL);
/* Zap it. */
PortalDrop(portal, false);
}
}
| void AtSubAbort_Portals | ( | SubTransactionId | mySubid, | |
| SubTransactionId | parentSubid, | |||
| ResourceOwner | parentXactOwner | |||
| ) |
Definition at line 875 of file portalmem.c.
References PortalData::cleanup, PortalData::createSubid, hash_seq_init(), hash_seq_search(), MarkPortalFailed(), MemoryContextDeleteChildren(), NULL, PointerIsValid, portalhashent::portal, PORTAL_ACTIVE, PORTAL_READY, PortalGetHeapMemory, PortalReleaseCachedPlan(), PortalData::resowner, and PortalData::status.
Referenced by AbortSubTransaction().
{
HASH_SEQ_STATUS status;
PortalHashEnt *hentry;
hash_seq_init(&status, PortalHashTable);
while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)
{
Portal portal = hentry->portal;
if (portal->createSubid != mySubid)
continue;
/*
* Force any live portals of my own subtransaction into FAILED state.
* We have to do this because they might refer to objects created or
* changed in the failed subtransaction, leading to crashes if
* execution is resumed, or even if we just try to run ExecutorEnd.
* (Note we do NOT do this to upper-level portals, since they cannot
* have such references and hence may be able to continue.)
*/
if (portal->status == PORTAL_READY ||
portal->status == PORTAL_ACTIVE)
MarkPortalFailed(portal);
/*
* Allow portalcmds.c to clean up the state it knows about, if we
* haven't already.
*/
if (PointerIsValid(portal->cleanup))
{
(*portal->cleanup) (portal);
portal->cleanup = NULL;
}
/* drop cached plan reference, if any */
PortalReleaseCachedPlan(portal);
/*
* Any resources belonging to the portal will be released in the
* upcoming transaction-wide cleanup; they will be gone before we run
* PortalDrop.
*/
portal->resowner = NULL;
/*
* Although we can't delete the portal data structure proper, we can
* release any memory in subsidiary contexts, such as executor state.
* The cleanup hook was the last thing that might have needed data
* there.
*/
MemoryContextDeleteChildren(PortalGetHeapMemory(portal));
}
}
| void AtSubCleanup_Portals | ( | SubTransactionId | mySubid | ) |
Definition at line 940 of file portalmem.c.
References Assert, PortalData::cleanup, PortalData::createSubid, hash_seq_init(), hash_seq_search(), NULL, portalhashent::portal, PortalDrop(), and PortalData::portalPinned.
Referenced by CleanupSubTransaction().
{
HASH_SEQ_STATUS status;
PortalHashEnt *hentry;
hash_seq_init(&status, PortalHashTable);
while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)
{
Portal portal = hentry->portal;
if (portal->createSubid != mySubid)
continue;
/*
* If a portal is still pinned, forcibly unpin it. PortalDrop will not
* let us drop the portal otherwise. Whoever pinned the portal was
* interrupted by the abort too and won't try to use it anymore.
*/
if (portal->portalPinned)
portal->portalPinned = false;
/* We had better not be calling any user-defined code here */
Assert(portal->cleanup == NULL);
/* Zap it. */
PortalDrop(portal, false);
}
}
| void AtSubCommit_Portals | ( | SubTransactionId | mySubid, | |
| SubTransactionId | parentSubid, | |||
| ResourceOwner | parentXactOwner | |||
| ) |
Definition at line 843 of file portalmem.c.
References PortalData::createSubid, hash_seq_init(), hash_seq_search(), NULL, portalhashent::portal, ResourceOwnerNewParent(), and PortalData::resowner.
Referenced by CommitSubTransaction().
{
HASH_SEQ_STATUS status;
PortalHashEnt *hentry;
hash_seq_init(&status, PortalHashTable);
while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)
{
Portal portal = hentry->portal;
if (portal->createSubid == mySubid)
{
portal->createSubid = parentSubid;
if (portal->resowner)
ResourceOwnerNewParent(portal->resowner, parentXactOwner);
}
}
}
| Portal CreateNewPortal | ( | void | ) |
Definition at line 253 of file portalmem.c.
References CreatePortal(), GetPortalByName(), and NULL.
Referenced by ExecuteQuery(), and SPI_cursor_open_internal().
{
static unsigned int unnamed_portal_count = 0;
char portalname[MAX_PORTALNAME_LEN];
/* Select a nonconflicting name */
for (;;)
{
unnamed_portal_count++;
sprintf(portalname, "<unnamed portal %u>", unnamed_portal_count);
if (GetPortalByName(portalname) == NULL)
break;
}
return CreatePortal(portalname, false, false);
}
Definition at line 196 of file portalmem.c.
References ALLOCSET_SMALL_INITSIZE, ALLOCSET_SMALL_MAXSIZE, ALLOCSET_SMALL_MINSIZE, AllocSetContextCreate(), AssertArg, PortalData::atEnd, PortalData::atStart, PortalData::cleanup, PortalData::createSubid, PortalData::creation_time, PortalData::cursorOptions, CurTransactionResourceOwner, ereport, errcode(), errmsg(), ERROR, GetCurrentStatementStartTimestamp(), GetCurrentSubTransactionId(), GetPortalByName(), PortalData::heap, MemoryContextAllocZero(), PointerIsValid, PortalDrop(), PortalHashTableInsert, PortalIsValid, ResourceOwnerCreate(), PortalData::resowner, PortalData::status, PortalData::strategy, PortalData::visible, and WARNING.
Referenced by CreateNewPortal(), exec_bind_message(), exec_simple_query(), PerformCursorOpen(), and SPI_cursor_open_internal().
{
Portal portal;
AssertArg(PointerIsValid(name));
portal = GetPortalByName(name);
if (PortalIsValid(portal))
{
if (!allowDup)
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_CURSOR),
errmsg("cursor \"%s\" already exists", name)));
if (!dupSilent)
ereport(WARNING,
(errcode(ERRCODE_DUPLICATE_CURSOR),
errmsg("closing existing cursor \"%s\"",
name)));
PortalDrop(portal, false);
}
/* make new portal structure */
portal = (Portal) MemoryContextAllocZero(PortalMemory, sizeof *portal);
/* initialize portal heap context; typically it won't store much */
portal->heap = AllocSetContextCreate(PortalMemory,
"PortalHeapMemory",
ALLOCSET_SMALL_MINSIZE,
ALLOCSET_SMALL_INITSIZE,
ALLOCSET_SMALL_MAXSIZE);
/* create a resource owner for the portal */
portal->resowner = ResourceOwnerCreate(CurTransactionResourceOwner,
"Portal");
/* initialize portal fields that don't start off zero */
portal->status = PORTAL_NEW;
portal->cleanup = PortalCleanup;
portal->createSubid = GetCurrentSubTransactionId();
portal->strategy = PORTAL_MULTI_QUERY;
portal->cursorOptions = CURSOR_OPT_NO_SCROLL;
portal->atStart = true;
portal->atEnd = true; /* disallow fetches until query is set */
portal->visible = true;
portal->creation_time = GetCurrentStatementStartTimestamp();
/* put portal in table (sets portal->name) */
PortalHashTableInsert(portal, name);
return portal;
}
| void EnablePortalManager | ( | void | ) |
Definition at line 102 of file portalmem.c.
References ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, ALLOCSET_DEFAULT_MINSIZE, AllocSetContextCreate(), Assert, HASHCTL::entrysize, hash_create(), HASH_ELEM, HASHCTL::keysize, NULL, PORTALS_PER_USER, and TopMemoryContext.
Referenced by InitPostgres().
{
HASHCTL ctl;
Assert(PortalMemory == NULL);
PortalMemory = AllocSetContextCreate(TopMemoryContext,
"PortalMemory",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
ctl.keysize = MAX_PORTALNAME_LEN;
ctl.entrysize = sizeof(PortalHashEnt);
/*
* use PORTALS_PER_USER as a guess of how many hash table entries to
* create, initially
*/
PortalHashTable = hash_create("Portal hash", PORTALS_PER_USER,
&ctl, HASH_ELEM);
}
| Portal GetPortalByName | ( | const char * | name | ) |
Definition at line 130 of file portalmem.c.
References PointerIsValid, and PortalHashTableLookup.
Referenced by CreateNewPortal(), CreatePortal(), exec_describe_portal_message(), exec_execute_message(), exec_simple_query(), execCurrentOf(), FetchStatementTargetList(), PerformPortalClose(), PerformPortalFetch(), PLy_cursor_close(), PLy_cursor_dealloc(), PLy_cursor_fetch(), PLy_cursor_iternext(), PostgresMain(), SPI_cursor_find(), UtilityReturnsTuples(), and UtilityTupleDescriptor().
{
Portal portal;
if (PointerIsValid(name))
PortalHashTableLookup(name, portal);
else
portal = NULL;
return portal;
}
| void MarkPortalDone | ( | Portal | portal | ) |
Definition at line 412 of file portalmem.c.
References Assert, PortalData::cleanup, PointerIsValid, PORTAL_ACTIVE, and PortalData::status.
Referenced by PortalRun().
{
/* Perform the state transition */
Assert(portal->status == PORTAL_ACTIVE);
portal->status = PORTAL_DONE;
/*
* Allow portalcmds.c to clean up the state it knows about. We might as
* well do that now, since the portal can't be executed any more.
*
* In some cases involving execution of a ROLLBACK command in an already
* aborted transaction, this prevents an assertion failure caused by
* reaching AtCleanup_Portals with the cleanup hook still unexecuted.
*/
if (PointerIsValid(portal->cleanup))
{
(*portal->cleanup) (portal);
portal->cleanup = NULL;
}
}
| void MarkPortalFailed | ( | Portal | portal | ) |
Definition at line 440 of file portalmem.c.
References Assert, PortalData::cleanup, PointerIsValid, PORTAL_DONE, and PortalData::status.
Referenced by AtAbort_Portals(), AtSubAbort_Portals(), PersistHoldablePortal(), PortalRun(), PortalRunFetch(), and PortalStart().
{
/* Perform the state transition */
Assert(portal->status != PORTAL_DONE);
portal->status = PORTAL_FAILED;
/*
* Allow portalcmds.c to clean up the state it knows about. We might as
* well do that now, since the portal can't be executed any more.
*
* In some cases involving cleanup of an already aborted transaction, this
* prevents an assertion failure caused by reaching AtCleanup_Portals with
* the cleanup hook still unexecuted.
*/
if (PointerIsValid(portal->cleanup))
{
(*portal->cleanup) (portal);
portal->cleanup = NULL;
}
}
| void PinPortal | ( | Portal | portal | ) |
Definition at line 388 of file portalmem.c.
References elog, ERROR, and PortalData::portalPinned.
Referenced by exec_for_query().
{
if (portal->portalPinned)
elog(ERROR, "portal already pinned");
portal->portalPinned = true;
}
| void PortalCreateHoldStore | ( | Portal | portal | ) |
Definition at line 347 of file portalmem.c.
References ALLOCSET_DEFAULT_INITSIZE, ALLOCSET_DEFAULT_MAXSIZE, ALLOCSET_DEFAULT_MINSIZE, AllocSetContextCreate(), Assert, CURSOR_OPT_SCROLL, PortalData::cursorOptions, PortalData::holdContext, PortalData::holdStore, MemoryContextSwitchTo(), NULL, tuplestore_begin_heap(), and work_mem.
Referenced by FillPortalStore(), and PreCommit_Portals().
{
MemoryContext oldcxt;
Assert(portal->holdContext == NULL);
Assert(portal->holdStore == NULL);
/*
* Create the memory context that is used for storage of the tuple set.
* Note this is NOT a child of the portal's heap memory.
*/
portal->holdContext =
AllocSetContextCreate(PortalMemory,
"PortalHoldContext",
ALLOCSET_DEFAULT_MINSIZE,
ALLOCSET_DEFAULT_INITSIZE,
ALLOCSET_DEFAULT_MAXSIZE);
/*
* Create the tuple store, selecting cross-transaction temp files, and
* enabling random access only if cursor requires scrolling.
*
* XXX: Should maintenance_work_mem be used for the portal size?
*/
oldcxt = MemoryContextSwitchTo(portal->holdContext);
portal->holdStore =
tuplestore_begin_heap(portal->cursorOptions & CURSOR_OPT_SCROLL,
true, work_mem);
MemoryContextSwitchTo(oldcxt);
}
| void PortalDefineQuery | ( | Portal | portal, | |
| const char * | prepStmtName, | |||
| const char * | sourceText, | |||
| const char * | commandTag, | |||
| List * | stmts, | |||
| CachedPlan * | cplan | |||
| ) |
Definition at line 300 of file portalmem.c.
References AssertArg, AssertState, PortalData::commandTag, PortalData::cplan, NIL, NULL, PORTAL_NEW, PortalIsValid, PortalData::prepStmtName, PortalData::sourceText, PortalData::status, and PortalData::stmts.
Referenced by exec_bind_message(), exec_simple_query(), ExecuteQuery(), PerformCursorOpen(), and SPI_cursor_open_internal().
{
AssertArg(PortalIsValid(portal));
AssertState(portal->status == PORTAL_NEW);
AssertArg(sourceText != NULL);
AssertArg(commandTag != NULL || stmts == NIL);
portal->prepStmtName = prepStmtName;
portal->sourceText = sourceText;
portal->commandTag = commandTag;
portal->stmts = stmts;
portal->cplan = cplan;
portal->status = PORTAL_DEFINED;
}
Definition at line 466 of file portalmem.c.
References AssertArg, PortalData::cleanup, ereport, errcode(), errmsg(), ERROR, PortalData::holdContext, PortalData::holdStore, MemoryContextDelete(), MemoryContextSwitchTo(), PortalData::name, pfree(), PointerIsValid, PORTAL_ACTIVE, PORTAL_FAILED, PortalGetHeapMemory, PortalHashTableDelete, PortalIsValid, PortalData::portalPinned, PortalReleaseCachedPlan(), RESOURCE_RELEASE_AFTER_LOCKS, RESOURCE_RELEASE_BEFORE_LOCKS, RESOURCE_RELEASE_LOCKS, ResourceOwnerDelete(), ResourceOwnerRelease(), PortalData::resowner, PortalData::status, and tuplestore_end().
Referenced by AtCleanup_Portals(), AtSubCleanup_Portals(), CreatePortal(), exec_simple_query(), ExecuteQuery(), PerformPortalClose(), PortalHashTableDeleteAll(), PostgresMain(), PreCommit_Portals(), and SPI_cursor_close().
{
AssertArg(PortalIsValid(portal));
/*
* Don't allow dropping a pinned portal, it's still needed by whoever
* pinned it. Not sure if the PORTAL_ACTIVE case can validly happen or
* not...
*/
if (portal->portalPinned ||
portal->status == PORTAL_ACTIVE)
ereport(ERROR,
(errcode(ERRCODE_INVALID_CURSOR_STATE),
errmsg("cannot drop active portal \"%s\"", portal->name)));
/*
* Allow portalcmds.c to clean up the state it knows about, in particular
* shutting down the executor if still active. This step potentially runs
* user-defined code so failure has to be expected. It's the cleanup
* hook's responsibility to not try to do that more than once, in the case
* that failure occurs and then we come back to drop the portal again
* during transaction abort.
*
* Note: in most paths of control, this will have been done already in
* MarkPortalDone or MarkPortalFailed. We're just making sure.
*/
if (PointerIsValid(portal->cleanup))
{
(*portal->cleanup) (portal);
portal->cleanup = NULL;
}
/*
* Remove portal from hash table. Because we do this here, we will not
* come back to try to remove the portal again if there's any error in the
* subsequent steps. Better to leak a little memory than to get into an
* infinite error-recovery loop.
*/
PortalHashTableDelete(portal);
/* drop cached plan reference, if any */
PortalReleaseCachedPlan(portal);
/*
* Release any resources still attached to the portal. There are several
* cases being covered here:
*
* Top transaction commit (indicated by isTopCommit): normally we should
* do nothing here and let the regular end-of-transaction resource
* releasing mechanism handle these resources too. However, if we have a
* FAILED portal (eg, a cursor that got an error), we'd better clean up
* its resources to avoid resource-leakage warning messages.
*
* Sub transaction commit: never comes here at all, since we don't kill
* any portals in AtSubCommit_Portals().
*
* Main or sub transaction abort: we will do nothing here because
* portal->resowner was already set NULL; the resources were already
* cleaned up in transaction abort.
*
* Ordinary portal drop: must release resources. However, if the portal
* is not FAILED then we do not release its locks. The locks become the
* responsibility of the transaction's ResourceOwner (since it is the
* parent of the portal's owner) and will be released when the transaction
* eventually ends.
*/
if (portal->resowner &&
(!isTopCommit || portal->status == PORTAL_FAILED))
{
bool isCommit = (portal->status != PORTAL_FAILED);
ResourceOwnerRelease(portal->resowner,
RESOURCE_RELEASE_BEFORE_LOCKS,
isCommit, false);
ResourceOwnerRelease(portal->resowner,
RESOURCE_RELEASE_LOCKS,
isCommit, false);
ResourceOwnerRelease(portal->resowner,
RESOURCE_RELEASE_AFTER_LOCKS,
isCommit, false);
ResourceOwnerDelete(portal->resowner);
}
portal->resowner = NULL;
/*
* Delete tuplestore if present. We should do this even under error
* conditions; since the tuplestore would have been using cross-
* transaction storage, its temp files need to be explicitly deleted.
*/
if (portal->holdStore)
{
MemoryContext oldcontext;
oldcontext = MemoryContextSwitchTo(portal->holdContext);
tuplestore_end(portal->holdStore);
MemoryContextSwitchTo(oldcontext);
portal->holdStore = NULL;
}
/* delete tuplestore storage, if any */
if (portal->holdContext)
MemoryContextDelete(portal->holdContext);
/* release subsidiary storage */
MemoryContextDelete(PortalGetHeapMemory(portal));
/* release portal struct (it's in PortalMemory) */
pfree(portal);
}
| void PortalHashTableDeleteAll | ( | void | ) |
Definition at line 582 of file portalmem.c.
References hash_seq_init(), hash_seq_search(), hash_seq_term(), NULL, portalhashent::portal, PORTAL_ACTIVE, PortalDrop(), and PortalData::status.
Referenced by DiscardAll(), and PerformPortalClose().
{
HASH_SEQ_STATUS status;
PortalHashEnt *hentry;
if (PortalHashTable == NULL)
return;
hash_seq_init(&status, PortalHashTable);
while ((hentry = hash_seq_search(&status)) != NULL)
{
Portal portal = hentry->portal;
/* Can't close the active portal (the one running the command) */
if (portal->status == PORTAL_ACTIVE)
continue;
PortalDrop(portal, false);
/* Restart the iteration in case that led to other drops */
hash_seq_term(&status);
hash_seq_init(&status, PortalHashTable);
}
}
Definition at line 158 of file portalmem.c.
References IsA, lfirst, and list_length().
Referenced by CachedPlanGetTargetList(), and PlanCacheComputeResultDesc().
{
ListCell *lc;
foreach(lc, stmts)
{
Node *stmt = (Node *) lfirst(lc);
if (IsA(stmt, PlannedStmt))
{
if (((PlannedStmt *) stmt)->canSetTag)
return stmt;
}
else if (IsA(stmt, Query))
{
if (((Query *) stmt)->canSetTag)
return stmt;
}
else
{
/* Utility stmts are assumed canSetTag if they're the only stmt */
if (list_length(stmts) == 1)
return stmt;
}
}
return NULL;
}
Definition at line 621 of file portalmem.c.
References PortalData::createSubid, CURSOR_OPT_HOLD, PortalData::cursorOptions, elog, ereport, errcode(), errmsg(), ERROR, hash_seq_init(), hash_seq_search(), hash_seq_term(), InvalidSubTransactionId, NULL, PersistHoldablePortal(), portalhashent::portal, PORTAL_ACTIVE, PORTAL_READY, PortalCreateHoldStore(), PortalDrop(), PortalData::portalPinned, PortalReleaseCachedPlan(), PortalData::resowner, and PortalData::status.
Referenced by CommitTransaction(), and PrepareTransaction().
{
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;
/*
* There should be no pinned portals anymore. Complain if someone
* leaked one.
*/
if (portal->portalPinned)
elog(ERROR, "cannot commit while a portal is pinned");
/*
* Do not touch active portals --- this can only happen in the case of
* a multi-transaction utility command, such as VACUUM.
*
* Note however that any resource owner attached to such a portal is
* still going to go away, so don't leave a dangling pointer.
*/
if (portal->status == PORTAL_ACTIVE)
{
portal->resowner = NULL;
continue;
}
/* 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.
*
* However, if this is PREPARE TRANSACTION rather than COMMIT,
* refuse PREPARE, because the semantics seem pretty unclear.
*/
if (isPrepare)
ereport(ERROR,
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
errmsg("cannot PREPARE a transaction that has created a cursor WITH HOLD")));
/*
* Note that PersistHoldablePortal() must release all resources
* used by the portal that are local to the creating transaction.
*/
PortalCreateHoldStore(portal);
PersistHoldablePortal(portal);
/* drop cached plan reference, if any */
PortalReleaseCachedPlan(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;
/* Report we changed state */
result = true;
}
else if (portal->createSubid == InvalidSubTransactionId)
{
/*
* Do nothing to cursors held over from a previous transaction
* (including ones we just froze in a previous cycle of this loop)
*/
continue;
}
else
{
/* Zap all non-holdable portals */
PortalDrop(portal, true);
/* Report we changed state */
result = true;
}
/*
* After either freezing or dropping a portal, we have to restart the
* iteration, because we could have invoked user-defined code that
* caused a drop of the next portal in the hash chain.
*/
hash_seq_term(&status);
hash_seq_init(&status, PortalHashTable);
}
return result;
}
| bool ThereAreNoReadyPortals | ( | void | ) |
Definition at line 1060 of file portalmem.c.
References hash_seq_init(), hash_seq_search(), NULL, portalhashent::portal, PORTAL_READY, and PortalData::status.
Referenced by CopyFrom().
{
HASH_SEQ_STATUS status;
PortalHashEnt *hentry;
hash_seq_init(&status, PortalHashTable);
while ((hentry = (PortalHashEnt *) hash_seq_search(&status)) != NULL)
{
Portal portal = hentry->portal;
if (portal->status == PORTAL_READY)
return false;
}
return true;
}
| void UnpinPortal | ( | Portal | portal | ) |
Definition at line 397 of file portalmem.c.
References elog, ERROR, and PortalData::portalPinned.
Referenced by exec_for_query().
{
if (!portal->portalPinned)
elog(ERROR, "portal not pinned");
portal->portalPinned = false;
}
1.7.1