0001-Add-partial-path-only-when-rel-s-consider_parallel-i.patch
text/x-patch
Filename: 0001-Add-partial-path-only-when-rel-s-consider_parallel-i.patch
Type: text/x-patch
Part: 0
Patch
Format: format-patch
Series: patch 0001
Subject: Add partial path only when rel's consider_parallel is true.
| File | + | − |
|---|---|---|
| src/backend/optimizer/path/allpaths.c | 23 | 18 |
| src/backend/optimizer/prep/prepunion.c | 2 | 1 |
| src/backend/optimizer/util/pathnode.c | 6 | 0 |
| src/test/regress/expected/select_parallel.out | 19 | 0 |
| src/test/regress/sql/select_parallel.sql | 6 | 0 |
From 708026f34f6a5d087660930f9cb05aa3e08c130b Mon Sep 17 00:00:00 2001
From: Jeevan Chalke <jeevan.chalke@enterprisedb.com>
Date: Wed, 11 Apr 2018 14:08:13 +0530
Subject: [PATCH] Add partial path only when rel's consider_parallel is true.
Otherwise, it will result in an assertion failure later in the
create_gather_path().
---
src/backend/optimizer/path/allpaths.c | 41 +++++++++++++++------------
src/backend/optimizer/prep/prepunion.c | 3 +-
src/backend/optimizer/util/pathnode.c | 6 ++++
src/test/regress/expected/select_parallel.out | 19 +++++++++++++
src/test/regress/sql/select_parallel.sql | 6 ++++
5 files changed, 56 insertions(+), 19 deletions(-)
diff --git a/src/backend/optimizer/path/allpaths.c b/src/backend/optimizer/path/allpaths.c
index 3ba3f87..c3d0634 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -2242,26 +2242,31 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
pathkeys, required_outer));
}
- /* If consider_parallel is false, there should be no partial paths. */
- Assert(sub_final_rel->consider_parallel ||
- sub_final_rel->partial_pathlist == NIL);
-
- /* Same for partial paths. */
- foreach(lc, sub_final_rel->partial_pathlist)
+ /* If outer rel allows parallelism, do same for partial paths. */
+ if (rel->consider_parallel && bms_is_empty(required_outer))
{
- Path *subpath = (Path *) lfirst(lc);
- List *pathkeys;
-
- /* Convert subpath's pathkeys to outer representation */
- pathkeys = convert_subquery_pathkeys(root,
- rel,
- subpath->pathkeys,
- make_tlist_from_pathtarget(subpath->pathtarget));
+ /* If consider_parallel is false, there should be no partial paths. */
+ Assert(sub_final_rel->consider_parallel ||
+ sub_final_rel->partial_pathlist == NIL);
- /* Generate outer path using this subpath */
- add_partial_path(rel, (Path *)
- create_subqueryscan_path(root, rel, subpath,
- pathkeys, required_outer));
+ /* Same for partial paths. */
+ foreach(lc, sub_final_rel->partial_pathlist)
+ {
+ Path *subpath = (Path *) lfirst(lc);
+ List *pathkeys;
+
+ /* Convert subpath's pathkeys to outer representation */
+ pathkeys = convert_subquery_pathkeys(root,
+ rel,
+ subpath->pathkeys,
+ make_tlist_from_pathtarget(subpath->pathtarget));
+
+ /* Generate outer path using this subpath */
+ add_partial_path(rel, (Path *)
+ create_subqueryscan_path(root, rel, subpath,
+ pathkeys,
+ required_outer));
+ }
}
}
diff --git a/src/backend/optimizer/prep/prepunion.c b/src/backend/optimizer/prep/prepunion.c
index 8d86e98..61d0770 100644
--- a/src/backend/optimizer/prep/prepunion.c
+++ b/src/backend/optimizer/prep/prepunion.c
@@ -330,7 +330,8 @@ recurse_set_operations(Node *setOp, PlannerInfo *root,
* to build a partial path for this relation. But there's no point in
* considering any path but the cheapest.
*/
- if (final_rel->partial_pathlist != NIL)
+ if (rel->consider_parallel && bms_is_empty(rel->lateral_relids) &&
+ final_rel->partial_pathlist != NIL)
{
Path *partial_subpath;
Path *partial_path;
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index bd9442c..561466c 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -770,6 +770,12 @@ add_partial_path(RelOptInfo *parent_rel, Path *new_path)
/* Check for query cancel. */
CHECK_FOR_INTERRUPTS();
+ /* Path to be added must be parallel safe. */
+ Assert(new_path->parallel_safe);
+
+ /* Relation should be OK for parallelism, too. */
+ Assert(parent_rel->consider_parallel);
+
/*
* As in add_path, throw out any paths which are dominated by the new
* path, but throw out the new path if some existing path dominates it.
diff --git a/src/test/regress/expected/select_parallel.out b/src/test/regress/expected/select_parallel.out
index fb209de..a07cd50 100644
--- a/src/test/regress/expected/select_parallel.out
+++ b/src/test/regress/expected/select_parallel.out
@@ -955,4 +955,23 @@ ORDER BY 1, 2, 3;
------------------------------+---------------------------+-------------+--------------
(0 rows)
+-- test interation between subquery and partial_paths
+SET LOCAL min_parallel_table_scan_size TO 0;
+CREATE VIEW tenk1_vw_sec WITH (security_barrier) AS SELECT * FROM tenk1;
+EXPLAIN (COSTS OFF)
+SELECT 1 FROM tenk1_vw_sec WHERE EXISTS (SELECT 1 WHERE unique1 = 0);
+ QUERY PLAN
+-------------------------------------------------------------------
+ Subquery Scan on tenk1_vw_sec
+ Filter: (alternatives: SubPlan 1 or hashed SubPlan 2)
+ -> Gather
+ Workers Planned: 4
+ -> Parallel Index Only Scan using tenk1_unique1 on tenk1
+ SubPlan 1
+ -> Result
+ One-Time Filter: (tenk1_vw_sec.unique1 = 0)
+ SubPlan 2
+ -> Result
+(10 rows)
+
rollback;
diff --git a/src/test/regress/sql/select_parallel.sql b/src/test/regress/sql/select_parallel.sql
index ac26d68..7db75b0 100644
--- a/src/test/regress/sql/select_parallel.sql
+++ b/src/test/regress/sql/select_parallel.sql
@@ -383,4 +383,10 @@ ORDER BY 1;
SELECT * FROM information_schema.foreign_data_wrapper_options
ORDER BY 1, 2, 3;
+-- test interation between subquery and partial_paths
+SET LOCAL min_parallel_table_scan_size TO 0;
+CREATE VIEW tenk1_vw_sec WITH (security_barrier) AS SELECT * FROM tenk1;
+EXPLAIN (COSTS OFF)
+SELECT 1 FROM tenk1_vw_sec WHERE EXISTS (SELECT 1 WHERE unique1 = 0);
+
rollback;
--
1.8.3.1