mirror of
https://github.com/postgres/postgres.git
synced 2025-07-02 09:02:37 +03:00
Clean up BeginCommand and related routines. BeginCommand and EndCommand
are now both invoked once per received SQL command (raw parsetree) from pg_exec_query_string. BeginCommand is actually just an empty routine at the moment --- all its former operations have been pushed into tuple receiver setup routines in printtup.c. This makes for a clean distinction between BeginCommand/EndCommand (once per command) and the tuple receiver setup/teardown routines (once per ExecutorRun call), whereas the old code was quite ad hoc. Along the way, clean up the calling conventions for ExecutorRun a little bit.
This commit is contained in:
@ -19,7 +19,7 @@
|
||||
* query plan and ExecutorEnd() should always be called at the end of
|
||||
* execution of a plan.
|
||||
*
|
||||
* ExecutorRun accepts 'feature' and 'count' arguments that specify whether
|
||||
* ExecutorRun accepts direction and count arguments that specify whether
|
||||
* the plan is to be executed forwards, backwards, and for how many tuples.
|
||||
*
|
||||
* Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group
|
||||
@ -27,7 +27,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.149 2001/10/25 05:49:27 momjian Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/execMain.c,v 1.150 2002/02/27 19:34:48 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -88,7 +88,7 @@ static void ExecCheckRTEPerms(RangeTblEntry *rte, CmdType operation);
|
||||
* query plan
|
||||
*
|
||||
* returns a TupleDesc which describes the attributes of the tuples to
|
||||
* be returned by the query.
|
||||
* be returned by the query. (Same value is saved in queryDesc)
|
||||
*
|
||||
* NB: the CurrentMemoryContext when this is called must be the context
|
||||
* to be used as the per-query context for the query plan. ExecutorRun()
|
||||
@ -137,6 +137,8 @@ ExecutorStart(QueryDesc *queryDesc, EState *estate)
|
||||
queryDesc->plantree,
|
||||
estate);
|
||||
|
||||
queryDesc->tupDesc = result;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -149,25 +151,23 @@ ExecutorStart(QueryDesc *queryDesc, EState *estate)
|
||||
*
|
||||
* ExecutorStart must have been called already.
|
||||
*
|
||||
* the different features supported are:
|
||||
* EXEC_RUN: retrieve all tuples in the forward direction
|
||||
* EXEC_FOR: retrieve 'count' number of tuples in the forward dir
|
||||
* EXEC_BACK: retrieve 'count' number of tuples in the backward dir
|
||||
* EXEC_RETONE: return one tuple but don't 'retrieve' it
|
||||
* used in postquel function processing
|
||||
* If direction is NoMovementScanDirection then nothing is done
|
||||
* except to start up/shut down the destination. Otherwise,
|
||||
* we retrieve up to 'count' tuples in the specified direction.
|
||||
*
|
||||
* Note: count = 0 is interpreted as "no limit".
|
||||
*
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
TupleTableSlot *
|
||||
ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, long count)
|
||||
ExecutorRun(QueryDesc *queryDesc, EState *estate,
|
||||
ScanDirection direction, long count)
|
||||
{
|
||||
CmdType operation;
|
||||
Plan *plan;
|
||||
TupleTableSlot *result;
|
||||
CommandDest dest;
|
||||
DestReceiver *destfunc;
|
||||
TupleTableSlot *result;
|
||||
|
||||
/*
|
||||
* sanity checks
|
||||
@ -181,69 +181,33 @@ ExecutorRun(QueryDesc *queryDesc, EState *estate, int feature, long count)
|
||||
operation = queryDesc->operation;
|
||||
plan = queryDesc->plantree;
|
||||
dest = queryDesc->dest;
|
||||
destfunc = DestToFunction(dest);
|
||||
|
||||
/*
|
||||
* startup tuple receiver
|
||||
*/
|
||||
estate->es_processed = 0;
|
||||
estate->es_lastoid = InvalidOid;
|
||||
|
||||
destfunc = DestToFunction(dest);
|
||||
(*destfunc->setup) (destfunc, (int) operation,
|
||||
queryDesc->portalName, queryDesc->tupDesc);
|
||||
|
||||
/*
|
||||
* FIXME: the dest setup function ought to be handed the tuple desc
|
||||
* for the tuples to be output, but I'm not quite sure how to get that
|
||||
* info at this point. For now, passing NULL is OK because no
|
||||
* existing dest setup function actually uses the pointer.
|
||||
* run plan
|
||||
*/
|
||||
(*destfunc->setup) (destfunc, (TupleDesc) NULL);
|
||||
|
||||
switch (feature)
|
||||
{
|
||||
case EXEC_RUN:
|
||||
result = ExecutePlan(estate,
|
||||
plan,
|
||||
operation,
|
||||
count,
|
||||
ForwardScanDirection,
|
||||
destfunc);
|
||||
break;
|
||||
|
||||
case EXEC_FOR:
|
||||
result = ExecutePlan(estate,
|
||||
plan,
|
||||
operation,
|
||||
count,
|
||||
ForwardScanDirection,
|
||||
destfunc);
|
||||
break;
|
||||
|
||||
/*
|
||||
* retrieve next n "backward" tuples
|
||||
*/
|
||||
case EXEC_BACK:
|
||||
result = ExecutePlan(estate,
|
||||
plan,
|
||||
operation,
|
||||
count,
|
||||
BackwardScanDirection,
|
||||
destfunc);
|
||||
break;
|
||||
|
||||
/*
|
||||
* return one tuple but don't "retrieve" it. (this is used by
|
||||
* the rule manager..) -cim 9/14/89
|
||||
*/
|
||||
case EXEC_RETONE:
|
||||
result = ExecutePlan(estate,
|
||||
plan,
|
||||
operation,
|
||||
ONE_TUPLE,
|
||||
ForwardScanDirection,
|
||||
destfunc);
|
||||
break;
|
||||
|
||||
default:
|
||||
elog(DEBUG, "ExecutorRun: Unknown feature %d", feature);
|
||||
result = NULL;
|
||||
break;
|
||||
}
|
||||
if (direction == NoMovementScanDirection)
|
||||
result = NULL;
|
||||
else
|
||||
result = ExecutePlan(estate,
|
||||
plan,
|
||||
operation,
|
||||
count,
|
||||
direction,
|
||||
destfunc);
|
||||
|
||||
/*
|
||||
* shutdown receiver
|
||||
*/
|
||||
(*destfunc->cleanup) (destfunc);
|
||||
|
||||
return result;
|
||||
@ -916,7 +880,7 @@ EndPlan(Plan *plan, EState *estate)
|
||||
*
|
||||
* processes the query plan to retrieve 'numberTuples' tuples in the
|
||||
* direction specified.
|
||||
* Retrieves all tuples if tupleCount is 0
|
||||
* Retrieves all tuples if numberTuples is 0
|
||||
*
|
||||
* result is either a slot containing the last tuple in the case
|
||||
* of a RETRIEVE or NULL otherwise.
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.48 2002/02/26 22:47:05 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/functions.c,v 1.49 2002/02/27 19:34:51 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -111,9 +111,8 @@ init_execution_state(char *src, Oid *argOidVect, int nargs)
|
||||
|
||||
nextes->next = NULL;
|
||||
nextes->status = F_EXEC_START;
|
||||
nextes->qd = CreateQueryDesc(queryTree,
|
||||
planTree,
|
||||
None);
|
||||
|
||||
nextes->qd = CreateQueryDesc(queryTree, planTree, None, NULL);
|
||||
estate = CreateExecutorState();
|
||||
|
||||
if (nargs > 0)
|
||||
@ -268,7 +267,7 @@ postquel_start(execution_state *es)
|
||||
static TupleTableSlot *
|
||||
postquel_getnext(execution_state *es)
|
||||
{
|
||||
int feature;
|
||||
long count;
|
||||
|
||||
if (es->qd->operation == CMD_UTILITY)
|
||||
{
|
||||
@ -281,9 +280,10 @@ postquel_getnext(execution_state *es)
|
||||
return (TupleTableSlot *) NULL;
|
||||
}
|
||||
|
||||
feature = (LAST_POSTQUEL_COMMAND(es)) ? EXEC_RETONE : EXEC_RUN;
|
||||
/* If it's not the last command, just run it to completion */
|
||||
count = (LAST_POSTQUEL_COMMAND(es)) ? 1L : 0L;
|
||||
|
||||
return ExecutorRun(es->qd, es->estate, feature, 0L);
|
||||
return ExecutorRun(es->qd, es->estate, ForwardScanDirection, count);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -8,7 +8,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.66 2002/02/26 22:47:05 tgl Exp $
|
||||
* $Header: /cvsroot/pgsql/src/backend/executor/spi.c,v 1.67 2002/02/27 19:34:59 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -779,7 +779,7 @@ SPI_cursor_open(char *name, void *plan, Datum *Values, char *Nulls)
|
||||
queryTree->isBinary = false;
|
||||
|
||||
/* Create the QueryDesc object and the executor state */
|
||||
queryDesc = CreateQueryDesc(queryTree, planTree, SPI);
|
||||
queryDesc = CreateQueryDesc(queryTree, planTree, SPI, NULL);
|
||||
eState = CreateExecutorState();
|
||||
|
||||
/* If the plan has parameters, put them into the executor state */
|
||||
@ -1023,7 +1023,7 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan)
|
||||
else if (plan == NULL)
|
||||
{
|
||||
qdesc = CreateQueryDesc(queryTree, planTree,
|
||||
islastquery ? SPI : None);
|
||||
islastquery ? SPI : None, NULL);
|
||||
state = CreateExecutorState();
|
||||
res = _SPI_pquery(qdesc, state, islastquery ? tcount : 0);
|
||||
if (res < 0 || islastquery)
|
||||
@ -1033,7 +1033,7 @@ _SPI_execute(char *src, int tcount, _SPI_plan *plan)
|
||||
else
|
||||
{
|
||||
qdesc = CreateQueryDesc(queryTree, planTree,
|
||||
islastquery ? SPI : None);
|
||||
islastquery ? SPI : None, NULL);
|
||||
res = _SPI_pquery(qdesc, NULL, islastquery ? tcount : 0);
|
||||
if (res < 0)
|
||||
return res;
|
||||
@ -1094,7 +1094,7 @@ _SPI_execute_plan(_SPI_plan *plan, Datum *Values, char *Nulls, int tcount)
|
||||
else
|
||||
{
|
||||
qdesc = CreateQueryDesc(queryTree, planTree,
|
||||
islastquery ? SPI : None);
|
||||
islastquery ? SPI : None, NULL);
|
||||
state = CreateExecutorState();
|
||||
if (nargs > 0)
|
||||
{
|
||||
@ -1132,7 +1132,6 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount)
|
||||
Query *parseTree = queryDesc->parsetree;
|
||||
int operation = queryDesc->operation;
|
||||
CommandDest dest = queryDesc->dest;
|
||||
TupleDesc tupdesc;
|
||||
bool isRetrieveIntoPortal = false;
|
||||
bool isRetrieveIntoRelation = false;
|
||||
char *intoName = NULL;
|
||||
@ -1174,11 +1173,13 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount)
|
||||
|
||||
if (state == NULL) /* plan preparation */
|
||||
return res;
|
||||
|
||||
#ifdef SPI_EXECUTOR_STATS
|
||||
if (ShowExecutorStats)
|
||||
ResetUsage();
|
||||
#endif
|
||||
tupdesc = ExecutorStart(queryDesc, state);
|
||||
|
||||
ExecutorStart(queryDesc, state);
|
||||
|
||||
/*
|
||||
* Don't work currently --- need to rearrange callers so that we
|
||||
@ -1188,7 +1189,7 @@ _SPI_pquery(QueryDesc *queryDesc, EState *state, int tcount)
|
||||
if (isRetrieveIntoPortal)
|
||||
elog(FATAL, "SPI_select: retrieve into portal not implemented");
|
||||
|
||||
ExecutorRun(queryDesc, state, EXEC_FOR, (long) tcount);
|
||||
ExecutorRun(queryDesc, state, ForwardScanDirection, (long) tcount);
|
||||
|
||||
_SPI_current->processed = state->es_processed;
|
||||
save_lastoid = state->es_lastoid;
|
||||
@ -1230,6 +1231,7 @@ _SPI_cursor_operation(Portal portal, bool forward, int count,
|
||||
QueryDesc *querydesc;
|
||||
EState *estate;
|
||||
MemoryContext oldcontext;
|
||||
ScanDirection direction;
|
||||
CommandId savedId;
|
||||
CommandDest olddest;
|
||||
|
||||
@ -1268,29 +1270,35 @@ _SPI_cursor_operation(Portal portal, bool forward, int count,
|
||||
/* Run the executor like PerformPortalFetch and remember states */
|
||||
if (forward)
|
||||
{
|
||||
if (!portal->atEnd)
|
||||
{
|
||||
ExecutorRun(querydesc, estate, EXEC_FOR, (long) count);
|
||||
_SPI_current->processed = estate->es_processed;
|
||||
if (estate->es_processed > 0)
|
||||
portal->atStart = false;
|
||||
if (count <= 0 || (int) estate->es_processed < count)
|
||||
portal->atEnd = true;
|
||||
}
|
||||
if (portal->atEnd)
|
||||
direction = NoMovementScanDirection;
|
||||
else
|
||||
direction = ForwardScanDirection;
|
||||
|
||||
ExecutorRun(querydesc, estate, direction, (long) count);
|
||||
|
||||
if (estate->es_processed > 0)
|
||||
portal->atStart = false; /* OK to back up now */
|
||||
if (count <= 0 || (int) estate->es_processed < count)
|
||||
portal->atEnd = true; /* we retrieved 'em all */
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!portal->atStart)
|
||||
{
|
||||
ExecutorRun(querydesc, estate, EXEC_BACK, (long) count);
|
||||
_SPI_current->processed = estate->es_processed;
|
||||
if (estate->es_processed > 0)
|
||||
portal->atEnd = false;
|
||||
if (count <= 0 || estate->es_processed < count)
|
||||
portal->atStart = true;
|
||||
}
|
||||
if (portal->atStart)
|
||||
direction = NoMovementScanDirection;
|
||||
else
|
||||
direction = BackwardScanDirection;
|
||||
|
||||
ExecutorRun(querydesc, estate, direction, (long) count);
|
||||
|
||||
if (estate->es_processed > 0)
|
||||
portal->atEnd = false; /* OK to go forward now */
|
||||
if (count <= 0 || (int) estate->es_processed < count)
|
||||
portal->atStart = true; /* we retrieved 'em all */
|
||||
}
|
||||
|
||||
_SPI_current->processed = estate->es_processed;
|
||||
|
||||
/*
|
||||
* Restore outer command ID.
|
||||
*/
|
||||
|
Reference in New Issue
Block a user