postgresql/src/include
Tom Lane 3f8c8e3c61 Fix failure to detoast fields in composite elements of structured types.
If we have an array of records stored on disk, the individual record fields
cannot contain out-of-line TOAST pointers: the tuptoaster.c mechanisms are
only prepared to deal with TOAST pointers appearing in top-level fields of
a stored row.  The same applies for ranges over composite types, nested
composites, etc.  However, the existing code only took care of expanding
sub-field TOAST pointers for the case of nested composites, not for other
structured types containing composites.  For example, given a command such
as

UPDATE tab SET arraycol = ARRAY[(ROW(x,42)::mycompositetype] ...

where x is a direct reference to a field of an on-disk tuple, if that field
is long enough to be toasted out-of-line then the TOAST pointer would be
inserted as-is into the array column.  If the source record for x is later
deleted, the array field value would become a dangling pointer, leading
to errors along the line of "missing chunk number 0 for toast value ..."
when the value is referenced.  A reproducible test case for this was
provided by Jan Pecek, but it seems likely that some of the "missing chunk
number" reports we've heard in the past were caused by similar issues.

Code-wise, the problem is that PG_DETOAST_DATUM() is not adequate to
produce a self-contained Datum value if the Datum is of composite type.
Seen in this light, the problem is not just confined to arrays and ranges,
but could also affect some other places where detoasting is done in that
way, for example form_index_tuple().

I tried teaching the array code to apply toast_flatten_tuple_attribute()
along with PG_DETOAST_DATUM() when the array element type is composite,
but this was messy and imposed extra cache lookup costs whether or not any
TOAST pointers were present, indeed sometimes when the array element type
isn't even composite (since sometimes it takes a typcache lookup to find
that out).  The idea of extending that approach to all the places that
currently use PG_DETOAST_DATUM() wasn't attractive at all.

This patch instead solves the problem by decreeing that composite Datum
values must not contain any out-of-line TOAST pointers in the first place;
that is, we expand out-of-line fields at the point of constructing a
composite Datum, not at the point where we're about to insert it into a
larger tuple.  This rule is applied only to true composite Datums, not
to tuples that are being passed around the system as tuples, so it's not
as invasive as it might sound at first.  With this approach, the amount
of code that has to be touched for a full solution is greatly reduced,
and added cache lookup costs are avoided except when there actually is
a TOAST pointer that needs to be inlined.

The main drawback of this approach is that we might sometimes dereference
a TOAST pointer that will never actually be used by the query, imposing a
rather large cost that wasn't there before.  On the other side of the coin,
if the field value is used multiple times then we'll come out ahead by
avoiding repeat detoastings.  Experimentation suggests that common SQL
coding patterns are unaffected either way, though.  Applications that are
very negatively affected could be advised to modify their code to not fetch
columns they won't be using.

In future, we might consider reverting this solution in favor of detoasting
only at the point where data is about to be stored to disk, using some
method that can drill down into multiple levels of nested structured types.
That will require defining new APIs for structured types, though, so it
doesn't seem feasible as a back-patchable fix.

Note that this patch changes HeapTupleGetDatum() from a macro to a function
call; this means that any third-party code using that macro will not get
protection against creating TOAST-pointer-containing Datums until it's
recompiled.  The same applies to any uses of PG_RETURN_HEAPTUPLEHEADER().
It seems likely that this is not a big problem in practice: most of the
tuple-returning functions in core and contrib produce outputs that could
not possibly be toasted anyway, and the same probably holds for third-party
extensions.

