aboutsummaryrefslogtreecommitdiff
path: root/src/backend/optimizer
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/optimizer')
-rw-r--r--src/backend/optimizer/path/allpaths.c13
-rw-r--r--src/backend/optimizer/plan/planner.c3
2 files changed, 14 insertions, 2 deletions
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 5db1688bf04..5f74d3b36d9 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -620,7 +620,20 @@ set_rel_consider_parallel(PlannerInfo *root, RelOptInfo *rel,
* the SubqueryScanPath as not parallel-safe. (Note that
* set_subquery_pathlist() might push some of these quals down
* into the subquery itself, but that doesn't change anything.)
+ *
+ * We can't push sub-select containing LIMIT/OFFSET to workers as
+ * there is no guarantee that the row order will be fully
+ * deterministic, and applying LIMIT/OFFSET will lead to
+ * inconsistent results at the top-level. (In some cases, where
+ * the result is ordered, we could relax this restriction. But it
+ * doesn't currently seem worth expending extra effort to do so.)
*/
+ {
+ Query *subquery = castNode(Query, rte->subquery);
+
+ if (limit_needed(subquery))
+ return;
+ }
break;
case RTE_JOIN:
diff --git a/src/backend/optimizer/plan/planner.c b/src/backend/optimizer/plan/planner.c
index 96bf0601a8e..e589471fee8 100644
--- a/src/backend/optimizer/plan/planner.c
+++ b/src/backend/optimizer/plan/planner.c
@@ -123,7 +123,6 @@ static void preprocess_rowmarks(PlannerInfo *root);
static double preprocess_limit(PlannerInfo *root,
double tuple_fraction,
int64 *offset_est, int64 *count_est);
-static bool limit_needed(Query *parse);
static void remove_useless_groupby_columns(PlannerInfo *root);
static List *preprocess_groupclause(PlannerInfo *root, List *force);
static List *extract_rollup_sets(List *groupingSets);
@@ -2870,7 +2869,7 @@ preprocess_limit(PlannerInfo *root, double tuple_fraction,
* a key distinction: here we need hard constants in OFFSET/LIMIT, whereas
* in preprocess_limit it's good enough to consider estimated values.
*/
-static bool
+bool
limit_needed(Query *parse)
{
Node *node;