PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
nodeProjectSet.c File Reference
#include "postgres.h"
#include "executor/executor.h"
#include "executor/nodeProjectSet.h"
#include "miscadmin.h"
#include "nodes/nodeFuncs.h"
#include "utils/memutils.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

void ExecEndProjectSet ( ProjectSetState node)

Definition at line 326 of file nodeProjectSet.c.

References ExecClearTuple(), ExecEndNode(), ExecFreeExprContext(), outerPlanState, ProjectSetState::ps, and PlanState::ps_ResultTupleSlot.

Referenced by ExecEndNode().

327 {
328  /*
329  * Free the exprcontext
330  */
331  ExecFreeExprContext(&node->ps);
332 
333  /*
334  * clean out the tuple table
335  */
337 
338  /*
339  * shut down subplans
340  */
342 }
PlanState ps
Definition: execnodes.h:944
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:523
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:521
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:880
#define outerPlanState(node)
Definition: execnodes.h:893
ProjectSetState* ExecInitProjectSet ( ProjectSet node,
EState estate,
int  eflags 
)

Definition at line 220 of file nodeProjectSet.c.

References ALLOCSET_DEFAULT_SIZES, AllocSetContextCreate(), ProjectSetState::argcontext, Assert, CurrentMemoryContext, ProjectSetState::elemdone, ProjectSetState::elems, EXEC_FLAG_BACKWARD, EXEC_FLAG_MARK, ExecAssignExprContext(), ExecAssignResultTypeFromTL(), ExecInitExpr(), ExecInitFunctionResultSet(), ExecInitNode(), ExecInitResultTupleSlot(), PlanState::ExecProcNode, ExecProjectSet(), TargetEntry::expr, expression_returns_set(), innerPlan, IsA, lfirst, list_length(), makeNode, ProjectSetState::nelems, NIL, outerPlan, outerPlanState, palloc(), ProjectSetState::pending_srf_tuples, ProjectSet::plan, PlanState::plan, ProjectSetState::ps, PlanState::ps_ExprContext, Plan::qual, PlanState::state, and Plan::targetlist.

Referenced by ExecInitNode().

