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

Go to the source code of this file.

Functions

static TupleTableSlotExecMaterial (PlanState *pstate)
 
MaterialStateExecInitMaterial (Material *node, EState *estate, int eflags)
 
void ExecEndMaterial (MaterialState *node)
 
void ExecMaterialMarkPos (MaterialState *node)
 
void ExecMaterialRestrPos (MaterialState *node)
 
void ExecReScanMaterial (MaterialState *node)
 

Function Documentation

◆ ExecEndMaterial()

void ExecEndMaterial ( MaterialState node)

Definition at line 242 of file nodeMaterial.c.

References ExecClearTuple(), ExecEndNode(), outerPlanState, MaterialState::ss, ScanState::ss_ScanTupleSlot, tuplestore_end(), and MaterialState::tuplestorestate.

Referenced by ExecEndNode().

243 {
244  /*
245  * clean out the tuple table
246  */
248 
249  /*
250  * Release tuplestore resources
251  */
252  if (node->tuplestorestate != NULL)
254  node->tuplestorestate = NULL;
255 
256  /*
257  * shut down the subplan
258  */
260 }
Tuplestorestate * tuplestorestate
Definition: execnodes.h:1829
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:539
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:475
ScanState ss
Definition: execnodes.h:1826
TupleTableSlot * ss_ScanTupleSlot
Definition: execnodes.h:1194
#define outerPlanState(node)
Definition: execnodes.h:965
void tuplestore_end(Tuplestorestate *state)
Definition: tuplestore.c:453

◆ ExecInitMaterial()

MaterialState* ExecInitMaterial ( Material node,
EState estate,
int  eflags 
)

Definition at line 166 of file nodeMaterial.c.

References MaterialState::eflags, MaterialState::eof_underlying, EXEC_FLAG_BACKWARD, EXEC_FLAG_MARK, EXEC_FLAG_REWIND, ExecCreateScanSlotFromOuterPlan(), ExecInitNode(), ExecInitResultTupleSlotTL(), ExecMaterial(), PlanState::ExecProcNode, makeNode, outerPlan, outerPlanState, PlanState::plan, ScanState::ps, PlanState::ps_ProjInfo, MaterialState::ss, PlanState::state, and MaterialState::tuplestorestate.

Referenced by ExecInitNode().

167 {
168  MaterialState *matstate;
169  Plan *outerPlan;
170 
171  /*
172  * create state structure
173  */
174  matstate = makeNode(MaterialState);
175  matstate->ss.ps.plan = (Plan *) node;
176  matstate->ss.ps.state = estate;
177  matstate->ss.ps.ExecProcNode = ExecMaterial;
178 
179  /*
180  * We must have a tuplestore buffering the subplan output to do backward
181  * scan or mark/restore. We also prefer to materialize the subplan output
182  * if we might be called on to rewind and replay it many times. However,
183  * if none of these cases apply, we can skip storing the data.
184  */
185  matstate->eflags = (eflags & (EXEC_FLAG_REWIND |
187  EXEC_FLAG_MARK));
188 
189  /*
190  * Tuplestore's interpretation of the flag bits is subtly different from
191  * the general executor meaning: it doesn't think BACKWARD necessarily
192  * means "backwards all the way to start". If told to support BACKWARD we
193  * must include REWIND in the tuplestore eflags, else tuplestore_trim
194  * might throw away too much.
195  */
196  if (eflags & EXEC_FLAG_BACKWARD)
197  matstate->eflags |= EXEC_FLAG_REWIND;
198 
199  matstate->eof_underlying = false;
200  matstate->tuplestorestate = NULL;
201 
202  /*
203  * Miscellaneous initialization
204  *
205  * Materialization nodes don't need ExprContexts because they never call
206  * ExecQual or ExecProject.
207  */
208 
209  /*
210  * initialize child nodes
211  *
212  * We shield the child node from the need to support REWIND, BACKWARD, or
213  * MARK/RESTORE.
214  */
215  eflags &= ~(EXEC_FLAG_REWIND | EXEC_FLAG_BACKWARD | EXEC_FLAG_MARK);
216 
217  outerPlan = outerPlan(node);
218  outerPlanState(matstate) = ExecInitNode(outerPlan, estate, eflags);
219 
220  /*
221  * Initialize result type and slot. No need to initialize projection info
222  * because this node doesn't do projections.
223  *
224  * material nodes only return tuples from their materialized relation.
225  */
226  ExecInitResultTupleSlotTL(estate, &matstate->ss.ps);
227  matstate->ss.ps.ps_ProjInfo = NULL;
228 
229  /*
230  * initialize tuple type.
231  */
232  ExecCreateScanSlotFromOuterPlan(estate, &matstate->ss);
233 
234  return matstate;
235 }
Tuplestorestate * tuplestorestate
Definition: execnodes.h:1829
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:947
ScanState ss
Definition: execnodes.h:1826
EState * state
Definition: execnodes.h:913
static TupleTableSlot * ExecMaterial(PlanState *pstate)
Definition: nodeMaterial.c:39
PlanState ps
Definition: execnodes.h:1191
void ExecCreateScanSlotFromOuterPlan(EState *estate, ScanState *scanstate)
Definition: execUtils.c:598
#define EXEC_FLAG_BACKWARD
Definition: executor.h:60
#define outerPlanState(node)
Definition: execnodes.h:965
bool eof_underlying
Definition: execnodes.h:1828
#define EXEC_FLAG_REWIND
Definition: executor.h:59
#define outerPlan(node)
Definition: plannodes.h:176
ExecProcNodeMtd ExecProcNode
Definition: execnodes.h:917
void ExecInitResultTupleSlotTL(EState *estate, PlanState *planstate)
Definition: execTuples.c:890
Plan * plan
Definition: execnodes.h:911
#define makeNode(_type_)
Definition: nodes.h:565
#define EXEC_FLAG_MARK
Definition: executor.h:61
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:139

