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