From 294b68508cade1dd0df5b78c0f0ec12d7ce761b8 Mon Sep 17 00:00:00 2001 From: Peter Eisentraut Date: Thu, 3 May 2018 10:54:13 -0400 Subject: [PATCH v1] PL/pgSQL: Flatten TOAST data in nonatomic context When in a nonatomic execution context, when storing a potentially toasted datum into a PL/pgSQL variable, we need to flatten the datum (i.e., remove any references to TOAST data). Otherwise, a transaction end combined with, say, a concurrent VACUUM, between storing the datum and reading it, could remove the TOAST data, and then the data in the variable would no longer be readable. --- src/pl/plpgsql/src/pl_exec.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c index 228d1c0d00..28a6957286 100644 --- a/src/pl/plpgsql/src/pl_exec.c +++ b/src/pl/plpgsql/src/pl_exec.c @@ -20,6 +20,7 @@ #include "access/htup_details.h" #include "access/transam.h" #include "access/tupconvert.h" +#include "access/tuptoaster.h" #include "catalog/pg_proc.h" #include "catalog/pg_type.h" #include "commands/defrem.h" @@ -6621,6 +6622,16 @@ exec_move_row(PLpgSQL_execstate *estate, { ExpandedRecordHeader *newerh = NULL; + /* + * If not in atomic context, flatten TOAST references. Otherwise the + * TOAST data might disappear if a transaction is committed. + */ + if (!estate->atomic) + { + if (tup) + tup = toast_flatten_tuple(tup, tupdesc); + } + /* * If target is RECORD, we may be able to avoid field-by-field processing. */ base-commit: 30c66e77be1d890c3cca766259c0bec80bcac1b5 -- 2.17.0