◆ ExecMaterial()

static TupleTableSlot* ExecMaterial ( PlanState pstate)
static

Definition at line 39 of file nodeMaterial.c.

References Assert, castNode, CHECK_FOR_INTERRUPTS, MaterialState::eflags, MaterialState::eof_underlying, EState::es_direction, EXEC_FLAG_MARK, ExecClearTuple(), ExecProcNode(), outerPlanState, PG_USED_FOR_ASSERTS_ONLY, ScanState::ps, PlanState::ps_ResultTupleSlot, ScanDirectionIsForward, MaterialState::ss, PlanState::state, TupIsNull, tuplestore_advance(), tuplestore_alloc_read_pointer(), tuplestore_ateof(), tuplestore_begin_heap(), tuplestore_gettupleslot(), tuplestore_puttupleslot(), tuplestore_set_eflags(), MaterialState::tuplestorestate, and work_mem.

Referenced by ExecInitMaterial().

40 {
41  MaterialState *node = castNode(MaterialState, pstate);
42  EState *estate;
43  ScanDirection dir;
44  bool forward;
45  Tuplestorestate *tuplestorestate;
46  bool eof_tuplestore;
47  TupleTableSlot *slot;
48 
50 
51  /*
52  * get state info from node
53  */
54  estate = node->ss.ps.state;
55  dir = estate->es_direction;
56  forward = ScanDirectionIsForward(dir);
57  tuplestorestate = node->tuplestorestate;
58 
59  /*
60  * If first time through, and we need a tuplestore, initialize it.
61  */
62  if (tuplestorestate == NULL && node->eflags != 0)
63  {
64  tuplestorestate = tuplestore_begin_heap(true, false, work_mem);
65  tuplestore_set_eflags(tuplestorestate, node->eflags);
66  if (node->eflags & EXEC_FLAG_MARK)
67  {
68  /*
69  * Allocate a second read pointer to serve as the mark. We know it
70  * must have index 1, so needn't store that.
71  */
72  int ptrno PG_USED_FOR_ASSERTS_ONLY;
73 
74  ptrno = tuplestore_alloc_read_pointer(tuplestorestate,
75  node->eflags);
76  Assert(ptrno == 1);
77  }
78  node->tuplestorestate = tuplestorestate;
79  }
80 
81  /*
82  * If we are not at the end of the tuplestore, or are going backwards, try
83  * to fetch a tuple from tuplestore.
84  */
85  eof_tuplestore = (tuplestorestate == NULL) ||
86  tuplestore_ateof(tuplestorestate);
87 
88  if (!forward && eof_tuplestore)
89  {
90  if (!node->eof_underlying)
91  {
92  /*
93  * When reversing direction at tuplestore EOF, the first
94  * gettupleslot call will fetch the last-added tuple; but we want
95  * to return the one before that, if possible. So do an extra
96  * fetch.
97  */
98  if (!tuplestore_advance(tuplestorestate, forward))
99  return NULL; /* the tuplestore must be empty */
100  }
101  eof_tuplestore = false;
102  }
103 
104  /*
105  * If we can fetch another tuple from the tuplestore, return it.
106  */
107  slot = node->ss.ps.ps_ResultTupleSlot;
108  if (!eof_tuplestore)
109  {
110  if (tuplestore_gettupleslot(tuplestorestate, forward, false, slot))
111  return slot;
112  if (forward)
113  eof_tuplestore = true;
114  }
115 
116  /*
117  * If necessary, try to fetch another row from the subplan.
118  *
119  * Note: the eof_underlying state variable exists to short-circuit further
120  * subplan calls. It's not optional, unfortunately, because some plan
121  * node types are not robust about being called again when they've already
122  * returned NULL.
123  */
124  if (eof_tuplestore && !node->eof_underlying)
125  {
126  PlanState *outerNode;
127  TupleTableSlot *outerslot;
128 
129  /*
130  * We can only get here with forward==true, so no need to worry about
131  * which direction the subplan will go.
132  */
133  outerNode = outerPlanState(node);
134  outerslot = ExecProcNode(outerNode);
135  if (TupIsNull(outerslot))
136  {
137  node->eof_underlying = true;
138  return NULL;
139  }
140 
141  /*
142  * Append a copy of the returned tuple to tuplestore. NOTE: because
143  * the tuplestore is certainly in EOF state, its read position will
144  * move forward over the added tuple. This is what we want.
145  */
146  if (tuplestorestate)
147  tuplestore_puttupleslot(tuplestorestate, outerslot);
148 
149  /*
150  * We can just return the subplan's returned tuple, without copying.
151  */
152  return outerslot;
153  }
154 
155  /*
156  * Nothing left ...
157  */
158  return ExecClearTuple(slot);
159 }
void tuplestore_puttupleslot(Tuplestorestate *state, TupleTableSlot *slot)
Definition: tuplestore.c:708
bool tuplestore_advance(Tuplestorestate *state, bool forward)
Definition: tuplestore.c:1110
Tuplestorestate * tuplestorestate
Definition: execnodes.h:1829
#define ScanDirectionIsForward(direction)
Definition: sdir.h:55
#define castNode(_type_, nodeptr)
Definition: nodes.h:586
void tuplestore_set_eflags(Tuplestorestate *state, int eflags)
Definition: tuplestore.c:359
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:475
ScanState ss
Definition: execnodes.h:1826
EState * state
Definition: execnodes.h:913
ScanDirection es_direction
Definition: execnodes.h:477
PlanState ps
Definition: execnodes.h:1191
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:945
#define outerPlanState(node)
Definition: execnodes.h:965
ScanDirection
Definition: sdir.h:22
#define TupIsNull(slot)
Definition: tuptable.h:146
bool eof_underlying
Definition: execnodes.h:1828
Tuplestorestate * tuplestore_begin_heap(bool randomAccess, bool interXact, int maxKBytes)
Definition: tuplestore.c:318
static TupleTableSlot * ExecProcNode(PlanState *node)
Definition: executor.h:233
int work_mem
Definition: globals.c:122
bool tuplestore_gettupleslot(Tuplestorestate *state, bool forward, bool copy, TupleTableSlot *slot)
Definition: tuplestore.c:1078
#define Assert(condition)
Definition: c.h:699
#define EXEC_FLAG_MARK
Definition: executor.h:61
int tuplestore_alloc_read_pointer(Tuplestorestate *state, int eflags)
Definition: tuplestore.c:383
#define CHECK_FOR_INTERRUPTS()
Definition: miscadmin.h:98
bool tuplestore_ateof(Tuplestorestate *state)
Definition: tuplestore.c:557
#define PG_USED_FOR_ASSERTS_ONLY
Definition: c.h:123