221 {
223  ListCell *lc;
224  int off;
225 
226  /* check for unsupported flags */
227  Assert(!(eflags & (EXEC_FLAG_MARK | EXEC_FLAG_BACKWARD)));
228 
229  /*
230  * create state structure
231  */
232  state = makeNode(ProjectSetState);
233  state->ps.plan = (Plan *) node;
234  state->ps.state = estate;
235  state->ps.ExecProcNode = ExecProjectSet;
236 
237  state->pending_srf_tuples = false;
238 
239  /*
240  * Miscellaneous initialization
241  *
242  * create expression context for node
243  */
244  ExecAssignExprContext(estate, &state->ps);
245 
246  /*
247  * tuple table initialization
248  */
249  ExecInitResultTupleSlot(estate, &state->ps);
250 
251  /* We don't support any qual on ProjectSet nodes */
252  Assert(node->plan.qual == NIL);
253 
254  /*
255  * initialize child nodes
256  */
257  outerPlanState(state) = ExecInitNode(outerPlan(node), estate, eflags);
258 
259  /*
260  * we don't use inner plan
261  */
262  Assert(innerPlan(node) == NULL);
263 
264  /*
265  * initialize tuple type and projection info
266  */
268 
269  /* Create workspace for per-tlist-entry expr state & SRF-is-done state */
270  state->nelems = list_length(node->plan.targetlist);
271  state->elems = (Node **)
272  palloc(sizeof(Node *) * state->nelems);
273  state->elemdone = (ExprDoneCond *)
274  palloc(sizeof(ExprDoneCond) * state->nelems);
275 
276  /*
277  * Build expressions to evaluate targetlist. We can't use
278  * ExecBuildProjectionInfo here, since that doesn't deal with SRFs.
279  * Instead compile each expression separately, using
280  * ExecInitFunctionResultSet where applicable.
281  */
282  off = 0;
283  foreach(lc, node->plan.targetlist)
284  {
285  TargetEntry *te = (TargetEntry *) lfirst(lc);
286  Expr *expr = te->expr;
287 
288  if ((IsA(expr, FuncExpr) &&((FuncExpr *) expr)->funcretset) ||
289  (IsA(expr, OpExpr) &&((OpExpr *) expr)->opretset))
290  {
291  state->elems[off] = (Node *)
293  &state->ps);
294  }
295  else
296  {
297  Assert(!expression_returns_set((Node *) expr));
298  state->elems[off] = (Node *) ExecInitExpr(expr, &state->ps);
299  }
300 
301  off++;
302  }
303 
304 
305  /*
306  * Create a memory context that ExecMakeFunctionResult can use to evaluate
307  * function arguments in. We can't use the per-tuple context for this
308  * because it gets reset too often; but we don't want to leak evaluation
309  * results into the query-lifespan context either. We use one context for
310  * the arguments of all tSRFs, as they have roughly equivalent lifetimes.
311  */
313  "tSRF function arguments",
315 
316  return state;
317 }
#define NIL
Definition: pg_list.h:69
List * qual
Definition: plannodes.h:145
#define IsA(nodeptr, _type_)
Definition: nodes.h:561
MemoryContext argcontext
Definition: execnodes.h:949
PlanState ps
Definition: execnodes.h:944
ExprContext * ps_ExprContext
Definition: execnodes.h:881
bool expression_returns_set(Node *clause)
Definition: nodeFuncs.c:670
bool pending_srf_tuples
Definition: execnodes.h:948
Definition: nodes.h:510
EState * state
Definition: execnodes.h:849
void ExecAssignResultTypeFromTL(PlanState *planstate)
Definition: execUtils.c:445
void ExecInitResultTupleSlot(EState *estate, PlanState *planstate)
Definition: execTuples.c:832
SetExprState * ExecInitFunctionResultSet(Expr *expr, ExprContext *econtext, PlanState *parent)
Definition: execSRF.c:424
#define ALLOCSET_DEFAULT_SIZES
Definition: memutils.h:165
#define EXEC_FLAG_BACKWARD
Definition: executor.h:60
#define outerPlanState(node)
Definition: execnodes.h:893
#define innerPlan(node)
Definition: plannodes.h:173
Node ** elems
Definition: execnodes.h:945
MemoryContext CurrentMemoryContext
Definition: mcxt.c:37
#define outerPlan(node)
Definition: plannodes.h:174
ExprDoneCond
Definition: execnodes.h:235
MemoryContext AllocSetContextCreate(MemoryContext parent, const char *name, Size minContextSize, Size initBlockSize, Size maxBlockSize)
Definition: aset.c:322
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:853
static TupleTableSlot * ExecProjectSet(PlanState *pstate)
Plan * plan
Definition: execnodes.h:847
#define makeNode(_type_)
Definition: nodes.h:558
#define Assert(condition)
Definition: c.h:681
#define lfirst(lc)
Definition: pg_list.h:106
#define EXEC_FLAG_MARK
Definition: executor.h:61
Definition: regguts.h:298
Expr * expr
Definition: primnodes.h:1368
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:423
static int list_length(const List *l)
Definition: pg_list.h:89
List * targetlist
Definition: plannodes.h:144
void * palloc(Size size)
Definition: mcxt.c:848
ExprDoneCond * elemdone
Definition: execnodes.h:946
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execExpr.c:113
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:139
Plan plan
Definition: plannodes.h:202
static TupleTableSlot* ExecProjectSet ( PlanState pstate)
static

Definition at line 43 of file nodeProjectSet.c.

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().

