aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/executor')
-rw-r--r--src/backend/executor/execMain.c74
-rw-r--r--src/backend/executor/functions.c30
2 files changed, 43 insertions, 61 deletions
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index 49fa4156de4..47840d42ebc 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -26,7 +26,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.313 2008/08/25 22:42:32 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.314 2008/10/31 21:07:54 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -76,7 +76,7 @@ typedef struct evalPlanQual
static void InitPlan(QueryDesc *queryDesc, int eflags);
static void ExecCheckPlanOutput(Relation resultRel, List *targetList);
static void ExecEndPlan(PlanState *planstate, EState *estate);
-static TupleTableSlot *ExecutePlan(EState *estate, PlanState *planstate,
+static void ExecutePlan(EState *estate, PlanState *planstate,
CmdType operation,
long numberTuples,
ScanDirection direction,
@@ -220,26 +220,28 @@ ExecutorStart(QueryDesc *queryDesc, int eflags)
* Note: count = 0 is interpreted as no portal limit, i.e., run to
* completion.
*
+ * There is no return value, but output tuples (if any) are sent to
+ * the destination receiver specified in the QueryDesc; and the number
+ * of tuples processed at the top level can be found in
+ * estate->es_processed.
+ *
* We provide a function hook variable that lets loadable plugins
* get control when ExecutorRun is called. Such a plugin would
* normally call standard_ExecutorRun().
*
* ----------------------------------------------------------------
*/
-TupleTableSlot *
+void
ExecutorRun(QueryDesc *queryDesc,
ScanDirection direction, long count)
{
- TupleTableSlot *result;
-
if (ExecutorRun_hook)
- result = (*ExecutorRun_hook) (queryDesc, direction, count);
+ (*ExecutorRun_hook) (queryDesc, direction, count);
else
- result = standard_ExecutorRun(queryDesc, direction, count);
- return result;
+ standard_ExecutorRun(queryDesc, direction, count);
}
-TupleTableSlot *
+void
standard_ExecutorRun(QueryDesc *queryDesc,
ScanDirection direction, long count)
{
@@ -247,7 +249,6 @@ standard_ExecutorRun(QueryDesc *queryDesc,
CmdType operation;
DestReceiver *dest;
bool sendTuples;
- TupleTableSlot *result;
MemoryContext oldcontext;
/* sanity checks */
@@ -283,15 +284,13 @@ standard_ExecutorRun(QueryDesc *queryDesc,
/*
* run plan
*/
- if (ScanDirectionIsNoMovement(direction))
- result = NULL;
- else
- result = ExecutePlan(estate,
- queryDesc->planstate,
- operation,
- count,
- direction,
- dest);
+ if (!ScanDirectionIsNoMovement(direction))
+ ExecutePlan(estate,
+ queryDesc->planstate,
+ operation,
+ count,
+ direction,
+ dest);
/*
* shutdown tuple receiver, if we started it
@@ -300,8 +299,6 @@ standard_ExecutorRun(QueryDesc *queryDesc,
(*dest->rShutdown) (dest);
MemoryContextSwitchTo(oldcontext);
-
- return result;
}
/* ----------------------------------------------------------------
@@ -1271,19 +1268,16 @@ ExecEndPlan(PlanState *planstate, EState *estate)
/* ----------------------------------------------------------------
* ExecutePlan
*
- * processes the query plan to retrieve 'numberTuples' tuples in the
- * direction specified.
- *
- * Retrieves all tuples if numberTuples is 0
+ * Processes the query plan until we have processed 'numberTuples' tuples,
+ * moving in the specified direction.
*
- * result is either a slot containing the last tuple in the case
- * of a SELECT or NULL otherwise.
+ * Runs to completion if numberTuples is 0
*
* Note: the ctid attribute is a 'junk' attribute that is removed before the
* user can see it
* ----------------------------------------------------------------
*/
-static TupleTableSlot *
+static void
ExecutePlan(EState *estate,
PlanState *planstate,
CmdType operation,
@@ -1297,13 +1291,11 @@ ExecutePlan(EState *estate,
ItemPointer tupleid = NULL;
ItemPointerData tuple_ctid;
long current_tuple_count;
- TupleTableSlot *result;
/*
* initialize local variables
*/
current_tuple_count = 0;
- result = NULL;
/*
* Set the direction.
@@ -1332,7 +1324,6 @@ ExecutePlan(EState *estate,
/*
* Loop until we've processed the proper number of tuples from the plan.
*/
-
for (;;)
{
/* Reset the per-output-tuple exprcontext */
@@ -1353,13 +1344,10 @@ lnext: ;
/*
* if the tuple is null, then we assume there is nothing more to
- * process so we just return null...
+ * process so we just end the loop...
*/
if (TupIsNull(planSlot))
- {
- result = NULL;
break;
- }
slot = planSlot;
/*
@@ -1453,7 +1441,6 @@ lnext: ;
default:
elog(ERROR, "unrecognized heap_lock_tuple status: %u",
test);
- return NULL;
}
}
}
@@ -1488,35 +1475,30 @@ lnext: ;
/*
* now that we have a tuple, do the appropriate thing with it.. either
- * return it to the user, add it to a relation someplace, delete it
- * from a relation, or modify some of its attributes.
+ * send it to the output destination, add it to a relation someplace,
+ * delete it from a relation, or modify some of its attributes.
*/
switch (operation)
{
case CMD_SELECT:
ExecSelect(slot, dest, estate);
- result = slot;
break;
case CMD_INSERT:
ExecInsert(slot, tupleid, planSlot, dest, estate);
- result = NULL;
break;
case CMD_DELETE:
ExecDelete(tupleid, planSlot, dest, estate);
- result = NULL;
break;
case CMD_UPDATE:
ExecUpdate(slot, tupleid, planSlot, dest, estate);
- result = NULL;
break;
default:
elog(ERROR, "unrecognized operation code: %d",
(int) operation);
- result = NULL;
break;
}
@@ -1548,12 +1530,6 @@ lnext: ;
/* do nothing */
break;
}
-
- /*
- * here, result is either a slot containing a tuple in the case of a
- * SELECT or NULL otherwise.
- */
- return result;
}
/* ----------------------------------------------------------------
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index a58703111ca..b34b90428ef 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.127 2008/10/31 19:37:56 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/functions.c,v 1.128 2008/10/31 21:07:55 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -105,8 +105,7 @@ static execution_state *init_execution_state(List *queryTree_list,
bool lazyEvalOK);
static void init_sql_fcache(FmgrInfo *finfo, bool lazyEvalOK);
static void postquel_start(execution_state *es, SQLFunctionCachePtr fcache);
-static TupleTableSlot *postquel_getnext(execution_state *es,
- SQLFunctionCachePtr fcache);
+static bool postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache);
static void postquel_end(execution_state *es);
static void postquel_sub_params(SQLFunctionCachePtr fcache,
FunctionCallInfo fcinfo);
@@ -441,10 +440,11 @@ postquel_start(execution_state *es, SQLFunctionCachePtr fcache)
}
/* Run one execution_state; either to completion or to first result row */
-static TupleTableSlot *
+/* Returns true if we ran to completion */
+static bool
postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache)
{
- TupleTableSlot *result;
+ bool result;
/* Make our snapshot the active one for any called functions */
PushActiveSnapshot(es->qd->snapshot);
@@ -460,14 +460,20 @@ postquel_getnext(execution_state *es, SQLFunctionCachePtr fcache)
false, /* not top level */
es->qd->dest,
NULL);
- result = NULL;
+ result = true; /* never stops early */
}
else
{
/* Run regular commands to completion unless lazyEval */
long count = (es->lazyEval) ? 1L : 0L;
- result = ExecutorRun(es->qd, ForwardScanDirection, count);
+ ExecutorRun(es->qd, ForwardScanDirection, count);
+
+ /*
+ * If we requested run to completion OR there was no tuple returned,
+ * command must be complete.
+ */
+ result = (count == 0L || es->qd->estate->es_processed == 0);
}
PopActiveSnapshot();
@@ -678,22 +684,22 @@ fmgr_sql(PG_FUNCTION_ARGS)
*/
while (es)
{
- TupleTableSlot *slot;
+ bool completed;
if (es->status == F_EXEC_START)
postquel_start(es, fcache);
- slot = postquel_getnext(es, fcache);
+ completed = postquel_getnext(es, fcache);
/*
* If we ran the command to completion, we can shut it down now.
* Any row(s) we need to return are safely stashed in the tuplestore,
* and we want to be sure that, for example, AFTER triggers get fired
* before we return anything. Also, if the function doesn't return
- * set, we can shut it down anyway because we don't care about
- * fetching any more result rows.
+ * set, we can shut it down anyway because it must be a SELECT and
+ * we don't care about fetching any more result rows.
*/
- if (TupIsNull(slot) || !fcache->returnsSet)
+ if (completed || !fcache->returnsSet)
postquel_end(es);
/*