diff options
| author | Tom Lane <tgl@sss.pgh.pa.us> | 2004-07-31 00:45:57 +0000 |
|---|---|---|
| committer | Tom Lane <tgl@sss.pgh.pa.us> | 2004-07-31 00:45:57 +0000 |
| commit | a393fbf93763709f90ba1f968e50a35bd4cabcfb (patch) | |
| tree | 955d74e7181214688b575f31c243005fe470dfe1 /src/backend/tcop/pquery.c | |
| parent | 94f8f63fdbcf61a56a23b8052d68fd78bec86a3b (diff) | |
| download | postgresql-a393fbf93763709f90ba1f968e50a35bd4cabcfb.tar.gz | |
Restructure error handling as recently discussed. It is now really
possible to trap an error inside a function rather than letting it
propagate out to PostgresMain. You still have to use AbortCurrentTransaction
to clean up, but at least the error handling itself will cooperate.
Diffstat (limited to 'src/backend/tcop/pquery.c')
| -rw-r--r-- | src/backend/tcop/pquery.c | 348 |
1 files changed, 199 insertions, 149 deletions
diff --git a/src/backend/tcop/pquery.c b/src/backend/tcop/pquery.c index 49e2a4b008..8973cca6d2 100644 --- a/src/backend/tcop/pquery.c +++ b/src/backend/tcop/pquery.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/tcop/pquery.c,v 1.81 2004/07/17 03:29:00 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/tcop/pquery.c,v 1.82 2004/07/31 00:45:36 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -246,94 +246,110 @@ PortalStart(Portal portal, ParamListInfo params) AssertState(portal->status == PORTAL_NEW); /* else extra PortalStart */ /* - * Set global portal context pointers. (Should we set QueryContext?) + * Set up global portal context pointers. (Should we set QueryContext?) */ saveActivePortal = ActivePortal; - ActivePortal = portal; saveResourceOwner = CurrentResourceOwner; - CurrentResourceOwner = portal->resowner; savePortalContext = PortalContext; - PortalContext = PortalGetHeapMemory(portal); + PG_TRY(); + { + ActivePortal = portal; + CurrentResourceOwner = portal->resowner; + PortalContext = PortalGetHeapMemory(portal); - oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal)); + oldContext = MemoryContextSwitchTo(PortalGetHeapMemory(portal)); - /* Must remember portal param list, if any */ - portal->portalParams = params; + /* Must remember portal param list, if any */ + portal->portalParams = params; - /* - * Determine the portal execution strategy - */ - portal->strategy = ChoosePortalStrategy(portal->parseTrees); + /* + * Determine the portal execution strategy + */ + portal->strategy = ChoosePortalStrategy(portal->parseTrees); - /* - * Fire her up according to the strategy - */ - switch (portal->strategy) - { - case PORTAL_ONE_SELECT: + /* + * Fire her up according to the strategy + */ + switch (portal->strategy) + { + case PORTAL_ONE_SELECT: - /* - * Must set query snapshot before starting executor. - */ - SetQuerySnapshot(); + /* + * Must set query snapshot before starting executor. + */ + SetQuerySnapshot(); - /* - * Create QueryDesc in portal's context; for the moment, set - * the destination to None. - */ - queryDesc = CreateQueryDesc((Query *) linitial(portal->parseTrees), - (Plan *) linitial(portal->planTrees), - None_Receiver, - params, - false); + /* + * Create QueryDesc in portal's context; for the moment, set + * the destination to None. + */ + queryDesc = CreateQueryDesc((Query *) linitial(portal->parseTrees), + (Plan *) linitial(portal->planTrees), + None_Receiver, + params, + false); - /* - * Call ExecStart to prepare the plan for execution - */ - ExecutorStart(queryDesc, false, false); + /* + * Call ExecStart to prepare the plan for execution + */ + ExecutorStart(queryDesc, false, false); - /* - * This tells PortalCleanup to shut down the executor - */ - portal->queryDesc = queryDesc; + /* + * This tells PortalCleanup to shut down the executor + */ + portal->queryDesc = queryDesc; - /* - * Remember tuple descriptor (computed by ExecutorStart) - */ - portal->tupDesc = queryDesc->tupDesc; + /* + * Remember tuple descriptor (computed by ExecutorStart) + */ + portal->tupDesc = queryDesc->tupDesc; - /* - * Reset cursor position data to "start of query" - */ - portal->atStart = true; - portal->atEnd = false; /* allow fetches */ - portal->portalPos = 0; - portal->posOverflow = false; - break; + /* + * Reset cursor position data to "start of query" + */ + portal->atStart = true; + portal->atEnd = false; /* allow fetches */ + portal->portalPos = 0; + portal->posOverflow = false; + break; - case PORTAL_UTIL_SELECT: + case PORTAL_UTIL_SELECT: - /* - * We don't set query snapshot here, because PortalRunUtility - * will take care of it. - */ - portal->tupDesc = - UtilityTupleDescriptor(((Query *) linitial(portal->parseTrees))->utilityStmt); + /* + * We don't set query snapshot here, because PortalRunUtility + * will take care of it. + */ + portal->tupDesc = + UtilityTupleDescriptor(((Query *) linitial(portal->parseTrees))->utilityStmt); - /* - * Reset cursor position data to "start of query" - */ - portal->atStart = true; - portal->atEnd = false; /* allow fetches */ - portal->portalPos = 0; - portal->posOverflow = false; - break; + /* + * Reset cursor position data to "start of query" + */ + portal->atStart = true; + portal->atEnd = false; /* allow fetches */ + portal->portalPos = 0; + portal->posOverflow = false; + break; - case PORTAL_MULTI_QUERY: - /* Need do nothing now */ - portal->tupDesc = NULL; - break; + case PORTAL_MULTI_QUERY: + /* Need do nothing now */ + portal->tupDesc = NULL; + break; + } } + PG_CATCH(); + { + /* Uncaught error while executing portal: mark it dead */ + portal->status = PORTAL_FAILED; + + /* Restore global vars and propagate error */ + ActivePortal = saveActivePortal; + CurrentResourceOwner = saveResourceOwner; + PortalContext = savePortalContext; + + PG_RE_THROW(); + } + PG_END_TRY(); MemoryContextSwitchTo(oldContext); @@ -449,91 +465,108 @@ PortalRun(Portal portal, long count, portal->status = PORTAL_ACTIVE; /* - * Set global portal context pointers. + * Set up global portal context pointers. */ saveActivePortal = ActivePortal; - ActivePortal = portal; saveResourceOwner = CurrentResourceOwner; - CurrentResourceOwner = portal->resowner; savePortalContext = PortalContext; - PortalContext = PortalGetHeapMemory(portal); saveQueryContext = QueryContext; - QueryContext = portal->queryContext; + PG_TRY(); + { + ActivePortal = portal; + CurrentResourceOwner = portal->resowner; + PortalContext = PortalGetHeapMemory(portal); + QueryContext = portal->queryContext; - oldContext = MemoryContextSwitchTo(PortalContext); + oldContext = MemoryContextSwitchTo(PortalContext); - switch (portal->strategy) - { - case PORTAL_ONE_SELECT: - (void) PortalRunSelect(portal, true, count, dest); - /* we know the query is supposed to set the tag */ - if (completionTag && portal->commandTag) - strcpy(completionTag, portal->commandTag); + switch (portal->strategy) + { + case PORTAL_ONE_SELECT: + (void) PortalRunSelect(portal, true, count, dest); + /* we know the query is supposed to set the tag */ + if (completionTag && portal->commandTag) + strcpy(completionTag, portal->commandTag); - /* Mark portal not active */ - portal->status = PORTAL_READY; + /* Mark portal not active */ + portal->status = PORTAL_READY; - /* - * Since it's a forward fetch, say DONE iff atEnd is now true. - */ - result = portal->atEnd; - break; + /* + * Since it's a forward fetch, say DONE iff atEnd is now true. + */ + result = portal->atEnd; + break; - case PORTAL_UTIL_SELECT: + case PORTAL_UTIL_SELECT: - /* - * If we have not yet run the utility statement, do so, - * storing its results in the portal's tuplestore. - */ - if (!portal->portalUtilReady) - { - DestReceiver *treceiver; - - PortalCreateHoldStore(portal); - treceiver = CreateDestReceiver(Tuplestore, portal); - PortalRunUtility(portal, linitial(portal->parseTrees), - treceiver, NULL); - (*treceiver->rDestroy) (treceiver); - portal->portalUtilReady = true; - } + /* + * If we have not yet run the utility statement, do so, + * storing its results in the portal's tuplestore. + */ + if (!portal->portalUtilReady) + { + DestReceiver *treceiver; + + PortalCreateHoldStore(portal); + treceiver = CreateDestReceiver(Tuplestore, portal); + PortalRunUtility(portal, linitial(portal->parseTrees), + treceiver, NULL); + (*treceiver->rDestroy) (treceiver); + portal->portalUtilReady = true; + } - /* - * Now fetch desired portion of results. - */ - (void) PortalRunSelect(portal, true, count, dest); + /* + * Now fetch desired portion of results. + */ + (void) PortalRunSelect(portal, true, count, dest); - /* - * We know the query is supposed to set the tag; we assume - * only the default tag is needed. - */ - if (completionTag && portal->commandTag) - strcpy(completionTag, portal->commandTag); + /* + * We know the query is supposed to set the tag; we assume + * only the default tag is needed. + */ + if (completionTag && portal->commandTag) + strcpy(completionTag, portal->commandTag); - /* Mark portal not active */ - portal->status = PORTAL_READY; + /* Mark portal not active */ + portal->status = PORTAL_READY; - /* - * Since it's a forward fetch, say DONE iff atEnd is now true. - */ - result = portal->atEnd; - break; + /* + * Since it's a forward fetch, say DONE iff atEnd is now true. + */ + result = portal->atEnd; + break; - case PORTAL_MULTI_QUERY: - PortalRunMulti(portal, dest, altdest, completionTag); + case PORTAL_MULTI_QUERY: + PortalRunMulti(portal, dest, altdest, completionTag); - /* Prevent portal's commands from being re-executed */ - portal->status = PORTAL_DONE; + /* Prevent portal's commands from being re-executed */ + portal->status = PORTAL_DONE; - /* Always complete at end of RunMulti */ - result = true; - break; + /* Always complete at end of RunMulti */ + result = true; + break; - default: - elog(ERROR, "unrecognized portal strategy: %d", - (int) portal->strategy); - result = false; /* keep compiler quiet */ - break; + default: + elog(ERROR, "unrecognized portal strategy: %d", + (int) portal->strategy); + result = false; /* keep compiler quiet */ + break; + } + } + PG_CATCH(); + { + /* Uncaught error while executing portal: mark it dead */ + portal->status = PORTAL_FAILED; + + /* Restore global vars and propagate error */ + ActivePortal = saveActivePortal; + CurrentResourceOwner = saveResourceOwner; + PortalContext = savePortalContext; + QueryContext = saveQueryContext; + + PG_RE_THROW(); } + PG_END_TRY(); MemoryContextSwitchTo(oldContext); @@ -970,30 +1003,47 @@ PortalRunFetch(Portal portal, portal->status = PORTAL_ACTIVE; /* - * Set global portal context pointers. + * Set up global portal context pointers. */ saveActivePortal = ActivePortal; - ActivePortal = portal; saveResourceOwner = CurrentResourceOwner; - CurrentResourceOwner = portal->resowner; savePortalContext = PortalContext; - PortalContext = PortalGetHeapMemory(portal); saveQueryContext = QueryContext; - QueryContext = portal->queryContext; + PG_TRY(); + { + ActivePortal = portal; + CurrentResourceOwner = portal->resowner; + PortalContext = PortalGetHeapMemory(portal); + QueryContext = portal->queryContext; - oldContext = MemoryContextSwitchTo(PortalContext); + oldContext = MemoryContextSwitchTo(PortalContext); - switch (portal->strategy) + switch (portal->strategy) + { + case PORTAL_ONE_SELECT: + result = DoPortalRunFetch(portal, fdirection, count, dest); + break; + + default: + elog(ERROR, "unsupported portal strategy"); + result = 0; /* keep compiler quiet */ + break; + } + } + PG_CATCH(); { - case PORTAL_ONE_SELECT: - result = DoPortalRunFetch(portal, fdirection, count, dest); - break; + /* Uncaught error while executing portal: mark it dead */ + portal->status = PORTAL_FAILED; - default: - elog(ERROR, "unsupported portal strategy"); - result = 0; /* keep compiler quiet */ - break; + /* Restore global vars and propagate error */ + ActivePortal = saveActivePortal; + CurrentResourceOwner = saveResourceOwner; + PortalContext = savePortalContext; + QueryContext = saveQueryContext; + + PG_RE_THROW(); } + PG_END_TRY(); MemoryContextSwitchTo(oldContext); |