◆ ExecMaterialMarkPos()

void ExecMaterialMarkPos ( MaterialState node)

Definition at line 269 of file nodeMaterial.c.

References Assert, MaterialState::eflags, EXEC_FLAG_MARK, tuplestore_copy_read_pointer(), tuplestore_trim(), and MaterialState::tuplestorestate.

Referenced by ExecMarkPos().

270 {
271  Assert(node->eflags & EXEC_FLAG_MARK);
272 
273  /*
274  * if we haven't materialized yet, just return.
275  */
276  if (!node->tuplestorestate)
277  return;
278 
279  /*
280  * copy the active read pointer to the mark.
281  */
283 
284  /*
285  * since we may have advanced the mark, try to truncate the tuplestore.
286  */
288 }
Tuplestorestate * tuplestorestate
Definition: execnodes.h:1829
void tuplestore_trim(Tuplestorestate *state)
Definition: tuplestore.c:1360
void tuplestore_copy_read_pointer(Tuplestorestate *state, int srcptr, int destptr)
Definition: tuplestore.c:1268
#define Assert(condition)
Definition: c.h:699
#define EXEC_FLAG_MARK
Definition: executor.h:61

◆ ExecMaterialRestrPos()

void ExecMaterialRestrPos ( MaterialState node)

Definition at line 297 of file nodeMaterial.c.

