*
* select 1 * 2
*
+ * insert into emp values ('mike', 15000)
+ *
+ * (Remember that in an INSERT or UPDATE, we need a plan tree that
+ * generates the new rows.)
+ *
* Result nodes are also used to optimise queries with constant
* qualifications (ie, quals that do not depend on the scanned data),
* such as:
*
* Result (with 2 > 1 qual)
* /
- * SeqScan (emp.all)
+ * SeqScan (emp.*)
*
* At runtime, the Result node evaluates the constant qual once,
* which is shown by EXPLAIN as a One-Time Filter. If it's
* plan normally and pass back the results.
*
*
- * Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeResult.c,v 1.30 2005/04/24 11:46:21 neilc Exp $
+ * src/backend/executor/nodeResult.c
*
*-------------------------------------------------------------------------
*/
ExecResult(ResultState *node)
{
TupleTableSlot *outerTupleSlot;
- TupleTableSlot *resultSlot;
PlanState *outerPlan;
ExprContext *econtext;
- ExprDoneCond isDone;
econtext = node->ps.ps_ExprContext;
*/
if (node->rs_checkqual)
{
- bool qualResult = ExecQual((List *) node->resconstantqual,
- econtext,
- false);
+ bool qualResult = ExecQual(node->resconstantqual, econtext);
node->rs_checkqual = false;
if (!qualResult)
}
}
- /*
- * Check to see if we're still projecting out tuples from a previous
- * scan tuple (because there is a function-returning-set in the
- * projection expressions). If so, try to project another one.
- */
- if (node->ps.ps_TupFromTlist)
- {
- resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
- if (isDone == ExprMultipleResult)
- return resultSlot;
- /* Done with that source tuple... */
- node->ps.ps_TupFromTlist = false;
- }
-
/*
* Reset per-tuple memory context to free any expression evaluation
- * storage allocated in the previous tuple cycle. Note this can't
- * happen until we're done projecting out tuples from a scan tuple.
+ * storage allocated in the previous tuple cycle.
*/
ResetExprContext(econtext);
/*
* if rs_done is true then it means that we were asked to return a
* constant tuple and we already did the last time ExecResult() was
- * called, OR that we failed the constant qual check. Either way, now
- * we are through.
+ * called, OR that we failed the constant qual check. Either way, now we
+ * are through.
*/
while (!node->rs_done)
{
if (outerPlan != NULL)
{
/*
- * retrieve tuples from the outer plan until there are no
- * more.
+ * retrieve tuples from the outer plan until there are no more.
*/
outerTupleSlot = ExecProcNode(outerPlan);
if (TupIsNull(outerTupleSlot))
return NULL;
- node->ps.ps_OuterTupleSlot = outerTupleSlot;
-
/*
- * XXX gross hack. use outer tuple as scan tuple for
- * projection
+ * prepare to compute projection expressions, which will expect to
+ * access the input tuples as varno OUTER.
*/
econtext->ecxt_outertuple = outerTupleSlot;
- econtext->ecxt_scantuple = outerTupleSlot;
}
else
{
/*
- * if we don't have an outer plan, then we are just generating
- * the results from a constant target list. Do it only once.
+ * if we don't have an outer plan, then we are just generating the
+ * results from a constant target list. Do it only once.
*/
node->rs_done = true;
}
- /*
- * form the result tuple using ExecProject(), and return it ---
- * unless the projection produces an empty set, in which case we
- * must loop back to see if there are more outerPlan tuples.
- */
- resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
-
- if (isDone != ExprEndResult)
- {
- node->ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
- return resultSlot;
- }
+ /* form the result tuple using ExecProject(), and return it */
+ return ExecProject(node->ps.ps_ProjInfo);
}
return NULL;
}
+/* ----------------------------------------------------------------
+ * ExecResultMarkPos
+ * ----------------------------------------------------------------
+ */
+void
+ExecResultMarkPos(ResultState *node)
+{
+ PlanState *outerPlan = outerPlanState(node);
+
+ if (outerPlan != NULL)
+ ExecMarkPos(outerPlan);
+ else
+ elog(DEBUG2, "Result nodes do not support mark/restore");
+}
+
+/* ----------------------------------------------------------------
+ * ExecResultRestrPos
+ * ----------------------------------------------------------------
+ */
+void
+ExecResultRestrPos(ResultState *node)
+{
+ PlanState *outerPlan = outerPlanState(node);
+
+ if (outerPlan != NULL)
+ ExecRestrPos(outerPlan);
+ else
+ elog(ERROR, "Result nodes do not support mark/restore");
+}
+
/* ----------------------------------------------------------------
* ExecInitResult
*
* Creates the run-time state information for the result node
- * produced by the planner and initailizes outer relations
+ * produced by the planner and initializes outer relations
* (child nodes).
* ----------------------------------------------------------------
*/
ResultState *
-ExecInitResult(Result *node, EState *estate)
+ExecInitResult(Result *node, EState *estate, int eflags)
{
ResultState *resstate;
+ /* check for unsupported flags */
+ Assert(!(eflags & (EXEC_FLAG_MARK | EXEC_FLAG_BACKWARD)) ||
+ outerPlan(node) != NULL);
+
/*
* create state structure
*/
*/
ExecAssignExprContext(estate, &resstate->ps);
-#define RESULT_NSLOTS 1
-
/*
* tuple table initialization
*/
/*
* initialize child expressions
*/
- resstate->ps.targetlist = (List *)
- ExecInitExpr((Expr *) node->plan.targetlist,
- (PlanState *) resstate);
- resstate->ps.qual = (List *)
- ExecInitExpr((Expr *) node->plan.qual,
- (PlanState *) resstate);
- resstate->resconstantqual = ExecInitExpr((Expr *) node->resconstantqual,
- (PlanState *) resstate);
+ resstate->ps.qual =
+ ExecInitQual(node->plan.qual, (PlanState *) resstate);
+ resstate->resconstantqual =
+ ExecInitQual((List *) node->resconstantqual, (PlanState *) resstate);
/*
* initialize child nodes
*/
- outerPlanState(resstate) = ExecInitNode(outerPlan(node), estate);
+ outerPlanState(resstate) = ExecInitNode(outerPlan(node), estate, eflags);
/*
* we don't use inner plan
* initialize tuple type and projection info
*/
ExecAssignResultTypeFromTL(&resstate->ps);
- ExecAssignProjectionInfo(&resstate->ps);
+ ExecAssignProjectionInfo(&resstate->ps, NULL);
return resstate;
}
-int
-ExecCountSlotsResult(Result *node)
-{
- return ExecCountSlotsNode(outerPlan(node)) + RESULT_NSLOTS;
-}
-
/* ----------------------------------------------------------------
* ExecEndResult
*
}
void
-ExecReScanResult(ResultState *node, ExprContext *exprCtxt)
+ExecReScanResult(ResultState *node)
{
node->rs_done = false;
- node->ps.ps_TupFromTlist = false;
node->rs_checkqual = (node->resconstantqual == NULL) ? false : true;
/*
- * if chgParam of subnode is not null then plan will be re-scanned by
+ * If chgParam of subnode is not null then plan will be re-scanned by
* first ExecProcNode.
*/
- if (((PlanState *) node)->lefttree &&
- ((PlanState *) node)->lefttree->chgParam == NULL)
- ExecReScan(((PlanState *) node)->lefttree, exprCtxt);
+ if (node->ps.lefttree &&
+ node->ps.lefttree->chgParam == NULL)
+ ExecReScan(node->ps.lefttree);
}