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 298 of file nodeProjectSet.c.

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

Referenced by ExecEndNode().

299 {
300  /*
301  * Free the exprcontext
302  */
303  ExecFreeExprContext(&node->ps);
304 
305  /*
306  * clean out the tuple table
307  */
309 
310  /*
311  * shut down subplans
312  */
314 }
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 204 of file nodeProjectSet.c.

References Assert, 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, NULL, 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().

205 {
207  ListCell *lc;
208  int off;
209 
210  /* check for unsupported flags */
211  Assert(!(eflags & (EXEC_FLAG_MARK | EXEC_FLAG_BACKWARD)));
212 
213  /*
214  * create state structure
215  */
216  state = makeNode(ProjectSetState);
217  state->ps.plan = (Plan *) node;
218  state->ps.state = estate;
219  state->ps.ExecProcNode = ExecProjectSet;
220 
221  state->pending_srf_tuples = false;
222 
223  /*
224  * Miscellaneous initialization
225  *
226  * create expression context for node
227  */
228  ExecAssignExprContext(estate, &state->ps);
229 
230  /*
231  * tuple table initialization
232  */
233  ExecInitResultTupleSlot(estate, &state->ps);
234 
235  /* We don't support any qual on ProjectSet nodes */
236  Assert(node->plan.qual == NIL);
237 
238  /*
239  * initialize child nodes
240  */
241  outerPlanState(state) = ExecInitNode(outerPlan(node), estate, eflags);
242 
243  /*
244  * we don't use inner plan
245  */
246  Assert(innerPlan(node) == NULL);
247 
248  /*
249  * initialize tuple type and projection info
250  */
252 
253  /* Create workspace for per-tlist-entry expr state & SRF-is-done state */
254  state->nelems = list_length(node->plan.targetlist);
255  state->elems = (Node **)
256  palloc(sizeof(Node *) * state->nelems);
257  state->elemdone = (ExprDoneCond *)
258  palloc(sizeof(ExprDoneCond) * state->nelems);
259 
260  /*
261  * Build expressions to evaluate targetlist. We can't use
262  * ExecBuildProjectionInfo here, since that doesn't deal with SRFs.
263  * Instead compile each expression separately, using
264  * ExecInitFunctionResultSet where applicable.
265  */
266  off = 0;
267  foreach(lc, node->plan.targetlist)
268  {
269  TargetEntry *te = (TargetEntry *) lfirst(lc);
270  Expr *expr = te->expr;
271 
272  if ((IsA(expr, FuncExpr) &&((FuncExpr *) expr)->funcretset) ||
273  (IsA(expr, OpExpr) &&((OpExpr *) expr)->opretset))
274  {
275  state->elems[off] = (Node *)
277  &state->ps);
278  }
279  else
280  {
281  Assert(!expression_returns_set((Node *) expr));
282  state->elems[off] = (Node *) ExecInitExpr(expr, &state->ps);
283  }
284 
285  off++;
286  }
287 
288  return state;
289 }
#define NIL
Definition: pg_list.h:69
List * qual
Definition: plannodes.h:145
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
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:509
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 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
#define outerPlan(node)
Definition: plannodes.h:174
ExprDoneCond
Definition: execnodes.h:235
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:853
static TupleTableSlot * ExecProjectSet(PlanState *pstate)
Plan * plan
Definition: execnodes.h:847
#define makeNode(_type_)
Definition: nodes.h:557
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
#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:849
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 castNode, CHECK_FOR_INTERRUPTS, ExprContext::ecxt_outertuple, ExecProcNode(), ExecProjectSRF(), NULL, 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  * Check to see if we're still projecting out tuples from a previous scan
57  * tuple (because there is a function-returning-set in the projection
58  * expressions). If so, try to project another one.
59  */
60  if (node->pending_srf_tuples)
61  {
62  resultSlot = ExecProjectSRF(node, true);
63 
64  if (resultSlot != NULL)
65  return resultSlot;
66  }
67 
68  /*
69  * Reset per-tuple memory context to free any expression evaluation
70  * storage allocated in the previous tuple cycle. Note this can't happen
71  * until we're done projecting out tuples from a scan tuple.
72  */
73  ResetExprContext(econtext);
74 
75  /*
76  * Get another input tuple and project SRFs from it.
77  */
78  for (;;)
79  {
80  /*
81  * Retrieve tuples from the outer plan until there are no more.
82  */
83  outerPlan = outerPlanState(node);
84  outerTupleSlot = ExecProcNode(outerPlan);
85 
86  if (TupIsNull(outerTupleSlot))
87  return NULL;
88 
89  /*
90  * Prepare to compute projection expressions, which will expect to
91  * access the input tuples as varno OUTER.
92  */
93  econtext->ecxt_outertuple = outerTupleSlot;
94 
95  /* Evaluate the expressions */
96  resultSlot = ExecProjectSRF(node, false);
97 
98  /*
99  * Return the tuple unless the projection produced no rows (due to an
100  * empty set), in which case we must loop back to see if there are
101  * more outerPlan tuples.
102  */
103  if (resultSlot)
104  return resultSlot;
105  }
106 
107  return NULL;
108 }
PlanState ps
Definition: execnodes.h:944
#define castNode(_type_, nodeptr)
Definition: nodes.h:578
ExprContext * ps_ExprContext
Definition: execnodes.h:881
bool pending_srf_tuples
Definition: execnodes.h:948
static TupleTableSlot * ExecProjectSRF(ProjectSetState *node, bool continuing)
#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:245
TupleTableSlot * ecxt_outertuple
Definition: execnodes.h:199
#define NULL
Definition: c.h:229
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
#define ResetExprContext(econtext)
Definition: executor.h:469
static TupleTableSlot * ExecProjectSRF ( ProjectSetState node,
bool  continuing 
)
static

