Skip to content

Commit 1b5bbe4

Browse files
committed
Fix EvalPlanQualStart to handle partitioned result rels correctly.
The es_root_result_relations array needs to be shallow-copied in the same way as the main es_result_relations array, else EPQ rechecks on partitioned result relations fail, as seen in bug #15677 from Norbert Benkocs. Amit Langote, isolation test case added by me Discussion: https://postgr.es/m/15677-0bf089579b4cd02d@postgresql.org Discussion: https://postgr.es/m/19321.1554567786@sss.pgh.pa.us
1 parent 67999b3 commit 1b5bbe4

File tree

3 files changed

+42
-1
lines changed

3 files changed

+42
-1
lines changed

src/backend/executor/execMain.c

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3101,7 +3101,7 @@ EvalPlanQualStart(EPQState *epqstate, EState *parentestate, Plan *planTree)
31013101
* es_param_exec_vals, etc.
31023102
*
31033103
* The ResultRelInfo array management is trickier than it looks. We
3104-
* create a fresh array for the child but copy all the content from the
3104+
* create fresh arrays for the child but copy all the content from the
31053105
* parent. This is because it's okay for the child to share any
31063106
* per-relation state the parent has already created --- but if the child
31073107
* sets up any ResultRelInfo fields, such as its own junkfilter, that
@@ -3118,6 +3118,7 @@ EvalPlanQualStart(EPQState *epqstate, EState *parentestate, Plan *planTree)
31183118
if (parentestate->es_num_result_relations > 0)
31193119
{
31203120
int numResultRelations = parentestate->es_num_result_relations;
3121+
int numRootResultRels = parentestate->es_num_root_result_relations;
31213122
ResultRelInfo *resultRelInfos;
31223123

31233124
resultRelInfos = (ResultRelInfo *)
@@ -3126,6 +3127,17 @@ EvalPlanQualStart(EPQState *epqstate, EState *parentestate, Plan *planTree)
31263127
numResultRelations * sizeof(ResultRelInfo));
31273128
estate->es_result_relations = resultRelInfos;
31283129
estate->es_num_result_relations = numResultRelations;
3130+
3131+
/* Also transfer partitioned root result relations. */
3132+
if (numRootResultRels > 0)
3133+
{
3134+
resultRelInfos = (ResultRelInfo *)
3135+
palloc(numRootResultRels * sizeof(ResultRelInfo));
3136+
memcpy(resultRelInfos, parentestate->es_root_result_relations,
3137+
numRootResultRels * sizeof(ResultRelInfo));
3138+
estate->es_root_result_relations = resultRelInfos;
3139+
estate->es_num_root_result_relations = numRootResultRels;
3140+
}
31293141
}
31303142
/* es_result_relation_info must NOT be copied */
31313143
/* es_trig_target_relations must NOT be copied */

src/test/isolation/expected/eval-plan-qual.out

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -263,3 +263,15 @@ step multireadwcte: <... completed>
263263
subid id
264264

265265
1 1
266+
267+
starting permutation: simplepartupdate complexpartupdate c1 c2
268+
step simplepartupdate:
269+
update parttbl set a = a;
270+
271+
step complexpartupdate:
272+
with u as (update parttbl set a = a returning parttbl.*)
273+
update parttbl set a = u.a from u;
274+
<waiting ...>
275+
step c1: COMMIT;
276+
step complexpartupdate: <... completed>
277+
step c2: COMMIT;

src/test/isolation/specs/eval-plan-qual.spec

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,13 +24,18 @@ setup
2424

2525
CREATE TABLE jointest AS SELECT generate_series(1,10) AS id, 0 AS data;
2626
CREATE INDEX ON jointest(id);
27+
28+
CREATE TABLE parttbl (a int) PARTITION BY LIST (a);
29+
CREATE TABLE parttbl1 PARTITION OF parttbl FOR VALUES IN (1);
30+
INSERT INTO parttbl VALUES (1);
2731
}
2832

2933
teardown
3034
{
3135
DROP TABLE accounts;
3236
DROP TABLE p CASCADE;
3337
DROP TABLE table_a, table_b, jointest;
38+
DROP TABLE parttbl;
3439
}
3540

3641
session "s1"
@@ -99,6 +104,12 @@ step "selectjoinforupdate" {
99104
select * from jointest a join jointest b on a.id=b.id for update;
100105
}
101106

107+
# test for EPQ on a partitioned result table
108+
109+
step "simplepartupdate" {
110+
update parttbl set a = a;
111+
}
112+
102113

103114
session "s2"
104115
setup { BEGIN ISOLATION LEVEL READ COMMITTED; }
@@ -133,6 +144,10 @@ step "updateforcip3" {
133144
}
134145
step "wrtwcte" { UPDATE table_a SET value = 'tableAValue2' WHERE id = 1; }
135146
step "wrjt" { UPDATE jointest SET data = 42 WHERE id = 7; }
147+
step "complexpartupdate" {
148+
with u as (update parttbl set a = a returning parttbl.*)
149+
update parttbl set a = u.a from u;
150+
}
136151
step "c2" { COMMIT; }
137152

138153
session "s3"
@@ -177,3 +192,5 @@ permutation "updateforcip" "updateforcip3" "c1" "c2" "read_a"
177192
permutation "wrtwcte" "readwcte" "c1" "c2"
178193
permutation "wrjt" "selectjoinforupdate" "c2" "c1"
179194
permutation "wrtwcte" "multireadwcte" "c1" "c2"
195+
196+
permutation "simplepartupdate" "complexpartupdate" "c1" "c2"

0 commit comments

Comments
 (0)