]> granicus.if.org Git - postgresql/blob - src/backend/executor/nodeResult.c
Update copyrights for 2013
[postgresql] / src / backend / executor / nodeResult.c
1 /*-------------------------------------------------------------------------
2  *
3  * nodeResult.c
4  *        support for constant nodes needing special code.
5  *
6  * DESCRIPTION
7  *
8  *              Result nodes are used in queries where no relations are scanned.
9  *              Examples of such queries are:
10  *
11  *                              select 1 * 2
12  *
13  *                              insert into emp values ('mike', 15000)
14  *
15  *              (Remember that in an INSERT or UPDATE, we need a plan tree that
16  *              generates the new rows.)
17  *
18  *              Result nodes are also used to optimise queries with constant
19  *              qualifications (ie, quals that do not depend on the scanned data),
20  *              such as:
21  *
22  *                              select * from emp where 2 > 1
23  *
24  *              In this case, the plan generated is
25  *
26  *                                              Result  (with 2 > 1 qual)
27  *                                              /
28  *                                 SeqScan (emp.*)
29  *
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.
35  *
36  *
37  * Portions Copyright (c) 1996-2013, PostgreSQL Global Development Group
38  * Portions Copyright (c) 1994, Regents of the University of California
39  *
40  * IDENTIFICATION
41  *        src/backend/executor/nodeResult.c
42  *
43  *-------------------------------------------------------------------------
44  */
45
46 #include "postgres.h"
47
48 #include "executor/executor.h"
49 #include "executor/nodeResult.h"
50 #include "utils/memutils.h"
51
52
53 /* ----------------------------------------------------------------
54  *              ExecResult(node)
55  *
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
60  *
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  * ----------------------------------------------------------------
65  */
66 TupleTableSlot *
67 ExecResult(ResultState *node)
68 {
69         TupleTableSlot *outerTupleSlot;
70         TupleTableSlot *resultSlot;
71         PlanState  *outerPlan;
72         ExprContext *econtext;
73         ExprDoneCond isDone;
74
75         econtext = node->ps.ps_ExprContext;
76
77         /*
78          * check constant qualifications like (2 > 1), if not already done
79          */
80         if (node->rs_checkqual)
81         {
82                 bool            qualResult = ExecQual((List *) node->resconstantqual,
83                                                                                   econtext,
84                                                                                   false);
85
86                 node->rs_checkqual = false;
87                 if (!qualResult)
88                 {
89                         node->rs_done = true;
90                         return NULL;
91                 }
92         }
93
94         /*
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.
98          */
99         if (node->ps.ps_TupFromTlist)
100         {
101                 resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
102                 if (isDone == ExprMultipleResult)
103                         return resultSlot;
104                 /* Done with that source tuple... */
105                 node->ps.ps_TupFromTlist = false;
106         }
107
108         /*
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.
112          */
113         ResetExprContext(econtext);
114
115         /*
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
119          * are through.
120          */
121         while (!node->rs_done)
122         {
123                 outerPlan = outerPlanState(node);
124
125                 if (outerPlan != NULL)
126                 {
127                         /*
128                          * retrieve tuples from the outer plan until there are no more.
129                          */
130                         outerTupleSlot = ExecProcNode(outerPlan);
131
132                         if (TupIsNull(outerTupleSlot))
133                                 return NULL;
134
135                         /*
136                          * prepare to compute projection expressions, which will expect to
137                          * access the input tuples as varno OUTER.
138                          */
139                         econtext->ecxt_outertuple = outerTupleSlot;
140                 }
141                 else
142                 {
143                         /*
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.
146                          */
147                         node->rs_done = true;
148                 }
149
150                 /*
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.
154                  */
155                 resultSlot = ExecProject(node->ps.ps_ProjInfo, &isDone);
156
157                 if (isDone != ExprEndResult)
158                 {
159                         node->ps.ps_TupFromTlist = (isDone == ExprMultipleResult);
160                         return resultSlot;
161                 }
162         }
163
164         return NULL;
165 }
166
167 /* ----------------------------------------------------------------
168  *              ExecResultMarkPos
169  * ----------------------------------------------------------------
170  */
171 void
172 ExecResultMarkPos(ResultState *node)
173 {
174         PlanState  *outerPlan = outerPlanState(node);
175
176         if (outerPlan != NULL)
177                 ExecMarkPos(outerPlan);
178         else
179                 elog(DEBUG2, "Result nodes do not support mark/restore");
180 }
181
182 /* ----------------------------------------------------------------
183  *              ExecResultRestrPos
184  * ----------------------------------------------------------------
185  */
186 void
187 ExecResultRestrPos(ResultState *node)
188 {
189         PlanState  *outerPlan = outerPlanState(node);
190
191         if (outerPlan != NULL)
192                 ExecRestrPos(outerPlan);
193         else
194                 elog(ERROR, "Result nodes do not support mark/restore");
195 }
196
197 /* ----------------------------------------------------------------
198  *              ExecInitResult
199  *
200  *              Creates the run-time state information for the result node
201  *              produced by the planner and initializes outer relations
202  *              (child nodes).
203  * ----------------------------------------------------------------
204  */
205 ResultState *
206 ExecInitResult(Result *node, EState *estate, int eflags)
207 {
208         ResultState *resstate;
209
210         /* check for unsupported flags */
211         Assert(!(eflags & (EXEC_FLAG_MARK | EXEC_FLAG_BACKWARD)) ||
212                    outerPlan(node) != NULL);
213
214         /*
215          * create state structure
216          */
217         resstate = makeNode(ResultState);
218         resstate->ps.plan = (Plan *) node;
219         resstate->ps.state = estate;
220
221         resstate->rs_done = false;
222         resstate->rs_checkqual = (node->resconstantqual == NULL) ? false : true;
223
224         /*
225          * Miscellaneous initialization
226          *
227          * create expression context for node
228          */
229         ExecAssignExprContext(estate, &resstate->ps);
230
231         resstate->ps.ps_TupFromTlist = false;
232
233         /*
234          * tuple table initialization
235          */
236         ExecInitResultTupleSlot(estate, &resstate->ps);
237
238         /*
239          * initialize child expressions
240          */
241         resstate->ps.targetlist = (List *)
242                 ExecInitExpr((Expr *) node->plan.targetlist,
243                                          (PlanState *) resstate);
244         resstate->ps.qual = (List *)
245                 ExecInitExpr((Expr *) node->plan.qual,
246                                          (PlanState *) resstate);
247         resstate->resconstantqual = ExecInitExpr((Expr *) node->resconstantqual,
248                                                                                          (PlanState *) resstate);
249
250         /*
251          * initialize child nodes
252          */
253         outerPlanState(resstate) = ExecInitNode(outerPlan(node), estate, eflags);
254
255         /*
256          * we don't use inner plan
257          */
258         Assert(innerPlan(node) == NULL);
259
260         /*
261          * initialize tuple type and projection info
262          */
263         ExecAssignResultTypeFromTL(&resstate->ps);
264         ExecAssignProjectionInfo(&resstate->ps, NULL);
265
266         return resstate;
267 }
268
269 /* ----------------------------------------------------------------
270  *              ExecEndResult
271  *
272  *              frees up storage allocated through C routines
273  * ----------------------------------------------------------------
274  */
275 void
276 ExecEndResult(ResultState *node)
277 {
278         /*
279          * Free the exprcontext
280          */
281         ExecFreeExprContext(&node->ps);
282
283         /*
284          * clean out the tuple table
285          */
286         ExecClearTuple(node->ps.ps_ResultTupleSlot);
287
288         /*
289          * shut down subplans
290          */
291         ExecEndNode(outerPlanState(node));
292 }
293
294 void
295 ExecReScanResult(ResultState *node)
296 {
297         node->rs_done = false;
298         node->ps.ps_TupFromTlist = false;
299         node->rs_checkqual = (node->resconstantqual == NULL) ? false : true;
300
301         /*
302          * If chgParam of subnode is not null then plan will be re-scanned by
303          * first ExecProcNode.
304          */
305         if (node->ps.lefttree &&
306                 node->ps.lefttree->chgParam == NULL)
307                 ExecReScan(node->ps.lefttree);
308 }