]> granicus.if.org Git - postgresql/blob - src/backend/executor/nodeResult.c
Goodbye register keyword. Compiler knows better.
[postgresql] / src / backend / executor / nodeResult.c
1 /*-------------------------------------------------------------------------
2  *
3  * nodeResult.c--
4  *        support for constant nodes needing special code.
5  *
6  * Copyright (c) 1994, Regents of the University of California
7  *
8  *
9  * DESCRIPTION
10  *
11  *              Example: in constant queries where no relations are scanned,
12  *              the planner generates result nodes.  Examples of such queries are:
13  *
14  *                              retrieve (x = 1)
15  *              and
16  *                              append emp (name = "mike", salary = 15000)
17  *
18  *              Result nodes are also used to optimise queries
19  *              with tautological qualifications like:
20  *
21  *                              retrieve (emp.all) where 2 > 1
22  *
23  *              In this case, the plan generated is
24  *
25  *                                              Result  (with 2 > 1 qual)
26  *                                              /
27  *                                 SeqScan (emp.all)
28  *
29  * IDENTIFICATION
30  *        $Header: /cvsroot/pgsql/src/backend/executor/nodeResult.c,v 1.5 1997/09/08 21:43:16 momjian Exp $
31  *
32  *-------------------------------------------------------------------------
33  */
34 #include "postgres.h"
35
36
37 #include "executor/executor.h"
38 #include "executor/nodeResult.h"
39
40 /* ----------------------------------------------------------------
41  *              ExecResult(node)
42  *
43  *              returns the tuples from the outer plan which satisify the
44  *              qualification clause.  Since result nodes with right
45  *              subtrees are never planned, we ignore the right subtree
46  *              entirely (for now).. -cim 10/7/89
47  *
48  *              The qualification containing only constant clauses are
49  *              checked first before any processing is done. It always returns
50  *              'nil' if the constant qualification is not satisfied.
51  * ----------------------------------------------------------------
52  */
53 TupleTableSlot *
54 ExecResult(Result *node)
55 {
56         ResultState *resstate;
57         TupleTableSlot *outerTupleSlot;
58         TupleTableSlot *resultSlot;
59         Plan       *outerPlan;
60         ExprContext *econtext;
61         Node       *qual;
62         bool            qualResult;
63         bool            isDone;
64         ProjectionInfo *projInfo;
65
66         /* ----------------
67          *      initialize the result node's state
68          * ----------------
69          */
70         resstate = node->resstate;
71
72         /* ----------------
73          *      get the expression context
74          * ----------------
75          */
76         econtext = resstate->cstate.cs_ExprContext;
77
78         /* ----------------
79          *       check tautological qualifications like (2 > 1)
80          * ----------------
81          */
82         qual = node->resconstantqual;
83         if (qual != NULL)
84         {
85                 qualResult = ExecQual((List *) qual, econtext);
86                 /* ----------------
87                  *      if we failed the constant qual, then there
88                  *      is no need to continue processing because regardless of
89                  *      what happens, the constant qual will be false..
90                  * ----------------
91                  */
92                 if (qualResult == false)
93                         return NULL;
94
95                 /* ----------------
96                  *      our constant qualification succeeded so now we
97                  *      throw away the qual because we know it will always
98                  *      succeed.
99                  * ----------------
100                  */
101                 node->resconstantqual = NULL;
102         }
103
104         if (resstate->cstate.cs_TupFromTlist)
105         {
106                 ProjectionInfo *projInfo;
107
108                 projInfo = resstate->cstate.cs_ProjInfo;
109                 resultSlot = ExecProject(projInfo, &isDone);
110                 if (!isDone)
111                         return resultSlot;
112         }
113
114         /* ----------------
115          *      retrieve a tuple that satisfy the qual from the outer plan until
116          *      there are no more.
117          *
118          *      if rs_done is 1 then it means that we were asked to return
119          *      a constant tuple and we alread did the last time ExecResult()
120          *      was called, so now we are through.
121          * ----------------
122          */
123         outerPlan = outerPlan(node);
124
125         while (!resstate->rs_done)
126         {
127
128                 /* ----------------
129                  *        get next outer tuple if necessary.
130                  * ----------------
131                  */
132                 if (outerPlan != NULL)
133                 {
134                         outerTupleSlot = ExecProcNode(outerPlan, (Plan *) node);
135
136                         if (TupIsNull(outerTupleSlot))
137                                 return NULL;
138
139                         resstate->cstate.cs_OuterTupleSlot = outerTupleSlot;
140                 }
141                 else
142                 {
143
144                         /* ----------------
145                          *      if we don't have an outer plan, then it's probably
146                          *      the case that we are doing a retrieve or an append
147                          *      with a constant target list, so we should only return
148                          *      the constant tuple once or never if we fail the qual.
149                          * ----------------
150                          */
151                         resstate->rs_done = 1;
152                 }
153
154                 /* ----------------
155                  *        get the information to place into the expr context
156                  * ----------------
157                  */
158                 resstate = node->resstate;
159
160                 outerTupleSlot = resstate->cstate.cs_OuterTupleSlot;
161
162                 /* ----------------
163                  *       fill in the information in the expression context
164                  *       XXX gross hack. use outer tuple as scan tuple
165                  * ----------------
166                  */
167                 econtext->ecxt_outertuple = outerTupleSlot;
168                 econtext->ecxt_scantuple = outerTupleSlot;
169
170                 /* ----------------
171                  *       form the result tuple and pass it back using ExecProject()
172                  * ----------------
173                  */
174                 projInfo = resstate->cstate.cs_ProjInfo;
175                 resultSlot = ExecProject(projInfo, &isDone);
176                 resstate->cstate.cs_TupFromTlist = !isDone;
177                 return resultSlot;
178         }
179
180         return NULL;
181 }
182
183 /* ----------------------------------------------------------------
184  *              ExecInitResult
185  *
186  *              Creates the run-time state information for the result node
187  *              produced by the planner and initailizes outer relations
188  *              (child nodes).
189  * ----------------------------------------------------------------
190  */
191 bool
192 ExecInitResult(Result *node, EState *estate, Plan *parent)
193 {
194         ResultState *resstate;
195
196         /* ----------------
197          *      assign execution state to node
198          * ----------------
199          */
200         node->plan.state = estate;
201
202         /* ----------------
203          *      create new ResultState for node
204          * ----------------
205          */
206         resstate = makeNode(ResultState);
207         resstate->rs_done = 0;
208         node->resstate = resstate;
209
210         /* ----------------
211          *      Miscellanious initialization
212          *
213          *               +      assign node's base_id
214          *               +      assign debugging hooks and
215          *               +      create expression context for node
216          * ----------------
217          */
218         ExecAssignNodeBaseInfo(estate, &resstate->cstate, parent);
219         ExecAssignExprContext(estate, &resstate->cstate);
220
221 #define RESULT_NSLOTS 1
222         /* ----------------
223          *      tuple table initialization
224          * ----------------
225          */
226         ExecInitResultTupleSlot(estate, &resstate->cstate);
227
228         /* ----------------
229          *      then initialize children
230          * ----------------
231          */
232         ExecInitNode(outerPlan(node), estate, (Plan *) node);
233
234         /*
235          * we don't use inner plan
236          */
237         Assert(innerPlan(node) == NULL);
238
239         /* ----------------
240          *      initialize tuple type and projection info
241          * ----------------
242          */
243         ExecAssignResultTypeFromTL((Plan *) node, &resstate->cstate);
244         ExecAssignProjectionInfo((Plan *) node, &resstate->cstate);
245
246         /* ----------------
247          *      set "are we done yet" to false
248          * ----------------
249          */
250         resstate->rs_done = 0;
251
252         return TRUE;
253 }
254
255 int
256 ExecCountSlotsResult(Result *node)
257 {
258         return ExecCountSlotsNode(outerPlan(node)) + RESULT_NSLOTS;
259 }
260
261 /* ----------------------------------------------------------------
262  *              ExecEndResult
263  *
264  *              fees up storage allocated through C routines
265  * ----------------------------------------------------------------
266  */
267 void
268 ExecEndResult(Result *node)
269 {
270         ResultState *resstate;
271
272         resstate = node->resstate;
273
274         /* ----------------
275          *      Free the projection info
276          *
277          *      Note: we don't ExecFreeResultType(resstate)
278          *                because the rule manager depends on the tupType
279          *                returned by ExecMain().  So for now, this
280          *                is freed at end-transaction time.  -cim 6/2/91
281          * ----------------
282          */
283         ExecFreeProjectionInfo(&resstate->cstate);
284
285         /* ----------------
286          *      shut down subplans
287          * ----------------
288          */
289         ExecEndNode(outerPlan(node), (Plan *) node);
290
291         /* ----------------
292          *      clean out the tuple table
293          * ----------------
294          */
295         ExecClearTuple(resstate->cstate.cs_ResultTupleSlot);
296 }