mirror of
https://git.postgresql.org/git/postgresql.git
synced 2024-09-04 14:47:19 +02:00
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.
This commit is contained in:
parent
a102f98e26
commit
8355897ff2
@ -25,6 +25,7 @@
|
|||||||
|
|
||||||
#include "executor/executor.h"
|
#include "executor/executor.h"
|
||||||
#include "executor/nodeValuesscan.h"
|
#include "executor/nodeValuesscan.h"
|
||||||
|
#include "utils/expandeddatum.h"
|
||||||
|
|
||||||
|
|
||||||
static TupleTableSlot *ValuesNext(ValuesScanState *node);
|
static TupleTableSlot *ValuesNext(ValuesScanState *node);
|
||||||
@ -94,6 +95,7 @@ ValuesNext(ValuesScanState *node)
|
|||||||
List *exprstatelist;
|
List *exprstatelist;
|
||||||
Datum *values;
|
Datum *values;
|
||||||
bool *isnull;
|
bool *isnull;
|
||||||
|
Form_pg_attribute *att;
|
||||||
ListCell *lc;
|
ListCell *lc;
|
||||||
int resind;
|
int resind;
|
||||||
|
|
||||||
@ -129,6 +131,7 @@ ValuesNext(ValuesScanState *node)
|
|||||||
*/
|
*/
|
||||||
values = slot->tts_values;
|
values = slot->tts_values;
|
||||||
isnull = slot->tts_isnull;
|
isnull = slot->tts_isnull;
|
||||||
|
att = slot->tts_tupleDescriptor->attrs;
|
||||||
|
|
||||||
resind = 0;
|
resind = 0;
|
||||||
foreach(lc, exprstatelist)
|
foreach(lc, exprstatelist)
|
||||||
@ -139,6 +142,17 @@ ValuesNext(ValuesScanState *node)
|
|||||||
econtext,
|
econtext,
|
||||||
&isnull[resind],
|
&isnull[resind],
|
||||||
NULL);
|
NULL);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* We must force any R/W expanded datums to read-only state, in
|
||||||
|
* case they are multiply referenced in the plan node's output
|
||||||
|
* expressions, or in case we skip the output projection and the
|
||||||
|
* output column is multiply referenced in higher plan nodes.
|
||||||
|
*/
|
||||||
|
values[resind] = MakeExpandedObjectReadOnly(values[resind],
|
||||||
|
isnull[resind],
|
||||||
|
att[resind]->attlen);
|
||||||
|
|
||||||
resind++;
|
resind++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5340,6 +5340,38 @@ select i, a from
|
|||||||
1 | {1,1}
|
1 | {1,1}
|
||||||
(1 row)
|
(1 row)
|
||||||
|
|
||||||
|
explain (verbose, costs off)
|
||||||
|
select consumes_rw_array(a), a from returns_rw_array(1) a;
|
||||||
|
QUERY PLAN
|
||||||
|
--------------------------------------------
|
||||||
|
Function Scan on public.returns_rw_array a
|
||||||
|
Output: consumes_rw_array(a), a
|
||||||
|
Function Call: returns_rw_array(1)
|
||||||
|
(3 rows)
|
||||||
|
|
||||||
|
select consumes_rw_array(a), a from returns_rw_array(1) a;
|
||||||
|
consumes_rw_array | a
|
||||||
|
-------------------+-------
|
||||||
|
1 | {1,1}
|
||||||
|
(1 row)
|
||||||
|
|
||||||
|
explain (verbose, costs off)
|
||||||
|
select consumes_rw_array(a), a from
|
||||||
|
(values (returns_rw_array(1)), (returns_rw_array(2))) v(a);
|
||||||
|
QUERY PLAN
|
||||||
|
---------------------------------------------------------------------
|
||||||
|
Values Scan on "*VALUES*"
|
||||||
|
Output: consumes_rw_array("*VALUES*".column1), "*VALUES*".column1
|
||||||
|
(2 rows)
|
||||||
|
|
||||||
|
select consumes_rw_array(a), a from
|
||||||
|
(values (returns_rw_array(1)), (returns_rw_array(2))) v(a);
|
||||||
|
consumes_rw_array | a
|
||||||
|
-------------------+-------
|
||||||
|
1 | {1,1}
|
||||||
|
2 | {2,2}
|
||||||
|
(2 rows)
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Test access to call stack
|
-- Test access to call stack
|
||||||
--
|
--
|
||||||
|
@ -4225,6 +4225,18 @@ select i, a from
|
|||||||
(select returns_rw_array(1) as a offset 0) ss,
|
(select returns_rw_array(1) as a offset 0) ss,
|
||||||
lateral consumes_rw_array(a) i;
|
lateral consumes_rw_array(a) i;
|
||||||
|
|
||||||
|
explain (verbose, costs off)
|
||||||
|
select consumes_rw_array(a), a from returns_rw_array(1) a;
|
||||||
|
|
||||||
|
select consumes_rw_array(a), a from returns_rw_array(1) a;
|
||||||
|
|
||||||
|
explain (verbose, costs off)
|
||||||
|
select consumes_rw_array(a), a from
|
||||||
|
(values (returns_rw_array(1)), (returns_rw_array(2))) v(a);
|
||||||
|
|
||||||
|
select consumes_rw_array(a), a from
|
||||||
|
(values (returns_rw_array(1)), (returns_rw_array(2))) v(a);
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- Test access to call stack
|
-- Test access to call stack
|
||||||
|
Loading…
Reference in New Issue
Block a user