Age Owner Branch data TLA 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-2024, 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 *
2463 andres@anarazel.de 67 :CBC 562242 : ExecResult(PlanState *pstate)
68 : : {
69 : 562242 : ResultState *node = castNode(ResultState, pstate);
70 : : TupleTableSlot *outerTupleSlot;
71 : : PlanState *outerPlan;
72 : : ExprContext *econtext;
73 : :
2455 74 [ + + ]: 562242 : CHECK_FOR_INTERRUPTS();
75 : :
7801 tgl@sss.pgh.pa.us 76 : 562239 : econtext = node->ps.ps_ExprContext;
77 : :
78 : : /*
79 : : * check constant qualifications like (2 > 1), if not already done
80 : : */
81 [ + + ]: 562239 : if (node->rs_checkqual)
82 : : {
2588 andres@anarazel.de 83 : 7210 : bool qualResult = ExecQual(node->resconstantqual, econtext);
84 : :
7801 tgl@sss.pgh.pa.us 85 : 7210 : node->rs_checkqual = false;
86 [ + + ]: 7210 : if (!qualResult)
87 : : {
88 : 4424 : node->rs_done = true;
9716 bruce@momjian.us 89 : 4424 : 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 : : */
8634 tgl@sss.pgh.pa.us 97 : 557815 : 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 : : */
1066 drowley@postgresql.o 105 [ + + ]: 557815 : if (!node->rs_done)
106 : : {
7801 tgl@sss.pgh.pa.us 107 : 443005 : outerPlan = outerPlanState(node);
108 : :
9716 bruce@momjian.us 109 [ + + ]: 443005 : if (outerPlan != NULL)
110 : : {
111 : : /*
112 : : * retrieve tuples from the outer plan until there are no more.
113 : : */
7801 tgl@sss.pgh.pa.us 114 : 266899 : outerTupleSlot = ExecProcNode(outerPlan);
115 : :
9716 bruce@momjian.us 116 [ + + + + ]: 266892 : if (TupIsNull(outerTupleSlot))
117 : 3422 : return NULL;
118 : :
119 : : /*
120 : : * prepare to compute projection expressions, which will expect to
121 : : * access the input tuples as varno OUTER.
122 : : */
8677 tgl@sss.pgh.pa.us 123 : 263470 : 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 : : */
7801 131 : 176106 : node->rs_done = true;
132 : : }
133 : :
134 : : /* form the result tuple using ExecProject(), and return it */
2642 andres@anarazel.de 135 : 439576 : return ExecProject(node->ps.ps_ProjInfo);
136 : : }
137 : :
9716 bruce@momjian.us 138 : 114810 : return NULL;
139 : : }
140 : :
141 : : /* ----------------------------------------------------------------
142 : : * ExecResultMarkPos
143 : : * ----------------------------------------------------------------
144 : : */
145 : : void
6268 tgl@sss.pgh.pa.us 146 :UBC 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 *
6620 tgl@sss.pgh.pa.us 180 :CBC 171027 : ExecInitResult(Result *node, EState *estate, int eflags)
181 : : {
182 : : ResultState *resstate;
183 : :
184 : : /* check for unsupported flags */
6268 185 [ - + - - ]: 171027 : Assert(!(eflags & (EXEC_FLAG_MARK | EXEC_FLAG_BACKWARD)) ||
186 : : outerPlan(node) != NULL);
187 : :
188 : : /*
189 : : * create state structure
190 : : */
9716 bruce@momjian.us 191 : 171027 : resstate = makeNode(ResultState);
7801 tgl@sss.pgh.pa.us 192 : 171027 : resstate->ps.plan = (Plan *) node;
193 : 171027 : resstate->ps.state = estate;
2463 andres@anarazel.de 194 : 171027 : resstate->ps.ExecProcNode = ExecResult;
195 : :
9557 vadim4o@yahoo.com 196 : 171027 : resstate->rs_done = false;
916 michael@paquier.xyz 197 : 171027 : resstate->rs_checkqual = (node->resconstantqual != NULL);
198 : :
199 : : /*
200 : : * Miscellaneous initialization
201 : : *
202 : : * create expression context for node
203 : : */
7801 tgl@sss.pgh.pa.us 204 : 171027 : ExecAssignExprContext(estate, &resstate->ps);
205 : :
206 : : /*
207 : : * initialize child nodes
208 : : */
6620 209 : 171027 : outerPlanState(resstate) = ExecInitNode(outerPlan(node), estate, eflags);
210 : :
211 : : /*
212 : : * we don't use inner plan
213 : : */
9716 bruce@momjian.us 214 [ - + ]: 171027 : Assert(innerPlan(node) == NULL);
215 : :
216 : : /*
217 : : * Initialize result slot, type and projection.
218 : : */
1977 andres@anarazel.de 219 : 171027 : ExecInitResultTupleSlotTL(&resstate->ps, &TTSOpsVirtual);
6281 tgl@sss.pgh.pa.us 220 : 171027 : ExecAssignProjectionInfo(&resstate->ps, NULL);
221 : :
222 : : /*
223 : : * initialize child expressions
224 : : */
2249 andres@anarazel.de 225 : 170996 : resstate->ps.qual =
226 : 170996 : ExecInitQual(node->plan.qual, (PlanState *) resstate);
227 : 170996 : resstate->resconstantqual =
228 : 170996 : ExecInitQual((List *) node->resconstantqual, (PlanState *) resstate);
229 : :
7801 tgl@sss.pgh.pa.us 230 : 170996 : return resstate;
231 : : }
232 : :
233 : : /* ----------------------------------------------------------------
234 : : * ExecEndResult
235 : : *
236 : : * frees up storage allocated through C routines
237 : : * ----------------------------------------------------------------
238 : : */
239 : : void
240 : 162547 : ExecEndResult(ResultState *node)
241 : : {
242 : : /*
243 : : * shut down subplans
244 : : */
245 : 162547 : ExecEndNode(outerPlanState(node));
10141 scrappy@hub.org 246 : 162547 : }
247 : :
248 : : void
5025 tgl@sss.pgh.pa.us 249 : 16651 : ExecReScanResult(ResultState *node)
250 : : {
647 251 : 16651 : PlanState *outerPlan = outerPlanState(node);
252 : :
7801 253 : 16651 : node->rs_done = false;
916 michael@paquier.xyz 254 : 16651 : 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 : : */
647 tgl@sss.pgh.pa.us 260 [ + + + + ]: 16651 : if (outerPlan && outerPlan->chgParam == NULL)
261 : 39 : ExecReScan(outerPlan);
9557 vadim4o@yahoo.com 262 : 16651 : }
|