PostgreSQL Source Code  git master
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros
nodeLimit.h File Reference
#include "nodes/execnodes.h"
Include dependency graph for nodeLimit.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Functions

LimitStateExecInitLimit (Limit *node, EState *estate, int eflags)
 
TupleTableSlotExecLimit (LimitState *node)
 
void ExecEndLimit (LimitState *node)
 
void ExecReScanLimit (LimitState *node)
 

Function Documentation

void ExecEndLimit ( LimitState node)

Definition at line 426 of file nodeLimit.c.

References ExecEndNode(), ExecFreeExprContext(), outerPlanState, and LimitState::ps.

Referenced by ExecEndNode().

427 {
428  ExecFreeExprContext(&node->ps);
430 }
void ExecEndNode(PlanState *node)
Definition: execProcnode.c:624
void ExecFreeExprContext(PlanState *planstate)
Definition: execUtils.c:684
#define outerPlanState(node)
Definition: execnodes.h:1089
PlanState ps
Definition: execnodes.h:2096
LimitState* ExecInitLimit ( Limit node,
EState estate,
int  eflags 
)

Definition at line 364 of file nodeLimit.c.

References Assert, EXEC_FLAG_MARK, ExecAssignExprContext(), ExecAssignResultTypeFromTL(), ExecInitExpr(), ExecInitNode(), ExecInitResultTupleSlot(), LIMIT_INITIAL, Limit::limitCount, LimitState::limitCount, Limit::limitOffset, LimitState::limitOffset, LimitState::lstate, makeNode, NULL, outerPlan, outerPlanState, PlanState::plan, LimitState::ps, PlanState::ps_ProjInfo, and PlanState::state.

Referenced by ExecInitNode().

365 {
366  LimitState *limitstate;
367  Plan *outerPlan;
368 
369  /* check for unsupported flags */
370  Assert(!(eflags & EXEC_FLAG_MARK));
371 
372  /*
373  * create state structure
374  */
375  limitstate = makeNode(LimitState);
376  limitstate->ps.plan = (Plan *) node;
377  limitstate->ps.state = estate;
378 
379  limitstate->lstate = LIMIT_INITIAL;
380 
381  /*
382  * Miscellaneous initialization
383  *
384  * Limit nodes never call ExecQual or ExecProject, but they need an
385  * exprcontext anyway to evaluate the limit/offset parameters in.
386  */
387  ExecAssignExprContext(estate, &limitstate->ps);
388 
389  /*
390  * initialize child expressions
391  */
392  limitstate->limitOffset = ExecInitExpr((Expr *) node->limitOffset,
393  (PlanState *) limitstate);
394  limitstate->limitCount = ExecInitExpr((Expr *) node->limitCount,
395  (PlanState *) limitstate);
396 
397  /*
398  * Tuple table initialization (XXX not actually used...)
399  */
400  ExecInitResultTupleSlot(estate, &limitstate->ps);
401 
402  /*
403  * then initialize outer plan
404  */
405  outerPlan = outerPlan(node);
406  outerPlanState(limitstate) = ExecInitNode(outerPlan, estate, eflags);
407 
408  /*
409  * limit nodes do no projections, so initialize projection info for this
410  * node appropriately
411  */
412  ExecAssignResultTypeFromTL(&limitstate->ps);
413  limitstate->ps.ps_ProjInfo = NULL;
414 
415  return limitstate;
416 }
ProjectionInfo * ps_ProjInfo
Definition: execnodes.h:1078
EState * state
Definition: execnodes.h:1048
LimitStateCond lstate
Definition: execnodes.h:2102
ExprState * limitCount
Definition: execnodes.h:2098
Node * limitOffset
Definition: plannodes.h:852
void ExecAssignResultTypeFromTL(PlanState *planstate)
Definition: execUtils.c:429
ExprState * ExecInitExpr(Expr *node, PlanState *parent)
Definition: execQual.c:4266
void ExecInitResultTupleSlot(EState *estate, PlanState *planstate)
Definition: execTuples.c:832
Node * limitCount
Definition: plannodes.h:853
#define outerPlanState(node)
Definition: execnodes.h:1089
ExprState * limitOffset
Definition: execnodes.h:2097
#define outerPlan(node)
Definition: plannodes.h:159
Plan * plan
Definition: execnodes.h:1046
#define makeNode(_type_)
Definition: nodes.h:556
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
#define EXEC_FLAG_MARK
Definition: executor.h:61
void ExecAssignExprContext(EState *estate, PlanState *planstate)
Definition: execUtils.c:407
PlanState * ExecInitNode(Plan *node, EState *estate, int eflags)
Definition: execProcnode.c:137
PlanState ps
Definition: execnodes.h:2096
TupleTableSlot* ExecLimit ( LimitState node)