References Assert, MaterialState::eflags, EXEC_FLAG_MARK, tuplestore_copy_read_pointer(), and MaterialState::tuplestorestate.

Referenced by ExecRestrPos().

298 {
299  Assert(node->eflags & EXEC_FLAG_MARK);
300 
301  /*
302  * if we haven't materialized yet, just return.
303  */
304  if (!node->tuplestorestate)
305  return;
306 
307  /*
308  * copy the mark to the active read pointer.
309  */
311 }
Tuplestorestate * tuplestorestate
Definition: execnodes.h:1829
void tuplestore_copy_read_pointer(Tuplestorestate *state, int srcptr, int destptr)
Definition: tuplestore.c:1268
#define Assert(condition)
Definition: c.h:699
#define EXEC_FLAG_MARK
Definition: executor.h:61

◆ ExecReScanMaterial()

void ExecReScanMaterial ( MaterialState node)

Definition at line 320 of file nodeMaterial.c.

References PlanState::chgParam, MaterialState::eflags, MaterialState::eof_underlying, EXEC_FLAG_REWIND, ExecClearTuple(), ExecReScan(), outerPlan, outerPlanState, ScanState::ps, PlanState::ps_ResultTupleSlot, MaterialState::ss, tuplestore_end(), tuplestore_rescan(), and MaterialState::tuplestorestate.

Referenced by ExecReScan().

321 {
323 
325 
326  if (node->eflags != 0)
327  {
328  /*
329  * If we haven't materialized yet, just return. If outerplan's
330  * chgParam is not NULL then it will be re-scanned by ExecProcNode,
331  * else no reason to re-scan it at all.
332  */
333  if (!node->tuplestorestate)
334  return;
335 
336  /*
337  * If subnode is to be rescanned then we forget previous stored
338  * results; we have to re-read the subplan and re-store. Also, if we
339  * told tuplestore it needn't support rescan, we lose and must
340  * re-read. (This last should not happen in common cases; else our
341  * caller lied by not passing EXEC_FLAG_REWIND to us.)
342  *
343  * Otherwise we can just rewind and rescan the stored output. The
344  * state of the subnode does not change.
345  */
346  if (outerPlan->chgParam != NULL ||
347  (node->eflags & EXEC_FLAG_REWIND) == 0)
348  {
350  node->tuplestorestate = NULL;
351  if (outerPlan->chgParam == NULL)
352  ExecReScan(outerPlan);
353  node->eof_underlying = false;
354  }
355  else
357  }
358  else
359  {
360  /* In this case we are just passing on the subquery's output */
361 
362  /*
363  * if chgParam of subnode is not null then plan will be re-scanned by
364  * first ExecProcNode.
365  */
366  if (outerPlan->chgParam == NULL)
367  ExecReScan(outerPlan);
368  node->eof_underlying = false;
369  }
370 }
void tuplestore_rescan(Tuplestorestate *state)
Definition: tuplestore.c:1233
Tuplestorestate * tuplestorestate
Definition: execnodes.h:1829
void ExecReScan(PlanState *node)
Definition: execAmi.c:76
TupleTableSlot * ExecClearTuple(TupleTableSlot *slot)
Definition: execTuples.c:475
ScanState ss
Definition: execnodes.h:1826
PlanState ps
Definition: execnodes.h:1191
TupleTableSlot * ps_ResultTupleSlot
Definition: execnodes.h:945
#define outerPlanState(node)
Definition: execnodes.h:965
bool eof_underlying
Definition: execnodes.h:1828
#define EXEC_FLAG_REWIND
Definition: executor.h:59
Bitmapset * chgParam
Definition: execnodes.h:940
#define outerPlan(node)
Definition: plannodes.h:176
void tuplestore_end(Tuplestorestate *state)
Definition: tuplestore.c:453