prohibit_parallel_limit_subselect_v1.patch
application/octet-stream
Filename: prohibit_parallel_limit_subselect_v1.patch
Type: application/octet-stream
Part: 0
Patch
Same data as JSON:
GET /api/v1/attachments/:id/patch
the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes.
API reference →
Format: unified
Series: patch v1
| File | + | − |
|---|---|---|
| src/backend/optimizer/util/clauses.c | 36 | 1 |
diff --git a/src/backend/optimizer/util/clauses.c b/src/backend/optimizer/util/clauses.c
index a04ad6e99e6..aecb6dfa72b 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -1208,12 +1208,25 @@ max_parallel_hazard_walker(Node *node, max_parallel_hazard_context *context)
/*
* Really we should not see SubLink during a max_interesting == restricted
- * scan, but if we do, return true.
+ * scan, but if we do, return true. Also, we can't push sub-select
+ * containing LIMIT/OFFSET to workers as that can change the results
+ * depending on what is beneath LIMIT node. So, consider that case as
+ * parallel-unsafe.
*/
else if (IsA(node, SubLink))
{
+ Query *subquery;
+ SubLink *sublink = (SubLink *) node;
+
if (max_parallel_hazard_test(PROPARALLEL_RESTRICTED, context))
return true;
+
+ subquery = castNode(Query, sublink->subselect);
+ if (subquery->limitOffset || subquery->limitCount)
+ {
+ context->max_hazard = PROPARALLEL_UNSAFE;
+ return true;
+ }
}
/*
@@ -1274,6 +1287,7 @@ max_parallel_hazard_walker(Node *node, max_parallel_hazard_context *context)
else if (IsA(node, Query))
{
Query *query = (Query *) node;
+ ListCell *rt;
/* SELECT FOR UPDATE/SHARE must be treated as unsafe */
if (query->rowMarks != NULL)
@@ -1282,6 +1296,27 @@ max_parallel_hazard_walker(Node *node, max_parallel_hazard_context *context)
return true;
}
+ /*
+ * We can't push sub-select containing LIMIT/OFFSET to workers as that
+ * can change the results depending on what is beneath LIMIT node.
+ * So, consider that case as parallel-unsafe.
+ */
+ foreach(rt, query->rtable)
+ {
+ RangeTblEntry *rte = (RangeTblEntry *) lfirst(rt);
+
+ if (rte->rtekind == RTE_SUBQUERY)
+ {
+ Query *subquery = castNode(Query, rte->subquery);
+
+ if (subquery->limitOffset || subquery->limitCount)
+ {
+ context->max_hazard = PROPARALLEL_UNSAFE;
+ return true;
+ }
+ }
+ }
+
/* Recurse into subselects */
return query_tree_walker(query,
max_parallel_hazard_walker,