1
0
mirror of https://github.com/postgres/postgres.git synced 2026-10-23 13:29:09 +03:00

Minimize footprint of TOAST_MAX_CHUNK_SIZE in heap and amcheck code

This refactoring eases a little bit a follow-up change to add support
for 8-byte TOAST value IDs, as the maximum chunk size allowed for a
single chunk of TOASTed data depends on the size of varatt_external, its
value ID being part of it.

It is worth noting that TOAST_MAX_CHUNK_SIZE resolves as a uintptr_t, so
the previous calculations were in 64-bit unsigned arithmetic.  These are
now done in int32, which still works the same way due to an external
TOAST value being bounded to 1GB.

Author: Michael Paquier <michael@paquier.xyz>
Reviewed-by: Yugo Nagata <nagata@sraoss.co.jp>
Reviewed-by: Bharath Rupireddy <bharath.rupireddyforpostgres@gmail.com>
Discussion: https://postgr.es/m/CALj2ACVnO6jjs5aRx3dSOBy9LV7=iakPBR1eOvoeB8rL8Q47zg@mail.gmail.com
This commit is contained in:
Michael Paquier
2026-09-04 07:50:46 +09:00
parent f7a563ccd1
commit 2b3d11aaed
2 changed files with 21 additions and 12 deletions

View File

@@ -1558,11 +1558,15 @@ check_toast_tuple(HeapTuple toasttup, HeapCheckContext *ctx,
uint32 extsize)
{
int32 chunk_seq;
int32 last_chunk_seq = (extsize - 1) / TOAST_MAX_CHUNK_SIZE;
int32 last_chunk_seq;
Pointer chunk;
bool isnull;
int32 chunksize;
int32 expected_size;
int32 max_chunk_size;
max_chunk_size = TOAST_MAX_CHUNK_SIZE;
last_chunk_seq = (extsize - 1) / max_chunk_size;
/* Sanity-check the sequence number. */
chunk_seq = DatumGetInt32(fastgetattr(toasttup, 2,
@@ -1628,8 +1632,8 @@ check_toast_tuple(HeapTuple toasttup, HeapCheckContext *ctx,
return;
}
expected_size = chunk_seq < last_chunk_seq ? TOAST_MAX_CHUNK_SIZE
: extsize - (last_chunk_seq * TOAST_MAX_CHUNK_SIZE);
expected_size = chunk_seq < last_chunk_seq ? max_chunk_size
: extsize - (last_chunk_seq * max_chunk_size);
if (chunksize != expected_size)
report_toast_corruption(ctx, ta,
@@ -1868,9 +1872,10 @@ check_toasted_attribute(HeapCheckContext *ctx, ToastedAttribute *ta)
uint32 extsize;
int32 expected_chunk_seq = 0;
int32 last_chunk_seq;
int32 max_chunk_size = TOAST_MAX_CHUNK_SIZE;
extsize = VARATT_EXTERNAL_GET_EXTSIZE(ta->toast_pointer);
last_chunk_seq = (extsize - 1) / TOAST_MAX_CHUNK_SIZE;
last_chunk_seq = (extsize - 1) / max_chunk_size;
/*
* Setup a scan key to find chunks in toast table with matching va_valueid

View File

@@ -634,11 +634,12 @@ heap_fetch_toast_slice(Relation toastrel, Oid valueid, int32 attrsize,
SysScanDesc toastscan;
HeapTuple ttup;
int32 expectedchunk;
int32 totalchunks = ((attrsize - 1) / TOAST_MAX_CHUNK_SIZE) + 1;
int32 totalchunks;
int startchunk;
int endchunk;
int num_indexes;
int validIndex;
int32 max_chunk_size;
/* Look for the valid index of toast relation */
validIndex = toast_open_indexes(toastrel,
@@ -646,8 +647,11 @@ heap_fetch_toast_slice(Relation toastrel, Oid valueid, int32 attrsize,
&toastidxs,
&num_indexes);
startchunk = sliceoffset / TOAST_MAX_CHUNK_SIZE;
endchunk = (sliceoffset + slicelength - 1) / TOAST_MAX_CHUNK_SIZE;
max_chunk_size = TOAST_MAX_CHUNK_SIZE;
totalchunks = ((attrsize - 1) / max_chunk_size) + 1;
startchunk = sliceoffset / max_chunk_size;
endchunk = (sliceoffset + slicelength - 1) / max_chunk_size;
Assert(endchunk <= totalchunks);
/* Set up a scan key to fetch from the index. */
@@ -747,8 +751,8 @@ heap_fetch_toast_slice(Relation toastrel, Oid valueid, int32 attrsize,
curchunk,
startchunk, endchunk, valueid,
RelationGetRelationName(toastrel))));
expected_size = curchunk < totalchunks - 1 ? TOAST_MAX_CHUNK_SIZE
: attrsize - ((totalchunks - 1) * TOAST_MAX_CHUNK_SIZE);
expected_size = curchunk < totalchunks - 1 ? max_chunk_size
: attrsize - ((totalchunks - 1) * max_chunk_size);
if (chunksize != expected_size)
ereport(ERROR,
(errcode(ERRCODE_DATA_CORRUPTED),
@@ -763,12 +767,12 @@ heap_fetch_toast_slice(Relation toastrel, Oid valueid, int32 attrsize,
chcpystrt = 0;
chcpyend = chunksize - 1;
if (curchunk == startchunk)
chcpystrt = sliceoffset % TOAST_MAX_CHUNK_SIZE;
chcpystrt = sliceoffset % max_chunk_size;
if (curchunk == endchunk)
chcpyend = (sliceoffset + slicelength - 1) % TOAST_MAX_CHUNK_SIZE;
chcpyend = (sliceoffset + slicelength - 1) % max_chunk_size;
memcpy(VARDATA(result) +
curchunk * TOAST_MAX_CHUNK_SIZE - sliceoffset + chcpystrt,
(curchunk * max_chunk_size - sliceoffset) + chcpystrt,
chunkdata + chcpystrt,
(chcpyend - chcpystrt) + 1);