Definition at line 40 of file nodeLimit.c.

References Assert, LimitState::count, elog, ERROR, EState::es_direction, ExecProcNode(), LIMIT_EMPTY, LIMIT_INITIAL, LIMIT_INWINDOW, LIMIT_RESCAN, LIMIT_SUBPLANEOF, LIMIT_WINDOWEND, LIMIT_WINDOWSTART, LimitState::lstate, LimitState::noCount, NULL, LimitState::offset, outerPlan, outerPlanState, LimitState::position, LimitState::ps, recompute_limits(), ScanDirectionIsForward, PlanState::state, LimitState::subSlot, and TupIsNull.

Referenced by ExecProcNode().

41 {
42  ScanDirection direction;
43  TupleTableSlot *slot;
45 
46  /*
47  * get information from the node
48  */
49  direction = node->ps.state->es_direction;
50  outerPlan = outerPlanState(node);
51 
52  /*
53  * The main logic is a simple state machine.
54  */
55  switch (node->lstate)
56  {
57  case LIMIT_INITIAL:
58 
59  /*
60  * First call for this node, so compute limit/offset. (We can't do
61  * this any earlier, because parameters from upper nodes will not
62  * be set during ExecInitLimit.) This also sets position = 0 and
63  * changes the state to LIMIT_RESCAN.
64  */
65  recompute_limits(node);
66 
67  /* FALL THRU */
68 
69  case LIMIT_RESCAN:
70 
71  /*
72  * If backwards scan, just return NULL without changing state.
73  */
74  if (!ScanDirectionIsForward(direction))
75  return NULL;
76 
77  /*
78  * Check for empty window; if so, treat like empty subplan.
79  */
80  if (node->count <= 0 && !node->noCount)
81  {
82  node->lstate = LIMIT_EMPTY;
83  return NULL;
84  }
85 
86  /*
87  * Fetch rows from subplan until we reach position > offset.
88  */
89  for (;;)
90  {
91  slot = ExecProcNode(outerPlan);
92  if (TupIsNull(slot))
93  {
94  /*
95  * The subplan returns too few tuples for us to produce
96  * any output at all.
97  */
98  node->lstate = LIMIT_EMPTY;
99  return NULL;
100  }
101  node->subSlot = slot;
102  if (++node->position > node->offset)
103  break;
104  }
105 
106  /*
107  * Okay, we have the first tuple of the window.
108  */
109  node->lstate = LIMIT_INWINDOW;
110  break;
111 
112  case LIMIT_EMPTY:
113 
114  /*
115  * The subplan is known to return no tuples (or not more than
116  * OFFSET tuples, in general). So we return no tuples.
117  */
118  return NULL;
119 
120  case LIMIT_INWINDOW:
121  if (ScanDirectionIsForward(direction))
122  {
123  /*
124  * Forwards scan, so check for stepping off end of window. If
125  * we are at the end of the window, return NULL without
126  * advancing the subplan or the position variable; but change
127  * the state machine state to record having done so.
128  */
129  if (!node->noCount &&
130  node->position - node->offset >= node->count)
131  {
132  node->lstate = LIMIT_WINDOWEND;
133  return NULL;
134  }
135 
136  /*
137  * Get next tuple from subplan, if any.
138  */
139  slot = ExecProcNode(outerPlan);
140  if (TupIsNull(slot))
141  {
142  node->lstate = LIMIT_SUBPLANEOF;
143  return NULL;
144  }
145  node->subSlot = slot;
146  node->position++;
147  }
148  else
149  {
150  /*
151  * Backwards scan, so check for stepping off start of window.
152  * As above, change only state-machine status if so.
153  */
154  if (node->position <= node->offset + 1)
155  {
156  node->lstate = LIMIT_WINDOWSTART;
157  return NULL;
158  }
159 
160  /*
161  * Get previous tuple from subplan; there should be one!
162  */
163  slot = ExecProcNode(outerPlan);
164  if (TupIsNull(slot))
165  elog(ERROR, "LIMIT subplan failed to run backwards");
166  node->subSlot = slot;
167  node->position--;
168  }
169  break;
170 
171  case LIMIT_SUBPLANEOF:
172  if (ScanDirectionIsForward(direction))
173  return NULL;
174 
175  /*
176  * Backing up from subplan EOF, so re-fetch previous tuple; there
177  * should be one! Note previous tuple must be in window.
178  */
179  slot = ExecProcNode(outerPlan);
180  if (TupIsNull(slot))
181  elog(ERROR, "LIMIT subplan failed to run backwards");
182  node->subSlot = slot;
183  node->lstate = LIMIT_INWINDOW;
184  /* position does not change 'cause we didn't advance it before */
185  break;
186 
187  case LIMIT_WINDOWEND:
188  if (ScanDirectionIsForward(direction))
189  return NULL;
190 
191  /*
192  * Backing up from window end: simply re-return the last tuple
193  * fetched from the subplan.
194  */
195  slot = node->subSlot;
196  node->lstate = LIMIT_INWINDOW;
197  /* position does not change 'cause we didn't advance it before */
198  break;
199 
200  case LIMIT_WINDOWSTART:
201  if (!ScanDirectionIsForward(direction))
202  return NULL;
203 
204  /*
205  * Advancing after having backed off window start: simply
206  * re-return the last tuple fetched from the subplan.
207  */
208  slot = node->subSlot;
209  node->lstate = LIMIT_INWINDOW;
210  /* position does not change 'cause we didn't change it before */
211  break;
212 
213  default:
214  elog(ERROR, "impossible LIMIT state: %d",
215  (int) node->lstate);
216  slot = NULL; /* keep compiler quiet */
217  break;
218  }
219 
220  /* Return the current tuple */
221  Assert(!TupIsNull(slot));
222 
223  return slot;
224 }
TupleTableSlot * ExecProcNode(PlanState *node)
Definition: execProcnode.c:380
#define ScanDirectionIsForward(direction)
Definition: sdir.h:55
bool noCount
Definition: execnodes.h:2101
EState * state
Definition: execnodes.h:1048
LimitStateCond lstate
Definition: execnodes.h:2102
int64 position
Definition: execnodes.h:2103
ScanDirection es_direction
Definition: execnodes.h:369
int64 count
Definition: execnodes.h:2100
#define ERROR
Definition: elog.h:43
int64 offset
Definition: execnodes.h:2099
#define outerPlanState(node)
Definition: execnodes.h:1089
ScanDirection
Definition: sdir.h:22
#define TupIsNull(slot)
Definition: tuptable.h:138
#define outerPlan(node)
Definition: plannodes.h:159
#define NULL
Definition: c.h:226
#define Assert(condition)
Definition: c.h:670
TupleTableSlot * subSlot
Definition: execnodes.h:2104
static void recompute_limits(LimitState *node)
Definition: nodeLimit.c:232
#define elog
Definition: elog.h:219
PlanState ps
Definition: execnodes.h:2096
void ExecReScanLimit ( LimitState node)

Definition at line 434 of file nodeLimit.c.

References PlanState::chgParam, ExecReScan(), PlanState::lefttree, NULL, LimitState::ps, and recompute_limits().

Referenced by ExecReScan().

435 {
436  /*
437  * Recompute limit/offset in case parameters changed, and reset the state
438  * machine. We must do this before rescanning our child node, in case
439  * it's a Sort that we are passing the parameters down to.
440  */
441  recompute_limits(node);
442 
443  /*
444  * if chgParam of subnode is not null then plan will be re-scanned by
445  * first ExecProcNode.
446  */
447  if (node->ps.lefttree->chgParam == NULL)
448  ExecReScan(node->ps.lefttree);
449 }
void ExecReScan(PlanState *node)
Definition: execAmi.c:73
struct PlanState * lefttree
Definition: execnodes.h:1062
Bitmapset * chgParam
Definition: execnodes.h:1071
#define NULL
Definition: c.h:226
static void recompute_limits(LimitState *node)
Definition: nodeLimit.c:232
PlanState ps
Definition: execnodes.h:2096