Definition at line 123 of file nodeProjectSet.c.

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

Referenced by ExecProjectSet().

124 {
125  TupleTableSlot *resultSlot = node->ps.ps_ResultTupleSlot;
126  ExprContext *econtext = node->ps.ps_ExprContext;
127  bool hassrf PG_USED_FOR_ASSERTS_ONLY;
128  bool hasresult;
129  int argno;
130 
131  ExecClearTuple(resultSlot);
132 
133  /*
134  * Assume no further tuples are produced unless an ExprMultipleResult is
135  * encountered from a set returning function.
136  */
137  node->pending_srf_tuples = false;
138 
139  hassrf = hasresult = false;
140  for (argno = 0; argno < node->nelems; argno++)
141  {
142  Node *elem = node->elems[argno];
143  ExprDoneCond *isdone = &node->elemdone[argno];
144  Datum *result = &resultSlot->tts_values[argno];
145  bool *isnull = &resultSlot->tts_isnull[argno];
146 
147  if (continuing && *isdone == ExprEndResult)
148  {
149  /*
150  * If we're continuing to project output rows from a source tuple,
151  * return NULLs once the SRF has been exhausted.
152  */
153  *result = (Datum) 0;
154  *isnull = true;
155  hassrf = true;
156  }
157  else if (IsA(elem, SetExprState))
158  {
159  /*
160  * Evaluate SRF - possibly continuing previously started output.
161  */
162  *result = ExecMakeFunctionResultSet((SetExprState *) elem,
163  econtext, isnull, isdone);
164 
165  if (*isdone != ExprEndResult)
166  hasresult = true;
167  if (*isdone == ExprMultipleResult)
168  node->pending_srf_tuples = true;
169  hassrf = true;
170  }
171  else
172  {
173  /* Non-SRF tlist expression, just evaluate normally. */
174  *result = ExecEvalExpr((ExprState *) elem, econtext, isnull);
175  *isdone = ExprSingleResult;
176  }
177  }
178 
179  /* ProjectSet should not be used if there's no SRFs */
180  Assert(hassrf);
181 
182  /*
183  * If all the SRFs returned EndResult, we consider that as no row being
184  * produced.
185  */
186  if (hasresult)
187  {
188  ExecStoreVirtualTuple(resultSlot);
189  return resultSlot;
190  }
191 
192  return NULL;
193 }
#define IsA(nodeptr, _type_)
Definition: nodes.h:560
PlanState ps
Definition: execnodes.h:944
ExprContext * ps_ExprContext
Definition: execnodes.h:881
bool pending_srf_tuples
Definition: execnodes.h:948
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:439
Definition: nodes.h:509
Datum * tts_values
Definition: tuptable.h:125
return result
Definition: formatting.c:1633
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:285
Datum ExecMakeFunctionResultSet(SetExprState *fcache, ExprContext *econtext, bool *isNull, ExprDoneCond *isDone)
Definition: execSRF.c:473
ExprDoneCond
Definition: execnodes.h:235
uintptr_t Datum
Definition: postgres.h:372
#define NULL
Definition: c.h:229
#define Assert(condition)
Definition: c.h:676
ExprDoneCond * elemdone
Definition: execnodes.h:946
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:991
TupleTableSlot * ExecStoreVirtualTuple(TupleTableSlot *slot)
Definition: execTuples.c:488
void ExecReScanProjectSet ( ProjectSetState node)

Definition at line 317 of file nodeProjectSet.c.

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

Referenced by ExecReScan().

318 {
319  /* Forget any incompletely-evaluated SRFs */
320  node->pending_srf_tuples = false;
321 
322  /*
323  * If chgParam of subnode is not null then plan will be re-scanned by
324  * first ExecProcNode.
325  */
326  if (node->ps.lefttree->chgParam == NULL)
327  ExecReScan(node->ps.lefttree);
328 }
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
#define NULL
Definition: c.h:229