aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeLimit.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2007-05-17 19:35:08 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2007-05-17 19:35:08 +0000
commitb11123b675d9317f771d2bc44f72594de329098d (patch)
treebf3e5080edbe144393337623b932f0b5c1540459 /src/backend/executor/nodeLimit.c
parent64058429c54afb49a679c58e5ff699640bd42502 (diff)
downloadpostgresql-b11123b675d9317f771d2bc44f72594de329098d.tar.gz
postgresql-b11123b675d9317f771d2bc44f72594de329098d.zip
Fix parameter recalculation for Limit nodes: during a ReScan call we must
recompute the limit/offset immediately, so that the updated values are available when the child's ReScan function is invoked. Add a regression test for this, too. Bug is new in HEAD (due to the bounded-sorting patch) so no need for back-patch. I did not do anything about merging this signaling with chgParam processing, but if we were to do that we'd still need to compute the updated values at this point rather than during the first ProcNode call. Per observation and test case from Greg Stark, though I didn't use his patch.
Diffstat (limited to 'src/backend/executor/nodeLimit.c')
-rw-r--r--src/backend/executor/nodeLimit.c34
1 files changed, 23 insertions, 11 deletions
diff --git a/src/backend/executor/nodeLimit.c b/src/backend/executor/nodeLimit.c
index 9d40952647d..76296cfd877 100644
--- a/src/backend/executor/nodeLimit.c
+++ b/src/backend/executor/nodeLimit.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeLimit.c,v 1.30 2007/05/04 01:13:43 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeLimit.c,v 1.31 2007/05/17 19:35:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -55,17 +55,22 @@ ExecLimit(LimitState *node)
case LIMIT_INITIAL:
/*
- * If backwards scan, just return NULL without changing state.
+ * First call for this node, so compute limit/offset. (We can't do
+ * this any earlier, because parameters from upper nodes will not
+ * be set during ExecInitLimit.) This also sets position = 0
+ * and changes the state to LIMIT_RESCAN.
*/
- if (!ScanDirectionIsForward(direction))
- return NULL;
+ recompute_limits(node);
+
+ /* FALL THRU */
+
+ case LIMIT_RESCAN:
/*
- * First call for this scan, so compute limit/offset. (We can't do
- * this any earlier, because parameters from upper nodes may not
- * be set until now.) This also sets position = 0.
+ * If backwards scan, just return NULL without changing state.
*/
- recompute_limits(node);
+ if (!ScanDirectionIsForward(direction))
+ return NULL;
/*
* Check for empty window; if so, treat like empty subplan.
@@ -217,7 +222,7 @@ ExecLimit(LimitState *node)
}
/*
- * Evaluate the limit/offset expressions --- done at start of each scan.
+ * Evaluate the limit/offset expressions --- done at startup or rescan.
*
* This is also a handy place to reset the current-position state info.
*/
@@ -281,6 +286,9 @@ recompute_limits(LimitState *node)
node->position = 0;
node->subSlot = NULL;
+ /* Set state-machine state */
+ node->lstate = LIMIT_RESCAN;
+
/*
* If we have a COUNT, and our input is a Sort node, notify it that it can
* use bounded sort.
@@ -403,8 +411,12 @@ ExecEndLimit(LimitState *node)
void
ExecReScanLimit(LimitState *node, ExprContext *exprCtxt)
{
- /* resetting lstate will force offset/limit recalculation */
- node->lstate = LIMIT_INITIAL;
+ /*
+ * Recompute limit/offset in case parameters changed, and reset the
+ * state machine. We must do this before rescanning our child node,
+ * in case it's a Sort that we are passing the parameters down to.
+ */
+ recompute_limits(node);
/*
* if chgParam of subnode is not null then plan will be re-scanned by