1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-02 09:02:37 +03:00

Invent ResourceOwner mechanism as per my recent proposal, and use it to

keep track of portal-related resources separately from transaction-related
resources.  This allows cursors to work in a somewhat sane fashion with
nested transactions.  For now, cursor behavior is non-subtransactional,
that is a cursor's state does not roll back if you abort a subtransaction
that fetched from the cursor.  We might want to change that later.
This commit is contained in:
Tom Lane
2004-07-17 03:32:14 +00:00
parent f4c069ca8f
commit fe548629c5
41 changed files with 2086 additions and 1192 deletions

View File

@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/tcop/pquery.c,v 1.80 2004/06/05 19:48:08 tgl Exp $
* $PostgreSQL: pgsql/src/backend/tcop/pquery.c,v 1.81 2004/07/17 03:29:00 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@ -235,12 +235,25 @@ ChoosePortalStrategy(List *parseTrees)
void
PortalStart(Portal portal, ParamListInfo params)
{
Portal saveActivePortal;
ResourceOwner saveResourceOwner;
MemoryContext savePortalContext;
MemoryContext oldContext;
QueryDesc *queryDesc;
AssertArg(PortalIsValid(portal));
AssertState(portal->queryContext != NULL); /* query defined? */
AssertState(!portal->portalReady); /* else extra PortalStart */
AssertState(portal->status == PORTAL_NEW); /* else extra PortalStart */
/*
* Set global portal context pointers. (Should we set QueryContext?)
*/
saveActivePortal = ActivePortal;
ActivePortal = portal;
saveResourceOwner = CurrentResourceOwner;
CurrentResourceOwner = portal->resowner;
savePortalContext = PortalContext;
PortalContext = PortalGetHeapMemory(portal);
oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal));
@ -324,7 +337,11 @@ PortalStart(Portal portal, ParamListInfo params)
MemoryContextSwitchTo(oldContext);
portal->portalReady = true;
ActivePortal = saveActivePortal;
CurrentResourceOwner = saveResourceOwner;
PortalContext = savePortalContext;
portal->status = PORTAL_READY;
}
/*
@ -403,12 +420,12 @@ PortalRun(Portal portal, long count,
{
bool result;
Portal saveActivePortal;
ResourceOwner saveResourceOwner;
MemoryContext savePortalContext;
MemoryContext saveQueryContext;
MemoryContext oldContext;
AssertArg(PortalIsValid(portal));
AssertState(portal->portalReady); /* else no PortalStart */
/* Initialize completion tag to empty string */
if (completionTag)
@ -425,21 +442,19 @@ PortalRun(Portal portal, long count,
/*
* Check for improper portal use, and mark portal active.
*/
if (portal->portalDone)
if (portal->status != PORTAL_READY)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("portal \"%s\" cannot be run anymore", portal->name)));
if (portal->portalActive)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("portal \"%s\" already active", portal->name)));
portal->portalActive = true;
errmsg("portal \"%s\" cannot be run", portal->name)));
portal->status = PORTAL_ACTIVE;
/*
* Set global portal context pointers.
*/
saveActivePortal = ActivePortal;
ActivePortal = portal;
saveResourceOwner = CurrentResourceOwner;
CurrentResourceOwner = portal->resowner;
savePortalContext = PortalContext;
PortalContext = PortalGetHeapMemory(portal);
saveQueryContext = QueryContext;
@ -455,6 +470,9 @@ PortalRun(Portal portal, long count,
if (completionTag && portal->commandTag)
strcpy(completionTag, portal->commandTag);
/* Mark portal not active */
portal->status = PORTAL_READY;
/*
* Since it's a forward fetch, say DONE iff atEnd is now true.
*/
@ -491,6 +509,9 @@ PortalRun(Portal portal, long count,
if (completionTag && portal->commandTag)
strcpy(completionTag, portal->commandTag);
/* Mark portal not active */
portal->status = PORTAL_READY;
/*
* Since it's a forward fetch, say DONE iff atEnd is now true.
*/
@ -499,6 +520,10 @@ PortalRun(Portal portal, long count,
case PORTAL_MULTI_QUERY:
PortalRunMulti(portal, dest, altdest, completionTag);
/* Prevent portal's commands from being re-executed */
portal->status = PORTAL_DONE;
/* Always complete at end of RunMulti */
result = true;
break;
@ -512,10 +537,8 @@ PortalRun(Portal portal, long count,
MemoryContextSwitchTo(oldContext);
/* Mark portal not active */
portal->portalActive = false;
ActivePortal = saveActivePortal;
CurrentResourceOwner = saveResourceOwner;
PortalContext = savePortalContext;
QueryContext = saveQueryContext;
@ -914,9 +937,6 @@ PortalRunMulti(Portal portal,
else if (strcmp(completionTag, "DELETE") == 0)
strcpy(completionTag, "DELETE 0");
}
/* Prevent portal's commands from being re-executed */
portal->portalDone = true;
}
/*
@ -933,31 +953,29 @@ PortalRunFetch(Portal portal,
{
long result;
Portal saveActivePortal;
ResourceOwner saveResourceOwner;
MemoryContext savePortalContext;
MemoryContext saveQueryContext;
MemoryContext oldContext;
AssertArg(PortalIsValid(portal));
AssertState(portal->portalReady); /* else no PortalStart */
/*
* Check for improper portal use, and mark portal active.
*/
if (portal->portalDone)
if (portal->status != PORTAL_READY)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("portal \"%s\" cannot be run anymore", portal->name)));
if (portal->portalActive)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("portal \"%s\" already active", portal->name)));
portal->portalActive = true;
errmsg("portal \"%s\" cannot be run", portal->name)));
portal->status = PORTAL_ACTIVE;
/*
* Set global portal context pointers.
*/
saveActivePortal = ActivePortal;
ActivePortal = portal;
saveResourceOwner = CurrentResourceOwner;
CurrentResourceOwner = portal->resowner;
savePortalContext = PortalContext;
PortalContext = PortalGetHeapMemory(portal);
saveQueryContext = QueryContext;
@ -980,9 +998,10 @@ PortalRunFetch(Portal portal,
MemoryContextSwitchTo(oldContext);
/* Mark portal not active */
portal->portalActive = false;
portal->status = PORTAL_READY;
ActivePortal = saveActivePortal;
CurrentResourceOwner = saveResourceOwner;
PortalContext = savePortalContext;
QueryContext = saveQueryContext;