*
*
* 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 $
*
*-------------------------------------------------------------------------
*/
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.
}
/*
- * 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.
*/
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.
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
* Portions Copyright (c) 1994, Regents of the University of California
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.88 2007/04/26 23:24:44 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/executor/nodeSubplan.c,v 1.89 2007/05/17 19:35:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
planstate->chgParam = bms_add_member(planstate->chgParam, paramid);
}
+ /*
+ * Now that we've set up its parameters, we can reset the subplan.
+ */
ExecReScan(planstate, NULL);
/*
subLinkType == ALL_SUBLINK)
elog(ERROR, "ANY/ALL subselect unsupported as initplan");
+ /*
+ * By definition, an initplan has no parameters from our query level,
+ * but it could have some from an outer level. Rescan it if needed.
+ */
if (planstate->chgParam != NULL)
ExecReScan(planstate, NULL);
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California
*
- * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.173 2007/05/04 01:13:45 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/execnodes.h,v 1.174 2007/05/17 19:35:08 tgl Exp $
*
*-------------------------------------------------------------------------
*/
typedef enum
{
LIMIT_INITIAL, /* initial state for LIMIT node */
+ LIMIT_RESCAN, /* rescan after recomputing parameters */
LIMIT_EMPTY, /* there are no returnable rows */
LIMIT_INWINDOW, /* have returned a row in the window */
LIMIT_SUBPLANEOF, /* at EOF of subplan (within window) */
| 904 | 793 | UIAAAA
(5 rows)
+-- Stress test for variable LIMIT in conjunction with bounded-heap sorting
+SELECT
+ (SELECT n
+ FROM (VALUES (1)) AS x,
+ (SELECT n FROM generate_series(1,10) AS n
+ ORDER BY n LIMIT 1 OFFSET s-1) AS y) AS z
+ FROM generate_series(1,10) AS s;
+ z
+----
+ 1
+ 2
+ 3
+ 4
+ 5
+ 6
+ 7
+ 8
+ 9
+ 10
+(10 rows)
+
SELECT ''::text AS five, unique1, unique2, stringu1
FROM onek
ORDER BY unique1 LIMIT 5 OFFSET 900;
+
+-- Stress test for variable LIMIT in conjunction with bounded-heap sorting
+
+SELECT
+ (SELECT n
+ FROM (VALUES (1)) AS x,
+ (SELECT n FROM generate_series(1,10) AS n
+ ORDER BY n LIMIT 1 OFFSET s-1) AS y) AS z
+ FROM generate_series(1,10) AS s;