diff options
author | Robert Haas <rhaas@postgresql.org> | 2017-08-21 14:43:01 -0400 |
---|---|---|
committer | Robert Haas <rhaas@postgresql.org> | 2017-08-21 14:19:44 -0400 |
commit | 1f6d515a67ec98194c23a5db25660856c9aab944 (patch) | |
tree | 11ea85be0cf33a654d1578baf13530422cf938e3 /src/backend/executor/nodeLimit.c | |
parent | 79ccd7cbd5ca44bee0191d12e9e65abf702899e7 (diff) | |
download | postgresql-1f6d515a67ec98194c23a5db25660856c9aab944.tar.gz postgresql-1f6d515a67ec98194c23a5db25660856c9aab944.zip |
Push limit through subqueries to underlying sort, where possible.
Douglas Doole, reviewed by Ashutosh Bapat and by me. Minor formatting
change by me.
Discussion: http://postgr.es/m/CADE5jYLuugnEEUsyW6Q_4mZFYTxHxaVCQmGAsF0yiY8ZDggi-w@mail.gmail.com
Diffstat (limited to 'src/backend/executor/nodeLimit.c')
-rw-r--r-- | src/backend/executor/nodeLimit.c | 26 |
1 files changed, 26 insertions, 0 deletions
diff --git a/src/backend/executor/nodeLimit.c b/src/backend/executor/nodeLimit.c index ac5a2ff0e60..09af1a5d8b3 100644 --- a/src/backend/executor/nodeLimit.c +++ b/src/backend/executor/nodeLimit.c @@ -308,6 +308,9 @@ recompute_limits(LimitState *node) * since the MergeAppend surely need read no more than that many tuples from * any one input. We also have to be prepared to look through a Result, * since the planner might stick one atop MergeAppend for projection purposes. + * We can also accept one or more levels of subqueries that have no quals or + * SRFs (that is, each subquery is just projecting columns) between the LIMIT + * and any of the above. * * This is a bit of a kluge, but we don't have any more-abstract way of * communicating between the two nodes; and it doesn't seem worth trying @@ -320,6 +323,29 @@ recompute_limits(LimitState *node) static void pass_down_bound(LimitState *node, PlanState *child_node) { + /* + * If the child is a subquery that does no filtering (no predicates) + * and does not have any SRFs in the target list then we can potentially + * push the limit through the subquery. It is possible that we could have + * multiple subqueries, so tunnel through them all. + */ + while (IsA(child_node, SubqueryScanState)) + { + SubqueryScanState *subqueryScanState; + + subqueryScanState = (SubqueryScanState *) child_node; + + /* + * Non-empty predicates or an SRF means we cannot push down the limit. + */ + if (subqueryScanState->ss.ps.qual != NULL || + expression_returns_set((Node *) child_node->plan->targetlist)) + return; + + /* Use the child in the following checks */ + child_node = subqueryScanState->subplan; + } + if (IsA(child_node, SortState)) { SortState *sortState = (SortState *) child_node; |