Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 8355897

Browse files
committed
Mark read/write expanded values as read-only in ValuesNext(), too.
Further thought about bug #14174 motivated me to try the case of a R/W datum being returned from a VALUES list, and sure enough it was broken. Fix that. Also add a regression test case exercising the same scenario for FunctionScan. That's not broken right now, because the function's result will get shoved into a tuplestore between generation and use; but it could easily become broken whenever we get around to optimizing FunctionScan better. There don't seem to be any other places where we put the result of expression evaluation into a virtual tuple slot that could then be the source for Vars of further expression evaluation, so I think this is the end of this bug.
1 parent a102f98 commit 8355897

File tree

3 files changed

+58
-0
lines changed

3 files changed

+58
-0
lines changed

src/backend/executor/nodeValuesscan.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
#include "executor/executor.h"
2727
#include "executor/nodeValuesscan.h"
28+
#include "utils/expandeddatum.h"
2829

2930

3031
static TupleTableSlot *ValuesNext(ValuesScanState *node);
@@ -94,6 +95,7 @@ ValuesNext(ValuesScanState *node)
9495
List *exprstatelist;
9596
Datum *values;
9697
bool *isnull;
98+
Form_pg_attribute *att;
9799
ListCell *lc;
98100
int resind;
99101

@@ -129,6 +131,7 @@ ValuesNext(ValuesScanState *node)
129131
*/
130132
values = slot->tts_values;
131133
isnull = slot->tts_isnull;
134+
att = slot->tts_tupleDescriptor->attrs;
132135

133136
resind = 0;
134137
foreach(lc, exprstatelist)
@@ -139,6 +142,17 @@ ValuesNext(ValuesScanState *node)
139142
econtext,
140143
&isnull[resind],
141144
NULL);
145+
146+
/*
147+
* We must force any R/W expanded datums to read-only state, in
148+
* case they are multiply referenced in the plan node's output
149+
* expressions, or in case we skip the output projection and the
150+
* output column is multiply referenced in higher plan nodes.
151+
*/
152+
values[resind] = MakeExpandedObjectReadOnly(values[resind],
153+
isnull[resind],
154+
att[resind]->attlen);
155+
142156
resind++;
143157
}
144158

src/test/regress/expected/plpgsql.out

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5340,6 +5340,38 @@ select i, a from
53405340
1 | {1,1}
53415341
(1 row)
53425342

5343+
explain (verbose, costs off)
5344+
select consumes_rw_array(a), a from returns_rw_array(1) a;
5345+
QUERY PLAN
5346+
--------------------------------------------
5347+
Function Scan on public.returns_rw_array a
5348+
Output: consumes_rw_array(a), a
5349+
Function Call: returns_rw_array(1)
5350+
(3 rows)
5351+
5352+
select consumes_rw_array(a), a from returns_rw_array(1) a;
5353+
consumes_rw_array | a
5354+
-------------------+-------
5355+
1 | {1,1}
5356+
(1 row)
5357+
5358+
explain (verbose, costs off)
5359+
select consumes_rw_array(a), a from
5360+
(values (returns_rw_array(1)), (returns_rw_array(2))) v(a);
5361+
QUERY PLAN
5362+
---------------------------------------------------------------------
5363+
Values Scan on "*VALUES*"
5364+
Output: consumes_rw_array("*VALUES*".column1), "*VALUES*".column1
5365+
(2 rows)
5366+
5367+
select consumes_rw_array(a), a from
5368+
(values (returns_rw_array(1)), (returns_rw_array(2))) v(a);
5369+
consumes_rw_array | a
5370+
-------------------+-------
5371+
1 | {1,1}
5372+
2 | {2,2}
5373+
(2 rows)
5374+
53435375
--
53445376
-- Test access to call stack
53455377
--

src/test/regress/sql/plpgsql.sql

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4225,6 +4225,18 @@ select i, a from
42254225
(select returns_rw_array(1) as a offset 0) ss,
42264226
lateral consumes_rw_array(a) i;
42274227
4228+
explain (verbose, costs off)
4229+
select consumes_rw_array(a), a from returns_rw_array(1) a;
4230+
4231+
select consumes_rw_array(a), a from returns_rw_array(1) a;
4232+
4233+
explain (verbose, costs off)
4234+
select consumes_rw_array(a), a from
4235+
(values (returns_rw_array(1)), (returns_rw_array(2))) v(a);
4236+
4237+
select consumes_rw_array(a), a from
4238+
(values (returns_rw_array(1)), (returns_rw_array(2))) v(a);
4239+
42284240
42294241
--
42304242
-- Test access to call stack

0 commit comments

Comments
 (0)