]> granicus.if.org Git - postgresql/blob - src/backend/executor/nodeResult.c
a753a53419183cefebf5c3e0ed9fe6a9f8e8ac37
[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-2017, 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         PlanState  *outerPlan;
71         ExprContext *econtext;
72
73         econtext = node->ps.ps_ExprContext;
74
75         /*
76          * check constant qualifications like (2 > 1), if not already done
77          */
78         if (node->rs_checkqual)
79         {
80                 bool            qualResult = ExecQual(node->resconstantqual, econtext);
81
82                 node->rs_checkqual = false;
83                 if (!qualResult)
84                 {
85                         node->rs_done = true;
86                         return NULL;
87                 }
88         }
89
90         /*
91          * Reset per-tuple memory context to free any expression evaluation
92          * storage allocated in the previous tuple cycle.
93          */
94         ResetExprContext(econtext);
95
96         /*
97          * if rs_done is true then it means that we were asked to return a
98          * constant tuple and we already did the last time ExecResult() was
99          * called, OR that we failed the constant qual check. Either way, now we
100          * are through.
101          */
102         while (!node->rs_done)
103         {
104                 outerPlan = outerPlanState(node);
105
106                 if (outerPlan != NULL)
107                 {
108                         /*
109                          * retrieve tuples from the outer plan until there are no more.
110                          */
111                         outerTupleSlot = ExecProcNode(outerPlan);
112
113                         if (TupIsNull(outerTupleSlot))
114                                 return NULL;
115
116                         /*
117                          * prepare to compute projection expressions, which will expect to
118                          * access the input tuples as varno OUTER.
119                          */
120                         econtext->ecxt_outertuple = outerTupleSlot;
121                 }
122                 else
123                 {
124                         /*
125                          * if we don't have an outer plan, then we are just generating the
126                          * results from a constant target list.  Do it only once.
127                          */
128                         node->rs_done = true;
129                 }
130
131                 /* form the result tuple using ExecProject(), and return it */
132                 return ExecProject(node->ps.ps_ProjInfo);
133         }
134
135         return NULL;
136 }
137
138 /* ----------------------------------------------------------------
139  *              ExecResultMarkPos
140  * ----------------------------------------------------------------
141  */
142 void
143 ExecResultMarkPos(ResultState *node)
144 {
145         PlanState  *outerPlan = outerPlanState(node);
146
147         if (outerPlan != NULL)
148                 ExecMarkPos(outerPlan);
149         else
150                 elog(DEBUG2, "Result nodes do not support mark/restore");
151 }
152
153 /* ----------------------------------------------------------------
154  *              ExecResultRestrPos
155  * ----------------------------------------------------------------
156  */
157 void
158 ExecResultRestrPos(ResultState *node)
159 {
160         PlanState  *outerPlan = outerPlanState(node);
161
162         if (outerPlan != NULL)
163                 ExecRestrPos(outerPlan);
164         else
165                 elog(ERROR, "Result nodes do not support mark/restore");
166 }
167
168 /* ----------------------------------------------------------------
169  *              ExecInitResult
170  *
171  *              Creates the run-time state information for the result node
172  *              produced by the planner and initializes outer relations
173  *              (child nodes).
174  * ----------------------------------------------------------------
175  */
176 ResultState *
177 ExecInitResult(Result *node, EState *estate, int eflags)
178 {
179         ResultState *resstate;
180
181         /* check for unsupported flags */
182         Assert(!(eflags & (EXEC_FLAG_MARK | EXEC_FLAG_BACKWARD)) ||
183                    outerPlan(node) != NULL);
184
185         /*
186          * create state structure
187          */
188         resstate = makeNode(ResultState);
189         resstate->ps.plan = (Plan *) node;
190         resstate->ps.state = estate;
191
192         resstate->rs_done = false;
193         resstate->rs_checkqual = (node->resconstantqual == NULL) ? false : true;
194
195         /*
196          * Miscellaneous initialization
197          *
198          * create expression context for node
199          */
200         ExecAssignExprContext(estate, &resstate->ps);
201
202         /*
203          * tuple table initialization
204          */
205         ExecInitResultTupleSlot(estate, &resstate->ps);
206
207         /*
208          * initialize child expressions
209          */
210         resstate->ps.qual =
211                 ExecInitQual(node->plan.qual, (PlanState *) resstate);
212         resstate->resconstantqual =
213                 ExecInitQual((List *) node->resconstantqual, (PlanState *) resstate);
214
215         /*
216          * initialize child nodes
217          */
218         outerPlanState(resstate) = ExecInitNode(outerPlan(node), estate, eflags);
219
220         /*
221          * we don't use inner plan
222          */
223         Assert(innerPlan(node) == NULL);
224
225         /*
226          * initialize tuple type and projection info
227          */
228         ExecAssignResultTypeFromTL(&resstate->ps);
229         ExecAssignProjectionInfo(&resstate->ps, NULL);
230
231         return resstate;
232 }
233
234 /* ----------------------------------------------------------------
235  *              ExecEndResult
236  *
237  *              frees up storage allocated through C routines
238  * ----------------------------------------------------------------
239  */
240 void
241 ExecEndResult(ResultState *node)
242 {
243         /*
244          * Free the exprcontext
245          */
246         ExecFreeExprContext(&node->ps);
247
248         /*
249          * clean out the tuple table
250          */
251         ExecClearTuple(node->ps.ps_ResultTupleSlot);
252
253         /*
254          * shut down subplans
255          */
256         ExecEndNode(outerPlanState(node));
257 }
258
259 void
260 ExecReScanResult(ResultState *node)
261 {
262         node->rs_done = false;
263         node->rs_checkqual = (node->resconstantqual == NULL) ? false : true;
264
265         /*
266          * If chgParam of subnode is not null then plan will be re-scanned by
267          * first ExecProcNode.
268          */
269         if (node->ps.lefttree &&
270                 node->ps.lefttree->chgParam == NULL)
271                 ExecReScan(node->ps.lefttree);
272 }