This bug has existed since TOAST was invented, so back-patch to all
supported branches.
2014-05-01 15:19:06 -04:00
..
access Fix failure to detoast fields in composite elements of structured types. 2014-05-01 15:19:06 -04:00
bootstrap Update copyright for 2014 2014-01-07 16:05:30 -05:00
catalog Rationalize common/relpath.[hc]. 2014-04-30 17:30:50 -04:00
commands Offer triggers on foreign tables. 2014-03-23 02:16:34 -04:00
common Rationalize common/relpath.[hc]. 2014-04-30 17:30:50 -04:00
datatype Update copyright for 2014 2014-01-07 16:05:30 -05:00
executor Update copyright for 2014 2014-01-07 16:05:30 -05:00
foreign Update copyright for 2014 2014-01-07 16:05:30 -05:00
lib Update copyright for 2014 2014-01-07 16:05:30 -05:00
libpq Fix assorted issues in client host name lookup. 2014-04-02 17:11:24 -04:00
mb Fix typo 2014-02-13 21:50:43 -05:00
nodes Make security barrier views automatically updatable 2014-04-12 21:04:58 -04:00
optimizer Make security barrier views automatically updatable 2014-04-12 21:04:58 -04:00
parser Allow polymorphic aggregates to have non-polymorphic state data types. 2014-04-23 19:17:41 -04:00
port Enable building with Visual Studion 2013. 2014-01-26 09:49:10 -05:00
portability Update copyright for 2014 2014-01-07 16:05:30 -05:00
postmaster Separate multixact freezing parameters from xid's 2014-02-13 19:36:31 -03:00
regex Allow regex operations to be terminated early by query cancel requests. 2014-03-01 15:20:56 -05:00
replication Allow logical decoding via the walsender interface. 2014-03-10 13:50:28 -04:00
rewrite Make security barrier views automatically updatable 2014-04-12 21:04:58 -04:00
snowball Update copyright for 2014 2014-01-07 16:05:30 -05:00
storage Rationalize common/relpath.[hc]. 2014-04-30 17:30:50 -04:00
tcop Avoid repeated name lookups during table and index DDL. 2014-02-17 09:33:31 -05:00
tsearch Allow opclasses to provide tri-valued GIN consistent functions. 2014-03-12 17:51:30 +02:00
utils Can't completely get rid of #ifndef FRONTEND in palloc.h :-( 2014-04-27 21:24:19 -04:00
.gitignore Autoconfiscate selection of 64-bit int type for 64-bit large object API. 2012-10-07 21:52:43 -04:00
c.h Prevent double macro definition of WIN32. 2014-01-17 11:49:44 -05:00
fmgr.h Fix failure to detoast fields in composite elements of structured types. 2014-05-01 15:19:06 -04:00
funcapi.h Fix failure to detoast fields in composite elements of structured types. 2014-05-01 15:19:06 -04:00
getaddrinfo.h Fix assorted issues in client host name lookup. 2014-04-02 17:11:24 -04:00
getopt_long.h Centralize getopt-related declarations in a new header file pg_getopt.h. 2014-02-15 14:31:30 -05:00
Makefile Remove maintainer-check target, fold into normal build 2013-10-10 20:11:56 -04:00
miscadmin.h Make sure -D is an absolute path when starting server on Windows. 2014-04-04 18:42:13 -04:00
pg_config_ext.h.in Autoconfiscate selection of 64-bit int type for 64-bit large object API. 2012-10-07 21:52:43 -04:00
pg_config_ext.h.win32 Autoconfiscate selection of 64-bit int type for 64-bit large object API. 2012-10-07 21:52:43 -04:00
pg_config_manual.h Fix typos in comments for ALTER SYSTEM. 2014-01-27 12:23:20 +09:00
pg_config.h.in Allow use of "z" flag in our printf calls, and use it where appropriate. 2014-01-23 17:18:33 -05:00
pg_config.h.win32 Enable building with Visual Studion 2013. 2014-01-26 09:49:10 -05:00
pg_getopt.h Centralize getopt-related declarations in a new header file pg_getopt.h. 2014-02-15 14:31:30 -05:00
pg_trace.h Update copyright for 2014 2014-01-07 16:05:30 -05:00
pgstat.h Fix some compiler warnings that clang emits with -pedantic. 2014-04-04 11:29:50 -04:00
pgtar.h Update copyright for 2014 2014-01-07 16:05:30 -05:00
pgtime.h Update copyright for 2014 2014-01-07 16:05:30 -05:00
port.h Make sure -D is an absolute path when starting server on Windows. 2014-04-04 18:42:13 -04:00
postgres_ext.h Provide database object names as separate fields in error messages. 2013-01-29 17:08:26 -05:00
postgres_fe.h Update copyright for 2014 2014-01-07 16:05:30 -05:00
postgres.h Further code review for pg_lsn data type. 2014-02-19 10:06:59 -05:00
rusagestub.h Update copyright for 2014 2014-01-07 16:05:30 -05:00
windowapi.h Update copyright for 2014 2014-01-07 16:05:30 -05:00