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

Commit d102aaf

Browse files
committed
Restore the portal-level snapshot for simple expressions, too.
Commits 84f5c29 et al missed the need to cover plpgsql's "simple expression" code path. If the first thing we execute after a COMMIT/ROLLBACK is one of those, rather than a full-fledged SPI command, we must explicitly do EnsurePortalSnapshotExists() to make sure we have an outer snapshot. Note that it wouldn't be good enough to just push a snapshot for the duration of the expression execution: what comes back might be toasted, so we'd better have a snapshot protecting it. The test case demonstrating this fact cheats a bit by marking a SQL function immutable even though it fetches from a table. That's nothing that users haven't been seen to do, though. Per report from Jim Nasby. Back-patch to v11, like the previous fix. Discussion: https://postgr.es/m/378885e4-f85f-fc28-6c91-c4d1c080bf26@amazon.com
1 parent 8e63884 commit d102aaf

File tree

3 files changed

+49
-0
lines changed

3 files changed

+49
-0
lines changed

src/pl/plpgsql/src/expected/plpgsql_transaction.out

+18
Original file line numberDiff line numberDiff line change
@@ -430,6 +430,24 @@ SELECT * FROM test1;
430430
---+---
431431
(0 rows)
432432

433+
-- detoast result of simple expression after commit
434+
CREATE TEMP TABLE test4(f1 text);
435+
ALTER TABLE test4 ALTER COLUMN f1 SET STORAGE EXTERNAL; -- disable compression
436+
INSERT INTO test4 SELECT repeat('xyzzy', 2000);
437+
-- immutable mark is a bit of a lie, but it serves to make call a simple expr
438+
-- that will return a still-toasted value
439+
CREATE FUNCTION data_source(i int) RETURNS TEXT LANGUAGE sql
440+
AS 'select f1 from test4' IMMUTABLE;
441+
DO $$
442+
declare x text;
443+
begin
444+
for i in 1..3 loop
445+
x := data_source(i);
446+
commit;
447+
end loop;
448+
raise notice 'length(x) = %', length(x);
449+
end $$;
450+
NOTICE: length(x) = 10000
433451
-- operations on composite types vs. internal transactions
434452
DO LANGUAGE plpgsql $$
435453
declare

src/pl/plpgsql/src/pl_exec.c

+10
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
#include "plpgsql.h"
3939
#include "storage/proc.h"
4040
#include "tcop/cmdtag.h"
41+
#include "tcop/pquery.h"
4142
#include "tcop/tcopprot.h"
4243
#include "tcop/utility.h"
4344
#include "utils/array.h"
@@ -5958,6 +5959,15 @@ exec_eval_simple_expr(PLpgSQL_execstate *estate,
59585959
expr->expr_simple_lxid == curlxid)
59595960
return false;
59605961

5962+
/*
5963+
* Ensure that there's a portal-level snapshot, in case this simple
5964+
* expression is the first thing evaluated after a COMMIT or ROLLBACK.
5965+
* We'd have to do this anyway before executing the expression, so we
5966+
* might as well do it now to ensure that any possible replanning doesn't
5967+
* need to take a new snapshot.
5968+
*/
5969+
EnsurePortalSnapshotExists();
5970+
59615971
/*
59625972
* Check to see if the cached plan has been invalidated. If not, and this
59635973
* is the first use in the current transaction, save a plan refcount in

src/pl/plpgsql/src/sql/plpgsql_transaction.sql

+21
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,27 @@ $$;
354354
SELECT * FROM test1;
355355

356356

357+
-- detoast result of simple expression after commit
358+
CREATE TEMP TABLE test4(f1 text);
359+
ALTER TABLE test4 ALTER COLUMN f1 SET STORAGE EXTERNAL; -- disable compression
360+
INSERT INTO test4 SELECT repeat('xyzzy', 2000);
361+
362+
-- immutable mark is a bit of a lie, but it serves to make call a simple expr
363+
-- that will return a still-toasted value
364+
CREATE FUNCTION data_source(i int) RETURNS TEXT LANGUAGE sql
365+
AS 'select f1 from test4' IMMUTABLE;
366+
367+
DO $$
368+
declare x text;
369+
begin
370+
for i in 1..3 loop
371+
x := data_source(i);
372+
commit;
373+
end loop;
374+
raise notice 'length(x) = %', length(x);
375+
end $$;
376+
377+
357378
-- operations on composite types vs. internal transactions
358379
DO LANGUAGE plpgsql $$
359380
declare

0 commit comments

Comments
 (0)