Skip to content

Commit

Permalink
Copy partitioned_rels lists to avoid shared substructure.
Browse files Browse the repository at this point in the history
Otherwise, set_plan_refs() can get applied to the same list
multiple times through different references, leading to chaos.

Amit Langote, Dilip Kumar, and Robert Haas, reviewed by Ashutosh
Bapat.  Original report by Sveinn Sveinsson.

Discussion: http://postgr.es/m/[email protected]
  • Loading branch information
robertmhaas committed May 19, 2017
1 parent cf5389f commit b522759
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 3 deletions.
6 changes: 3 additions & 3 deletions src/backend/optimizer/util/pathnode.c
Original file line number Diff line number Diff line change
Expand Up @@ -1216,7 +1216,7 @@ create_append_path(RelOptInfo *rel, List *subpaths, Relids required_outer,
pathnode->path.parallel_workers = parallel_workers;
pathnode->path.pathkeys = NIL; /* result is always considered
* unsorted */
pathnode->partitioned_rels = partitioned_rels;
pathnode->partitioned_rels = list_copy(partitioned_rels);
pathnode->subpaths = subpaths;

/*
Expand Down Expand Up @@ -1276,7 +1276,7 @@ create_merge_append_path(PlannerInfo *root,
pathnode->path.parallel_safe = rel->consider_parallel;
pathnode->path.parallel_workers = 0;
pathnode->path.pathkeys = pathkeys;
pathnode->partitioned_rels = partitioned_rels;
pathnode->partitioned_rels = list_copy(partitioned_rels);
pathnode->subpaths = subpaths;

/*
Expand Down Expand Up @@ -3238,7 +3238,7 @@ create_modifytable_path(PlannerInfo *root, RelOptInfo *rel,
pathnode->operation = operation;
pathnode->canSetTag = canSetTag;
pathnode->nominalRelation = nominalRelation;
pathnode->partitioned_rels = partitioned_rels;
pathnode->partitioned_rels = list_copy(partitioned_rels);
pathnode->resultRelations = resultRelations;
pathnode->subpaths = subpaths;
pathnode->subroots = subroots;
Expand Down
31 changes: 31 additions & 0 deletions src/test/regress/expected/inherit.out
Original file line number Diff line number Diff line change
Expand Up @@ -1918,3 +1918,34 @@ explain (costs off) select * from mcrparted where a = 20 and c > 20; -- scans mc
(7 rows)

drop table mcrparted;
-- check that partitioned table Appends cope with being referenced in
-- subplans
create table parted_minmax (a int, b varchar(16)) partition by range (a);
create table parted_minmax1 partition of parted_minmax for values from (1) to (10);
create index parted_minmax1i on parted_minmax1 (a, b);
insert into parted_minmax values (1,'12345');
explain (costs off) select min(a), max(a) from parted_minmax where b = '12345';
QUERY PLAN
-------------------------------------------------------------------------------------------------------
Result
InitPlan 1 (returns $0)
-> Limit
-> Merge Append
Sort Key: parted_minmax1.a
-> Index Only Scan using parted_minmax1i on parted_minmax1
Index Cond: ((a IS NOT NULL) AND (b = '12345'::text))
InitPlan 2 (returns $1)
-> Limit
-> Merge Append
Sort Key: parted_minmax1_1.a DESC
-> Index Only Scan Backward using parted_minmax1i on parted_minmax1 parted_minmax1_1
Index Cond: ((a IS NOT NULL) AND (b = '12345'::text))
(13 rows)

select min(a), max(a) from parted_minmax where b = '12345';
min | max
-----+-----
1 | 1
(1 row)

drop table parted_minmax;
10 changes: 10 additions & 0 deletions src/test/regress/sql/inherit.sql
Original file line number Diff line number Diff line change
Expand Up @@ -661,3 +661,13 @@ explain (costs off) select * from mcrparted where a > -1; -- scans all partition
explain (costs off) select * from mcrparted where a = 20 and abs(b) = 10 and c > 10; -- scans mcrparted4
explain (costs off) select * from mcrparted where a = 20 and c > 20; -- scans mcrparted3, mcrparte4, mcrparte5
drop table mcrparted;

-- check that partitioned table Appends cope with being referenced in
-- subplans
create table parted_minmax (a int, b varchar(16)) partition by range (a);
create table parted_minmax1 partition of parted_minmax for values from (1) to (10);
create index parted_minmax1i on parted_minmax1 (a, b);
insert into parted_minmax values (1,'12345');
explain (costs off) select min(a), max(a) from parted_minmax where b = '12345';
select min(a), max(a) from parted_minmax where b = '12345';
drop table parted_minmax;

0 comments on commit b522759

Please sign in to comment.