44 {
45  ProjectSetState *node = castNode(ProjectSetState, pstate);
46  TupleTableSlot *outerTupleSlot;
47  TupleTableSlot *resultSlot;
49  ExprContext *econtext;
50 
52 
53  econtext = node->ps.ps_ExprContext;
54 
55  /*
56  * Reset per-tuple context to free expression-evaluation storage allocated
57  * for a potentially previously returned tuple. Note that the SRF argument
58  * context has a different lifetime and is reset below.
59  */
60  ResetExprContext(econtext);
61 
62  /*
63  * Check to see if we're still projecting out tuples from a previous scan
64  * tuple (because there is a function-returning-set in the projection
65  * expressions). If so, try to project another one.
66  */
67  if (node->pending_srf_tuples)
68  {
69  resultSlot = ExecProjectSRF(node, true);
70 
71  if (resultSlot != NULL)
72  return resultSlot;
73  }
74 
75  /*
76  * Reset argument context to free any expression evaluation storage
77  * allocated in the previous tuple cycle. Note this can't happen until
78  * we're done projecting out tuples from a scan tuple, as ValuePerCall
79  * functions are allowed to reference the arguments for each returned
80  * tuple.
81  */
83 
84  /*
85  * Get another input tuple and project SRFs from it.
86  */
87  for (;;)
88  {
89  /*
90  * Retrieve tuples from the outer plan until there are no more.
91  */
92  outerPlan = outerPlanState(node);
93  outerTupleSlot = ExecProcNode(outerPlan);
94 
95  if (TupIsNull(outerTupleSlot))
96  return NULL;
97 
98  /*
99  * Prepare to compute projection expressions, which will expect to
100  * access the input tuples as varno OUTER.
101  */
102  econtext->ecxt_outertuple = outerTupleSlot;
103 
104  /* Evaluate the expressions */
105  resultSlot = ExecProjectSRF(node, false);
106 
107  /*
108  * Return the tuple unless the projection produced no rows (due to an
109  * empty set), in which case we must loop back to see if there are
110  * more outerPlan tuples.
111  */
112  if (resultSlot)
113  return resultSlot;
114  }
115 
116  return NULL;
117 }
MemoryContext argcontext
Definition: execnodes.h:949
PlanState ps
Definition: execnodes.h:944
#define castNode(_type_, nodeptr)
Definition: nodes.h:579
ExprContext * ps_ExprContext
Definition: execnodes.h:881
bool pending_srf_tuples
Definition: execnodes.h:948
static TupleTableSlot * ExecProjectSRF(ProjectSetState *node, bool continuing)
void MemoryContextReset(MemoryContext context)
Definition: mcxt.c:135
#define outerPlanState(node)
Definition: execnodes.h:893
#define TupIsNull(slot)
Definition: tuptable.h:138
#define outerPlan(node)
Definition: plannodes.h:174
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:246
TupleTableSlot * ecxt_outertuple
Definition: execnodes.h:199
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
#define ResetExprContext(econtext)
Definition: executor.h:471
static TupleTableSlot * ExecProjectSRF ( ProjectSetState node,
bool  continuing 
)
static

Definition at line 132 of file nodeProjectSet.c.

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().

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

Definition at line 345 of file nodeProjectSet.c.

References PlanState::chgParam, ExecReScan(), PlanState::lefttree, ProjectSetState::pending_srf_tuples, and ProjectSetState::ps.

Referenced by ExecReScan().

346 {
347  /* Forget any incompletely-evaluated SRFs */
348  node->pending_srf_tuples = false;
349 
350  /*
351  * If chgParam of subnode is not null then plan will be re-scanned by
352  * first ExecProcNode.
353  */
354  if (node->ps.lefttree->chgParam == NULL)
355  ExecReScan(node->ps.lefttree);
356 }
PlanState ps
Definition: execnodes.h:944
void ExecReScan(PlanState *node)
Definition: execAmi.c:76
bool pending_srf_tuples
Definition: execnodes.h:948
struct PlanState * lefttree
Definition: execnodes.h:866
Bitmapset * chgParam
Definition: execnodes.h:875