diff --git a/src/backend/executor/nodeCtescan.c b/src/backend/executor/nodeCtescan.c index 218619c760..24700dd396 100644 --- a/src/backend/executor/nodeCtescan.c +++ b/src/backend/executor/nodeCtescan.c @@ -107,6 +107,13 @@ CteScanNext(CteScanState *node) return NULL; } + /* + * There are corner cases where the subplan could change which + * tuplestore read pointer is active, so be sure to reselect ours + * before storing the tuple we got. + */ + tuplestore_select_read_pointer(tuplestorestate, node->readptr); + /* * Append a copy of the returned tuple to tuplestore. NOTE: because * our read pointer is certainly in EOF state, its read position will @@ -178,6 +185,12 @@ ExecInitCteScan(CteScan *node, EState *estate, int eflags) * we might be asked to rescan the CTE even though upper levels didn't * tell us to be prepared to do it efficiently. Annoying, since this * prevents truncation of the tuplestore. XXX FIXME + * + * Note: if we are in an EPQ recheck plan tree, it's likely that no access + * to the tuplestore is needed at all, making this even more annoying. + * It's not worth improving that as long as all the read pointers would + * have REWIND anyway, but if we ever improve this logic then that aspect + * should be considered too. */ eflags |= EXEC_FLAG_REWIND; diff --git a/src/test/isolation/expected/eval-plan-qual.out b/src/test/isolation/expected/eval-plan-qual.out index eb40717679..fed01459cf 100644 --- a/src/test/isolation/expected/eval-plan-qual.out +++ b/src/test/isolation/expected/eval-plan-qual.out @@ -217,3 +217,18 @@ id data id data 9 0 9 0 10 0 10 0 step c1: COMMIT; + +starting permutation: wrtwcte multireadwcte c1 c2 +step wrtwcte: UPDATE table_a SET value = 'tableAValue2' WHERE id = 1; +step multireadwcte: + WITH updated AS ( + UPDATE table_a SET value = 'tableAValue3' WHERE id = 1 RETURNING id + ) + SELECT (SELECT id FROM updated) AS subid, * FROM updated; + +step c1: COMMIT; +step c2: COMMIT; +step multireadwcte: <... completed> +subid id + +1 1 diff --git a/src/test/isolation/specs/eval-plan-qual.spec b/src/test/isolation/specs/eval-plan-qual.spec index d2b34ec7cc..51ab61dc86 100644 --- a/src/test/isolation/specs/eval-plan-qual.spec +++ b/src/test/isolation/specs/eval-plan-qual.spec @@ -139,6 +139,14 @@ step "readwcte" { SELECT * FROM cte2; } +# this test exercises a different CTE misbehavior, cf bug #14870 +step "multireadwcte" { + WITH updated AS ( + UPDATE table_a SET value = 'tableAValue3' WHERE id = 1 RETURNING id + ) + SELECT (SELECT id FROM updated) AS subid, * FROM updated; +} + teardown { COMMIT; } permutation "wx1" "wx2" "c1" "c2" "read" @@ -151,3 +159,4 @@ permutation "wx2" "lockwithvalues" "c2" "c1" "read" permutation "updateforss" "readforss" "c1" "c2" permutation "wrtwcte" "readwcte" "c1" "c2" permutation "wrjt" "selectjoinforupdate" "c2" "c1" +permutation "wrtwcte" "multireadwcte" "c1" "c2"