summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Haas2017-05-19 19:23:42 +0000
committerRobert Haas2017-05-19 19:26:05 +0000
commitb522759508dae17535f8cd20598a50a409a97f4d (patch)
treefa0c7964d143e8a1d43d774dbc4d82a1b236107c
parentcf5389f5b57af714d002d532add291f87ddb0062 (diff)
Copy partitioned_rels lists to avoid shared substructure.
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]
-rw-r--r--src/backend/optimizer/util/pathnode.c6
-rw-r--r--src/test/regress/expected/inherit.out31
-rw-r--r--src/test/regress/sql/inherit.sql10
3 files changed, 44 insertions, 3 deletions
diff --git a/src/backend/optimizer/util/pathnode.c b/src/backend/optimizer/util/pathnode.c
index 46778aaefd..ec4a093d9f 100644
--- a/src/backend/optimizer/util/pathnode.c
+++ b/src/backend/optimizer/util/pathnode.c
@@ -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;
diff --git a/src/test/regress/expected/inherit.out b/src/test/regress/expected/inherit.out
index af7090ba0d..35d182d599 100644
--- a/src/test/regress/expected/inherit.out
+++ b/src/test/regress/expected/inherit.out
@@ -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;
diff --git a/src/test/regress/sql/inherit.sql b/src/test/regress/sql/inherit.sql
index 7f34f43ec0..70fe971d51 100644
--- a/src/test/regress/sql/inherit.sql
+++ b/src/test/regress/sql/inherit.sql
@@ -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;