1 /*-------------------------------------------------------------------------
4 * support for constant nodes needing special code.
8 * Result nodes are used in queries where no relations are scanned.
9 * Examples of such queries are:
13 * insert into emp values ('mike', 15000)
15 * (Remember that in an INSERT or UPDATE, we need a plan tree that
16 * generates the new rows.)
18 * Result nodes are also used to optimise queries with constant
19 * qualifications (ie, quals that do not depend on the scanned data),
22 * select * from emp where 2 > 1
24 * In this case, the plan generated is
26 * Result (with 2 > 1 qual)
30 * At runtime, the Result node evaluates the constant qual once,
31 * which is shown by EXPLAIN as a One-Time Filter. If it's
32 * false, we can return an empty result set without running the
33 * controlled plan at all. If it's true, we run the controlled
34 * plan normally and pass back the results.
37 * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group
38 * Portions Copyright (c) 1994, Regents of the University of California
43 *-------------------------------------------------------------------------
48 #include "executor/executor.h"
49 #include "executor/nodeResult.h"
50 #include "utils/memutils.h"
53 /* ----------------------------------------------------------------
56 * returns the tuples from the outer plan which satisfy the
57 * qualification clause. Since result nodes with right
58 * subtrees are never planned, we ignore the right subtree
59 * entirely (for now).. -cim 10/7/89
61 * The qualification containing only constant clauses are
62 * checked first before any processing is done. It always returns
63 * 'nil' if the constant qualification is not satisfied.
64 * ----------------------------------------------------------------
67 ExecResult(ResultState
*node
)
69 TupleTableSlot
*outerTupleSlot
;
70 TupleTableSlot
*resultSlot
;
72 ExprContext
*econtext
;
75 econtext
= node
->ps
.ps_ExprContext
;
78 * check constant qualifications like (2 > 1), if not already done
80 if (node
->rs_checkqual
)
82 bool qualResult
= ExecQual((List
*) node
->resconstantqual
,
86 node
->rs_checkqual
= false;
95 * Check to see if we're still projecting out tuples from a previous scan
96 * tuple (because there is a function-returning-set in the projection
97 * expressions). If so, try to project another one.
99 if (node
->ps
.ps_TupFromTlist
)
101 resultSlot
= ExecProject(node
->ps
.ps_ProjInfo
, &isDone
);
102 if (isDone
== ExprMultipleResult
)
104 /* Done with that source tuple... */
105 node
->ps
.ps_TupFromTlist
= false;
109 * Reset per-tuple memory context to free any expression evaluation
110 * storage allocated in the previous tuple cycle. Note this can't happen
111 * until we're done projecting out tuples from a scan tuple.
113 ResetExprContext(econtext
);
116 * if rs_done is true then it means that we were asked to return a
117 * constant tuple and we already did the last time ExecResult() was
118 * called, OR that we failed the constant qual check. Either way, now we
121 while (!node
->rs_done
)
123 outerPlan
= outerPlanState(node
);
125 if (outerPlan
!= NULL
)
128 * retrieve tuples from the outer plan until there are no more.
130 outerTupleSlot
= ExecProcNode(outerPlan
);
132 if (TupIsNull(outerTupleSlot
))
136 * prepare to compute projection expressions, which will expect to
137 * access the input tuples as varno OUTER.
139 econtext
->ecxt_outertuple
= outerTupleSlot
;
144 * if we don't have an outer plan, then we are just generating the
145 * results from a constant target list. Do it only once.
147 node
->rs_done
= true;
151 * form the result tuple using ExecProject(), and return it --- unless
152 * the projection produces an empty set, in which case we must loop
153 * back to see if there are more outerPlan tuples.
155 resultSlot
= ExecProject(node
->ps
.ps_ProjInfo
, &isDone
);
157 if (isDone
!= ExprEndResult
)
159 node
->ps
.ps_TupFromTlist
= (isDone
== ExprMultipleResult
);
167 /* ----------------------------------------------------------------
169 * ----------------------------------------------------------------
172 ExecResultMarkPos(ResultState
*node
)
174 PlanState
*outerPlan
= outerPlanState(node
);
176 if (outerPlan
!= NULL
)
177 ExecMarkPos(outerPlan
);
179 elog(DEBUG2
, "Result nodes do not support mark/restore");
182 /* ----------------------------------------------------------------
184 * ----------------------------------------------------------------
187 ExecResultRestrPos(ResultState
*node
)
189 PlanState
*outerPlan
= outerPlanState(node
);
191 if (outerPlan
!= NULL
)
192 ExecRestrPos(outerPlan
);
194 elog(ERROR
, "Result nodes do not support mark/restore");
197 /* ----------------------------------------------------------------
200 * Creates the run-time state information for the result node
201 * produced by the planner and initializes outer relations
203 * ----------------------------------------------------------------
206 ExecInitResult(Result
*node
, EState
*estate
, int eflags
)
208 ResultState
*resstate
;
210 /* check for unsupported flags */
211 Assert(!(eflags
& (EXEC_FLAG_MARK
| EXEC_FLAG_BACKWARD
)) ||
212 outerPlan(node
) != NULL
);
215 * create state structure
217 resstate
= makeNode(ResultState
);
218 resstate
->ps
.plan
= (Plan
*) node
;
219 resstate
->ps
.state
= estate
;
221 resstate
->rs_done
= false;
222 resstate
->rs_checkqual
= (node
->resconstantqual
== NULL
) ? false : true;
225 * Miscellaneous initialization
227 * create expression context for node
229 ExecAssignExprContext(estate
, &resstate
->ps
);
231 resstate
->ps
.ps_TupFromTlist
= false;
233 #define RESULT_NSLOTS 1
236 * tuple table initialization
238 ExecInitResultTupleSlot(estate
, &resstate
->ps
);
241 * initialize child expressions
243 resstate
->ps
.targetlist
= (List
*)
244 ExecInitExpr((Expr
*) node
->plan
.targetlist
,
245 (PlanState
*) resstate
);
246 resstate
->ps
.qual
= (List
*)
247 ExecInitExpr((Expr
*) node
->plan
.qual
,
248 (PlanState
*) resstate
);
249 resstate
->resconstantqual
= ExecInitExpr((Expr
*) node
->resconstantqual
,
250 (PlanState
*) resstate
);
253 * initialize child nodes
255 outerPlanState(resstate
) = ExecInitNode(outerPlan(node
), estate
, eflags
);
258 * we don't use inner plan
260 Assert(innerPlan(node
) == NULL
);
263 * initialize tuple type and projection info
265 ExecAssignResultTypeFromTL(&resstate
->ps
);
266 ExecAssignProjectionInfo(&resstate
->ps
, NULL
);
272 ExecCountSlotsResult(Result
*node
)
274 return ExecCountSlotsNode(outerPlan(node
)) + RESULT_NSLOTS
;
277 /* ----------------------------------------------------------------
280 * frees up storage allocated through C routines
281 * ----------------------------------------------------------------
284 ExecEndResult(ResultState
*node
)
287 * Free the exprcontext
289 ExecFreeExprContext(&node
->ps
);
292 * clean out the tuple table
294 ExecClearTuple(node
->ps
.ps_ResultTupleSlot
);
299 ExecEndNode(outerPlanState(node
));
303 ExecReScanResult(ResultState
*node
, ExprContext
*exprCtxt
)
305 node
->rs_done
= false;
306 node
->ps
.ps_TupFromTlist
= false;
307 node
->rs_checkqual
= (node
->resconstantqual
== NULL
) ? false : true;
310 * If chgParam of subnode is not null then plan will be re-scanned by
311 * first ExecProcNode. However, if caller is passing us an exprCtxt then
312 * forcibly rescan the subnode now, so that we can pass the exprCtxt down
313 * to the subnode (needed for gated indexscan).
315 if (node
->ps
.lefttree
&&
316 (node
->ps
.lefttree
->chgParam
== NULL
|| exprCtxt
!= NULL
))
317 ExecReScan(node
->ps
.lefttree
, exprCtxt
);