Copy partitioned_rels lists to avoid shared substructure.
authorRobert Haas <rhaas@postgresql.org>
Fri, 19 May 2017 19:23:42 +0000 (15:23 -0400)
committerRobert Haas <rhaas@postgresql.org>
Fri, 19 May 2017 19:26:05 +0000 (15:26 -0400)
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/20170517141151.1435.79890@wrigleys.postgresql.org

src/backend/optimizer/util/pathnode.c
src/test/regress/expected/inherit.out
src/test/regress/sql/inherit.sql

index 46778aaefd3c983b944290d2d630db10b329accf..ec4a093d9fb375c5ff6d5b944b5e4f783d851dfd 100644 (file)
@@ -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;
 
    /*
@@ -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;
 
    /*
@@ -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;
index af7090ba0d61af84e5f4166c55caddbaddfb3344..35d182d599233021900d2f04946d4cb80633b0a2 100644 (file)
@@ -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;
index 7f34f43ec0c2cd05dd6b3beadced9d8317bb3b26..70fe971d51f8c03db8a8b00fcf716a3ccf798a75 100644 (file)
@@ -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;