|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * IDENTIFICATION
|
11 |
| - * $PostgreSQL: pgsql/src/backend/executor/nodeLimit.c,v 1.30 2007/05/04 01:13:43 tgl Exp $ |
| 11 | + * $PostgreSQL: pgsql/src/backend/executor/nodeLimit.c,v 1.31 2007/05/17 19:35:08 tgl Exp $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
@@ -55,17 +55,22 @@ ExecLimit(LimitState *node)
|
55 | 55 | case LIMIT_INITIAL:
|
56 | 56 |
|
57 | 57 | /*
|
58 |
| - * If backwards scan, just return NULL without changing state. |
| 58 | + * First call for this node, so compute limit/offset. (We can't do |
| 59 | + * this any earlier, because parameters from upper nodes will not |
| 60 | + * be set during ExecInitLimit.) This also sets position = 0 |
| 61 | + * and changes the state to LIMIT_RESCAN. |
59 | 62 | */
|
60 |
| - if (!ScanDirectionIsForward(direction)) |
61 |
| - return NULL; |
| 63 | + recompute_limits(node); |
| 64 | + |
| 65 | + /* FALL THRU */ |
| 66 | + |
| 67 | + case LIMIT_RESCAN: |
62 | 68 |
|
63 | 69 | /*
|
64 |
| - * First call for this scan, so compute limit/offset. (We can't do |
65 |
| - * this any earlier, because parameters from upper nodes may not |
66 |
| - * be set until now.) This also sets position = 0. |
| 70 | + * If backwards scan, just return NULL without changing state. |
67 | 71 | */
|
68 |
| - recompute_limits(node); |
| 72 | + if (!ScanDirectionIsForward(direction)) |
| 73 | + return NULL; |
69 | 74 |
|
70 | 75 | /*
|
71 | 76 | * Check for empty window; if so, treat like empty subplan.
|
@@ -217,7 +222,7 @@ ExecLimit(LimitState *node)
|
217 | 222 | }
|
218 | 223 |
|
219 | 224 | /*
|
220 |
| - * Evaluate the limit/offset expressions --- done at start of each scan. |
| 225 | + * Evaluate the limit/offset expressions --- done at startup or rescan. |
221 | 226 | *
|
222 | 227 | * This is also a handy place to reset the current-position state info.
|
223 | 228 | */
|
@@ -281,6 +286,9 @@ recompute_limits(LimitState *node)
|
281 | 286 | node->position = 0;
|
282 | 287 | node->subSlot = NULL;
|
283 | 288 |
|
| 289 | + /* Set state-machine state */ |
| 290 | + node->lstate = LIMIT_RESCAN; |
| 291 | + |
284 | 292 | /*
|
285 | 293 | * If we have a COUNT, and our input is a Sort node, notify it that it can
|
286 | 294 | * use bounded sort.
|
@@ -403,8 +411,12 @@ ExecEndLimit(LimitState *node)
|
403 | 411 | void
|
404 | 412 | ExecReScanLimit(LimitState *node, ExprContext *exprCtxt)
|
405 | 413 | {
|
406 |
| - /* resetting lstate will force offset/limit recalculation */ |
407 |
| - node->lstate = LIMIT_INITIAL; |
| 414 | + /* |
| 415 | + * Recompute limit/offset in case parameters changed, and reset the |
| 416 | + * state machine. We must do this before rescanning our child node, |
| 417 | + * in case it's a Sort that we are passing the parameters down to. |
| 418 | + */ |
| 419 | + recompute_limits(node); |
408 | 420 |
|
409 | 421 | /*
|
410 | 422 | * if chgParam of subnode is not null then plan will be re-scanned by
|
|
0 commit comments