aboutsummaryrefslogtreecommitdiff
path: root/src/backend/executor/nodeLimit.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2010-11-18 11:53:49 -0500
committerTom Lane <tgl@sss.pgh.pa.us>2010-11-18 11:54:34 -0500
commit48c348f86ce09c668af7cf271757c3f156f28344 (patch)
treeea8223183f60b7a8bdd0171dbd22df4c02c09408 /src/backend/executor/nodeLimit.c
parent1fc2d60d8c9d8096373e94a8f8c9b28d2082b7d3 (diff)
downloadpostgresql-48c348f86ce09c668af7cf271757c3f156f28344.tar.gz
postgresql-48c348f86ce09c668af7cf271757c3f156f28344.zip
Dept of second thoughts: don't try to push LIMIT below a SRF.
If we have Limit->Result->Sort, the Result might be projecting a tlist that contains a set-returning function. If so, it's possible for the SRF to sometimes return zero rows, which means we could need to fetch more than N rows from the Sort in order to satisfy LIMIT N. So top-N sorting cannot be used in this scenario.
Diffstat (limited to 'src/backend/executor/nodeLimit.c')
-rw-r--r--src/backend/executor/nodeLimit.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/src/backend/executor/nodeLimit.c b/src/backend/executor/nodeLimit.c
index 5ed8664f66f..c939752f37a 100644
--- a/src/backend/executor/nodeLimit.c
+++ b/src/backend/executor/nodeLimit.c
@@ -23,6 +23,7 @@
#include "executor/executor.h"
#include "executor/nodeLimit.h"
+#include "nodes/nodeFuncs.h"
static void recompute_limits(LimitState *node);
static void pass_down_bound(LimitState *node, PlanState *child_node);
@@ -344,7 +345,19 @@ pass_down_bound(LimitState *node, PlanState *child_node)
}
else if (IsA(child_node, ResultState))
{
- if (outerPlanState(child_node))
+ /*
+ * An extra consideration here is that if the Result is projecting
+ * a targetlist that contains any SRFs, we can't assume that every
+ * input tuple generates an output tuple, so a Sort underneath
+ * might need to return more than N tuples to satisfy LIMIT N.
+ * So we cannot use bounded sort.
+ *
+ * If Result supported qual checking, we'd have to punt on seeing
+ * a qual, too. Note that having a resconstantqual is not a
+ * showstopper: if that fails we're not getting any rows at all.
+ */
+ if (outerPlanState(child_node) &&
+ !expression_returns_set((Node *) child_node->plan->targetlist))
pass_down_bound(node, outerPlanState(child_node));
}
}