PostgreSQL Source Code git master
nodeProjectSet.c File Reference
#include "postgres.h"
#include "executor/executor.h"
#include "executor/nodeProjectSet.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
Include dependency graph for nodeProjectSet.c:

Go to the source code of this file.

Functions

static TupleTableSlotExecProjectSRF (ProjectSetState *node, bool continuing)
 
static TupleTableSlotExecProjectSet (PlanState *pstate)
 
ProjectSetStateExecInitProjectSet (ProjectSet *node, EState *estate, int eflags)
 
void ExecEndProjectSet (ProjectSetState *node)
 
void ExecReScanProjectSet (ProjectSetState *node)
 

Function Documentation

◆ ExecEndProjectSet()

void ExecEndProjectSet ( ProjectSetState node)

Definition at line 328 of file nodeProjectSet.c.

329{
330 /*
331 * shut down subplans
332 */
334}
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:562
#define outerPlanState(node)
Definition: execnodes.h:1237

References ExecEndNode(), and outerPlanState.

Referenced by ExecEndNode().

◆ ExecInitProjectSet()

ProjectSetState * ExecInitProjectSet ( ProjectSet node,
EState estate,
int  eflags 
)

Definition at line 227 of file nodeProjectSet.c.

228{
230 ListCell *lc;
231 int off;
232
233 /* check for unsupported flags */
235
236 /*
237 * create state structure
238 */
240 state->ps.plan = (Plan *) node;
241 state->ps.state = estate;
242 state->ps.ExecProcNode = ExecProjectSet;
243
244 state->pending_srf_tuples = false;
245
246 /*
247 * Miscellaneous initialization
248 *
249 * create expression context for node
250 */
251 ExecAssignExprContext(estate, &state->ps);
252
253 /*
254 * initialize child nodes
255 */
256 outerPlanState(state) = ExecInitNode(outerPlan(node), estate, eflags);
257
258 /*
259 * we don't use inner plan
260 */
261 Assert(innerPlan(node) == NULL);
262
263 /*
264 * tuple table and result type initialization
265 */
267
268 /* Create workspace for per-tlist-entry expr state & SRF-is-done state */
269 state->nelems = list_length(node->plan.targetlist);
270 state->elems = (Node **)
271 palloc(sizeof(Node *) * state->nelems);
272 state->elemdone = (ExprDoneCond *)
273 palloc(sizeof(ExprDoneCond) * state->nelems);
274
275 /*
276 * Build expressions to evaluate targetlist. We can't use
277 * ExecBuildProjectionInfo here, since that doesn't deal with SRFs.
278 * Instead compile each expression separately, using
279 * ExecInitFunctionResultSet where applicable.
280 */
281 off = 0;
282 foreach(lc, node->plan.targetlist)
283 {
284 TargetEntry *te = (TargetEntry *) lfirst(lc);
285 Expr *expr = te->expr;
286
287 if ((IsA(expr, FuncExpr) && ((FuncExpr *) expr)->funcretset) ||
288 (IsA(expr, OpExpr) && ((OpExpr *) expr)->opretset))
289 {
290 state->elems[off] = (Node *)
291 ExecInitFunctionResultSet(expr, state->ps.ps_ExprContext,
292 &state->ps);
293 }
294 else
295 {
297 state->elems[off] = (Node *) ExecInitExpr(expr, &state->ps);
298 }
299
300 off++;
301 }
302
303 /* We don't support any qual on ProjectSet nodes */
304 Assert(node->plan.qual == NIL);
305
306 /*
307 * Create a memory context that ExecMakeFunctionResultSet can use to
308 * evaluate function arguments in. We can't use the per-tuple context for
309 * this because it gets reset too often; but we don't want to leak
310 * evaluation results into the query-lifespan context either. We use one
311 * context for the arguments of all tSRFs, as they have roughly equivalent
312 * lifetimes.
313 */
315 "tSRF function arguments",
317
318 return state;
319}
#define Assert(condition)
Definition: c.h:815
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:143
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:142
SetExprState * ExecInitFunctionResultSet(Expr *expr, ExprContext *econtext, PlanState *parent)
Definition: execSRF.c:444
const TupleTableSlotOps TTSOpsVirtual
Definition: execTuples.c:84
void ExecInitResultTupleSlotTL(PlanState *planstate, const TupleTableSlotOps *tts_ops)
Definition: execTuples.c:1986
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:485
ExprDoneCond
Definition: execnodes.h:320
#define EXEC_FLAG_BACKWARD
Definition: executor.h:68
#define EXEC_FLAG_MARK
Definition: executor.h:69
void * palloc(Size size)
Definition: mcxt.c:1317
MemoryContext CurrentMemoryContext
Definition: mcxt.c:143
#define AllocSetContextCreate
Definition: memutils.h:129
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:160
bool expression_returns_set(Node *clause)
Definition: nodeFuncs.c:763
static TupleTableSlot * ExecProjectSet(PlanState *pstate)
#define IsA(nodeptr, _type_)
Definition: nodes.h:158
#define makeNode(_type_)
Definition: nodes.h:155
#define lfirst(lc)
Definition: pg_list.h:172
static int list_length(const List *l)
Definition: pg_list.h:152
#define NIL
Definition: pg_list.h:68
#define innerPlan(node)
Definition: plannodes.h:182
#define outerPlan(node)
Definition: plannodes.h:183
Definition: nodes.h:129
List * qual
Definition: plannodes.h:154
List * targetlist
Definition: plannodes.h:153
Plan plan
Definition: plannodes.h:211
Expr * expr
Definition: primnodes.h:2245
Definition: regguts.h:323

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate, Assert, CurrentMemoryContext, EXEC_FLAG_BACKWARD, EXEC_FLAG_MARK, ExecAssignExprContext(), ExecInitExpr(), ExecInitFunctionResultSet(), ExecInitNode(), ExecInitResultTupleSlotTL(), ExecProjectSet(), TargetEntry::expr, expression_returns_set(), innerPlan, IsA, lfirst, list_length(), makeNode, NIL, outerPlan, outerPlanState, palloc(), ProjectSet::plan, Plan::qual, Plan::targetlist, and TTSOpsVirtual.

