@@ -303,14 +303,11 @@ recompute_limits(LimitState *node)
303303
304304/*
305305 * If we have a COUNT, and our input is a Sort node, notify it that it can
306- * use bounded sort. Also, if our input is a MergeAppend, we can apply the
307- * same bound to any Sorts that are direct children of the MergeAppend,
308- * since the MergeAppend surely need read no more than that many tuples from
309- * any one input. We also have to be prepared to look through a Result,
310- * since the planner might stick one atop MergeAppend for projection purposes.
311- * We can also accept one or more levels of subqueries that have no quals or
312- * SRFs (that is, each subquery is just projecting columns) between the LIMIT
313- * and any of the above.
306+ * use bounded sort. We can also pass down the bound through plan nodes
307+ * that cannot remove or combine input rows; for example, if our input is a
308+ * MergeAppend, we can apply the same bound to any Sorts that are direct
309+ * children of the MergeAppend, since the MergeAppend surely need not read
310+ * more than that many tuples from any one input.
314311 *
315312 * This is a bit of a kluge, but we don't have any more-abstract way of
316313 * communicating between the two nodes; and it doesn't seem worth trying
@@ -324,27 +321,10 @@ static void
324321pass_down_bound (LimitState * node , PlanState * child_node )
325322{
326323 /*
327- * If the child is a subquery that does no filtering (no predicates)
328- * and does not have any SRFs in the target list then we can potentially
329- * push the limit through the subquery. It is possible that we could have
330- * multiple subqueries, so tunnel through them all.
324+ * Since this function recurses, in principle we should check stack depth
325+ * here. In practice, it's probably pointless since the earlier node
326+ * initialization tree traversal would surely have consumed more stack.
331327 */
332- while (IsA (child_node , SubqueryScanState ))
333- {
334- SubqueryScanState * subqueryScanState ;
335-
336- subqueryScanState = (SubqueryScanState * ) child_node ;
337-
338- /*
339- * Non-empty predicates or an SRF means we cannot push down the limit.
340- */
341- if (subqueryScanState -> ss .ps .qual != NULL ||
342- expression_returns_set ((Node * ) child_node -> plan -> targetlist ))
343- return ;
344-
345- /* Use the child in the following checks */
346- child_node = subqueryScanState -> subplan ;
347- }
348328
349329 if (IsA (child_node , SortState ))
350330 {
@@ -365,6 +345,7 @@ pass_down_bound(LimitState *node, PlanState *child_node)
365345 }
366346 else if (IsA (child_node , MergeAppendState ))
367347 {
348+ /* Pass down the bound through MergeAppend */
368349 MergeAppendState * maState = (MergeAppendState * ) child_node ;
369350 int i ;
370351
@@ -374,13 +355,34 @@ pass_down_bound(LimitState *node, PlanState *child_node)
374355 else if (IsA (child_node , ResultState ))
375356 {
376357 /*
358+ * We also have to be prepared to look through a Result, since the
359+ * planner might stick one atop MergeAppend for projection purposes.
360+ *
377361 * If Result supported qual checking, we'd have to punt on seeing a
378362 * qual. Note that having a resconstantqual is not a showstopper: if
379363 * that fails we're not getting any rows at all.
380364 */
381365 if (outerPlanState (child_node ))
382366 pass_down_bound (node , outerPlanState (child_node ));
383367 }
368+ else if (IsA (child_node , SubqueryScanState ))
369+ {
370+ /*
371+ * We can also look through SubqueryScan, but only if it has no qual
372+ * (otherwise it might discard rows).
373+ */
374+ SubqueryScanState * subqueryState = (SubqueryScanState * ) child_node ;
375+
376+ if (subqueryState -> ss .ps .qual == NULL )
377+ pass_down_bound (node , subqueryState -> subplan );
378+ }
379+
380+ /*
381+ * In principle we could look through any plan node type that is certain
382+ * not to discard or combine input rows. In practice, there are not many
383+ * node types that the planner might put between Sort and Limit, so trying
384+ * to be very general is not worth the trouble.
385+ */
384386}
385387
386388/* ----------------------------------------------------------------
0 commit comments