Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit dc1057f

Browse files
committed
Prevent generation of bogus subquery scan paths.
Commit 0927d2f didn't check that consider_parallel was set for the target relation or account for the possibility that required_outer might be non-empty. To prevent future bugs of this ilk, add some assertions to add_partial_path and do a bit of future-proofing of the code recently added to recurse_set_operations. Report by Andreas Seltenreich. Patch by Jeevan Chalke. Review by Amit Kapila and by me. Discussion: http://postgr.es/m/CAM2+6=U+9otsyF2fYB8x_2TBeHTR90itarqW=qAEjN-kHaC7kw@mail.gmail.com
1 parent f35f30f commit dc1057f

File tree

5 files changed

+56
-19
lines changed

5 files changed

+56
-19
lines changed

src/backend/optimizer/path/allpaths.c

+23-18
Original file line numberDiff line numberDiff line change
@@ -2243,26 +2243,31 @@ set_subquery_pathlist(PlannerInfo *root, RelOptInfo *rel,
22432243
pathkeys, required_outer));
22442244
}
22452245

2246-
/* If consider_parallel is false, there should be no partial paths. */
2247-
Assert(sub_final_rel->consider_parallel ||
2248-
sub_final_rel->partial_pathlist == NIL);
2249-
2250-
/* Same for partial paths. */
2251-
foreach(lc, sub_final_rel->partial_pathlist)
2246+
/* If outer rel allows parallelism, do same for partial paths. */
2247+
if (rel->consider_parallel && bms_is_empty(required_outer))
22522248
{
2253-
Path *subpath = (Path *) lfirst(lc);
2254-
List *pathkeys;
2255-
2256-
/* Convert subpath's pathkeys to outer representation */
2257-
pathkeys = convert_subquery_pathkeys(root,
2258-
rel,
2259-
subpath->pathkeys,
2260-
make_tlist_from_pathtarget(subpath->pathtarget));
2249+
/* If consider_parallel is false, there should be no partial paths. */
2250+
Assert(sub_final_rel->consider_parallel ||
2251+
sub_final_rel->partial_pathlist == NIL);
22612252

2262-
/* Generate outer path using this subpath */
2263-
add_partial_path(rel, (Path *)
2264-
create_subqueryscan_path(root, rel, subpath,
2265-
pathkeys, required_outer));
2253+
/* Same for partial paths. */
2254+
foreach(lc, sub_final_rel->partial_pathlist)
2255+
{
2256+
Path *subpath = (Path *) lfirst(lc);
2257+
List *pathkeys;
2258+
2259+
/* Convert subpath's pathkeys to outer representation */
2260+
pathkeys = convert_subquery_pathkeys(root,
2261+
rel,
2262+
subpath->pathkeys,
2263+
make_tlist_from_pathtarget(subpath->pathtarget));
2264+
2265+
/* Generate outer path using this subpath */
2266+
add_partial_path(rel, (Path *)
2267+
create_subqueryscan_path(root, rel, subpath,
2268+
pathkeys,
2269+
required_outer));
2270+
}
22662271
}
22672272
}
22682273

src/backend/optimizer/prep/prepunion.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -330,7 +330,8 @@ recurse_set_operations(Node *setOp, PlannerInfo *root,
330330
* to build a partial path for this relation. But there's no point in
331331
* considering any path but the cheapest.
332332
*/
333-
if (final_rel->partial_pathlist != NIL)
333+
if (rel->consider_parallel && bms_is_empty(rel->lateral_relids) &&
334+
final_rel->partial_pathlist != NIL)
334335
{
335336
Path *partial_subpath;
336337
Path *partial_path;

src/backend/optimizer/util/pathnode.c

+6
Original file line numberDiff line numberDiff line change
@@ -770,6 +770,12 @@ add_partial_path(RelOptInfo *parent_rel, Path *new_path)
770770
/* Check for query cancel. */
771771
CHECK_FOR_INTERRUPTS();
772772

773+
/* Path to be added must be parallel safe. */
774+
Assert(new_path->parallel_safe);
775+
776+
/* Relation should be OK for parallelism, too. */
777+
Assert(parent_rel->consider_parallel);
778+
773779
/*
774780
* As in add_path, throw out any paths which are dominated by the new
775781
* path, but throw out the new path if some existing path dominates it.

src/test/regress/expected/select_parallel.out

+19
Original file line numberDiff line numberDiff line change
@@ -955,4 +955,23 @@ ORDER BY 1, 2, 3;
955955
------------------------------+---------------------------+-------------+--------------
956956
(0 rows)
957957

958+
-- test interation between subquery and partial_paths
959+
SET LOCAL min_parallel_table_scan_size TO 0;
960+
CREATE VIEW tenk1_vw_sec WITH (security_barrier) AS SELECT * FROM tenk1;
961+
EXPLAIN (COSTS OFF)
962+
SELECT 1 FROM tenk1_vw_sec WHERE EXISTS (SELECT 1 WHERE unique1 = 0);
963+
QUERY PLAN
964+
-------------------------------------------------------------------
965+
Subquery Scan on tenk1_vw_sec
966+
Filter: (alternatives: SubPlan 1 or hashed SubPlan 2)
967+
-> Gather
968+
Workers Planned: 4
969+
-> Parallel Index Only Scan using tenk1_unique1 on tenk1
970+
SubPlan 1
971+
-> Result
972+
One-Time Filter: (tenk1_vw_sec.unique1 = 0)
973+
SubPlan 2
974+
-> Result
975+
(10 rows)
976+
958977
rollback;

src/test/regress/sql/select_parallel.sql

+6
Original file line numberDiff line numberDiff line change
@@ -383,4 +383,10 @@ ORDER BY 1;
383383
SELECT * FROM information_schema.foreign_data_wrapper_options
384384
ORDER BY 1, 2, 3;
385385

386+
-- test interation between subquery and partial_paths
387+
SET LOCAL min_parallel_table_scan_size TO 0;
388+
CREATE VIEW tenk1_vw_sec WITH (security_barrier) AS SELECT * FROM tenk1;
389+
EXPLAIN (COSTS OFF)
390+
SELECT 1 FROM tenk1_vw_sec WHERE EXISTS (SELECT 1 WHERE unique1 = 0);
391+
386392
rollback;

0 commit comments

Comments
 (0)