Referenced by ExecInitNode().

◆ ExecProjectSet()

static TupleTableSlot * ExecProjectSet ( PlanState pstate)
static

Definition at line 42 of file nodeProjectSet.c.

43{
45 TupleTableSlot *outerTupleSlot;
46 TupleTableSlot *resultSlot;
48 ExprContext *econtext;
49
51
52 econtext = node->ps.ps_ExprContext;
53
54 /*
55 * Reset per-tuple context to free expression-evaluation storage allocated
56 * for a potentially previously returned tuple. Note that the SRF argument
57 * context has a different lifetime and is reset below.
58 */
59 ResetExprContext(econtext);
60
61 /*
62 * Check to see if we're still projecting out tuples from a previous scan
63 * tuple (because there is a function-returning-set in the projection
64 * expressions). If so, try to project another one.
65 */
66 if (node->pending_srf_tuples)
67 {
68 resultSlot = ExecProjectSRF(node, true);
69
70 if (resultSlot != NULL)
71 return resultSlot;
72 }
73
74 /*
75 * Get another input tuple and project SRFs from it.
76 */
77 for (;;)
78 {
79 /*
80 * Reset argument context to free any expression evaluation storage
81 * allocated in the previous tuple cycle. Note this can't happen
82 * until we're done projecting out tuples from a scan tuple, as
83 * ValuePerCall functions are allowed to reference the arguments for
84 * each returned tuple. However, if we loop around after finding that
85 * no rows are produced from a scan tuple, we should reset, to avoid
86 * leaking memory when many successive scan tuples produce no rows.
87 */
89
90 /*
91 * Retrieve tuples from the outer plan until there are no more.
92 */
94 outerTupleSlot = ExecProcNode(outerPlan);
95
96 if (TupIsNull(outerTupleSlot))
97 return NULL;
98
99 /*
100 * Prepare to compute projection expressions, which will expect to
101 * access the input tuples as varno OUTER.
102 */
103 econtext->ecxt_outertuple = outerTupleSlot;
104
105 /* Evaluate the expressions */
106 resultSlot = ExecProjectSRF(node, false);
107
108 /*
109 * Return the tuple unless the projection produced no rows (due to an
110 * empty set), in which case we must loop back to see if there are
111 * more outerPlan tuples.
112 */
113 if (resultSlot)
114 return resultSlot;
115
116 /*
117 * When we do loop back, we'd better reset the econtext again, just in
118 * case the SRF leaked some memory there.
119 */
120 ResetExprContext(econtext);
121 }
122
123 return NULL;
124}
#define ResetExprContext(econtext)
Definition: executor.h:557
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:267
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:383
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:122
static TupleTableSlot * ExecProjectSRF(ProjectSetState *node, bool continuing)
#define castNode(_type_, nodeptr)
Definition: nodes.h:176
TupleTableSlot * ecxt_outertuple
Definition: execnodes.h:271
ExprContext * ps_ExprContext
Definition: execnodes.h:1180
PlanState ps
Definition: execnodes.h:1359
MemoryContext argcontext
Definition: execnodes.h:1364
bool pending_srf_tuples
Definition: execnodes.h:1363
#define TupIsNull(slot)
Definition: tuptable.h:306

References ProjectSetState::argcontext, castNode, CHECK_FOR_INTERRUPTS, ExprContext::ecxt_outertuple, ExecProcNode(), ExecProjectSRF(), MemoryContextReset(), outerPlan, outerPlanState, ProjectSetState::pending_srf_tuples, ProjectSetState::ps, PlanState::ps_ExprContext, ResetExprContext, and TupIsNull.

Referenced by ExecInitProjectSet().

◆ ExecProjectSRF()

static TupleTableSlot * ExecProjectSRF ( ProjectSetState node,
bool  continuing 
)
static

Definition at line 139 of file nodeProjectSet.c.

140{
141 TupleTableSlot *resultSlot = node->ps.ps_ResultTupleSlot;
142 ExprContext *econtext = node->ps.ps_ExprContext;
143 MemoryContext oldcontext;
144 bool hassrf PG_USED_FOR_ASSERTS_ONLY;
145 bool hasresult;
146 int argno;
147
148 ExecClearTuple(resultSlot);
149
150 /* Call SRFs, as well as plain expressions, in per-tuple context */
151 oldcontext = MemoryContextSwitchTo(econtext->ecxt_per_tuple_memory);
152
153 /*
154 * Assume no further tuples are produced unless an ExprMultipleResult is
155 * encountered from a set returning function.
156 */
157 node->pending_srf_tuples = false;
158
159 hassrf = hasresult = false;
160 for (argno = 0; argno < node->nelems; argno++)
161 {
162 Node *elem = node->elems[argno];
163 ExprDoneCond *isdone = &node->elemdone[argno];
164 Datum *result = &resultSlot->tts_values[argno];
165 bool *isnull = &resultSlot->tts_isnull[argno];
166
167 if (continuing && *isdone == ExprEndResult)
168 {
169 /*
170 * If we're continuing to project output rows from a source tuple,
171 * return NULLs once the SRF has been exhausted.
172 */
173 *result = (Datum) 0;
174 *isnull = true;
175 hassrf = true;
176 }
177 else if (IsA(elem, SetExprState))
178 {
179 /*
180 * Evaluate SRF - possibly continuing previously started output.
181 */
182 *result = ExecMakeFunctionResultSet((SetExprState *) elem,
183 econtext, node->argcontext,
184 isnull, isdone);
185
186 if (*isdone != ExprEndResult)
187 hasresult = true;
188 if (*isdone == ExprMultipleResult)
189 node->pending_srf_tuples = true;
190 hassrf = true;
191 }
192 else
193 {
194 /* Non-SRF tlist expression, just evaluate normally. */
195 *result = ExecEvalExpr((ExprState *) elem, econtext, isnull);
196 *isdone = ExprSingleResult;
197 }
198 }
199
200 MemoryContextSwitchTo(oldcontext);
201
202 /* ProjectSet should not be used if there's no SRFs */
203 Assert(hassrf);
204
205 /*
206 * If all the SRFs returned ExprEndResult, we consider that as no row
207 * being produced.
208 */
209 if (hasresult)
210 {
211 ExecStoreVirtualTuple(resultSlot);
212 return resultSlot;
213 }
214
215 return NULL;
216}
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:204
Datum ExecMakeFunctionResultSet(SetExprState *fcache, ExprContext *econtext, MemoryContext argContext, bool *isNull, ExprDoneCond *isDone)
Definition: execSRF.c:497
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:1739
@ ExprSingleResult
Definition: execnodes.h:321
@ ExprMultipleResult
Definition: execnodes.h:322
@ ExprEndResult
Definition: execnodes.h:323
static Datum ExecEvalExpr(ExprState *state, ExprContext *econtext, bool *isNull)
Definition: executor.h:346
static MemoryContext MemoryContextSwitchTo(MemoryContext context)
Definition: palloc.h:124
uintptr_t Datum
Definition: postgres.h:69
MemoryContext ecxt_per_tuple_memory
Definition: execnodes.h:275
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:1179
ExprDoneCond * elemdone
Definition: execnodes.h:1361
bool * tts_isnull
Definition: tuptable.h:127
Datum * tts_values
Definition: tuptable.h:125
static TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: tuptable.h:454

References ProjectSetState::argcontext, Assert, ExprContext::ecxt_per_tuple_memory, ProjectSetState::elemdone, ProjectSetState::elems, ExecClearTuple(), ExecEvalExpr(), ExecMakeFunctionResultSet(), ExecStoreVirtualTuple(), ExprEndResult, ExprMultipleResult, ExprSingleResult, IsA, MemoryContextSwitchTo(), ProjectSetState::nelems, ProjectSetState::pending_srf_tuples, PG_USED_FOR_ASSERTS_ONLY, ProjectSetState::ps, PlanState::ps_ExprContext, PlanState::ps_ResultTupleSlot, TupleTableSlot::tts_isnull, and TupleTableSlot::tts_values.

Referenced by ExecProjectSet().

◆ ExecReScanProjectSet()

void ExecReScanProjectSet ( ProjectSetState node)

Definition at line 337 of file nodeProjectSet.c.

338{
340
341 /* Forget any incompletely-evaluated SRFs */
342 node->pending_srf_tuples = false;
343
344 /*
345 * If chgParam of subnode is not null then plan will be re-scanned by
346 * first ExecProcNode.
347 */
348 if (outerPlan->chgParam == NULL)
350}
void ExecReScan(PlanState *node)
Definition: execAmi.c:76

References ExecReScan(), outerPlan, outerPlanState, and ProjectSetState::pending_srf_tuples.

Referenced by ExecReScan().