From c64223cb8305e2d76f78af936c53c93c52d8789c Mon Sep 17 00:00:00 2001 From: David Christensen Date: Tue, 19 Dec 2023 18:13:07 -0500 Subject: [PATCH v2 8/9] Split MaxHeapTupleSize into Limit and Dynamic variants --- src/backend/access/heap/heapam.c | 12 ++++++------ src/backend/access/heap/hio.c | 6 +++--- src/backend/access/heap/rewriteheap.c | 4 ++-- src/backend/replication/logical/reorderbuffer.c | 2 +- src/backend/storage/freespace/freespace.c | 2 +- src/include/access/heaptoast.h | 2 +- src/include/access/htup_details.h | 5 ++--- src/test/regress/expected/insert.out | 2 +- src/test/regress/sql/insert.sql | 2 +- 9 files changed, 18 insertions(+), 19 deletions(-) diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 182d3d7b59..6916a58359 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -9231,7 +9231,7 @@ heap_xlog_insert(XLogReaderState *record) union { HeapTupleHeaderData hdr; - char data[MaxHeapTupleSize]; + char data[MaxHeapTupleSizeLimit]; } tbuf; HeapTupleHeader htup; xl_heap_header xlhdr; @@ -9287,7 +9287,7 @@ heap_xlog_insert(XLogReaderState *record) data = XLogRecGetBlockData(record, 0, &datalen); newlen = datalen - SizeOfHeapHeader; - Assert(datalen > SizeOfHeapHeader && newlen <= MaxHeapTupleSize); + Assert(datalen > SizeOfHeapHeader && newlen <= MaxHeapTupleSizeDynamic); memcpy((char *) &xlhdr, data, SizeOfHeapHeader); data += SizeOfHeapHeader; @@ -9353,7 +9353,7 @@ heap_xlog_multi_insert(XLogReaderState *record) union { HeapTupleHeaderData hdr; - char data[MaxHeapTupleSize]; + char data[MaxHeapTupleSizeLimit]; } tbuf; HeapTupleHeader htup; uint32 newlen; @@ -9431,7 +9431,7 @@ heap_xlog_multi_insert(XLogReaderState *record) tupdata = ((char *) xlhdr) + SizeOfMultiInsertTuple; newlen = xlhdr->datalen; - Assert(newlen <= MaxHeapTupleSize); + Assert(newlen <= MaxHeapTupleSizeDynamic); htup = &tbuf.hdr; MemSet((char *) htup, 0, SizeofHeapTupleHeader); /* PG73FORMAT: get bitmap [+ padding] [+ oid] + data */ @@ -9510,7 +9510,7 @@ heap_xlog_update(XLogReaderState *record, bool hot_update) union { HeapTupleHeaderData hdr; - char data[MaxHeapTupleSize]; + char data[MaxHeapTupleSizeLimit]; } tbuf; xl_heap_header xlhdr; uint32 newlen; @@ -9666,7 +9666,7 @@ heap_xlog_update(XLogReaderState *record, bool hot_update) recdata += SizeOfHeapHeader; tuplen = recdata_end - recdata; - Assert(tuplen <= MaxHeapTupleSize); + Assert(tuplen <= MaxHeapTupleSizeDynamic); htup = &tbuf.hdr; MemSet((char *) htup, 0, SizeofHeapTupleHeader); diff --git a/src/backend/access/heap/hio.c b/src/backend/access/heap/hio.c index bd427ba2f8..337aa4a530 100644 --- a/src/backend/access/heap/hio.c +++ b/src/backend/access/heap/hio.c @@ -530,11 +530,11 @@ RelationGetBufferForTuple(Relation relation, Size len, /* * If we're gonna fail for oversize tuple, do it right away */ - if (len > MaxHeapTupleSize) + if (len > MaxHeapTupleSizeDynamic) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("row is too big: size %zu, maximum size %zu", - len, MaxHeapTupleSize))); + len, MaxHeapTupleSizeDynamic))); /* Compute desired extra freespace due to fillfactor option */ saveFreeSpace = RelationGetTargetPageFreeSpace(relation, @@ -546,7 +546,7 @@ RelationGetBufferForTuple(Relation relation, Size len, * somewhat arbitrary, but it should prevent most unnecessary relation * extensions while inserting large tuples into low-fillfactor tables. */ - nearlyEmptyFreeSpace = MaxHeapTupleSize - + nearlyEmptyFreeSpace = MaxHeapTupleSizeDynamic - (MaxHeapTuplesPerPageDynamic / 8 * sizeof(ItemIdData)); if (len + saveFreeSpace > nearlyEmptyFreeSpace) targetFreeSpace = Max(len, nearlyEmptyFreeSpace); diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c index 424958912c..273a7faf85 100644 --- a/src/backend/access/heap/rewriteheap.c +++ b/src/backend/access/heap/rewriteheap.c @@ -653,11 +653,11 @@ raw_heap_insert(RewriteState state, HeapTuple tup) /* * If we're gonna fail for oversize tuple, do it right away */ - if (len > MaxHeapTupleSize) + if (len > MaxHeapTupleSizeDynamic) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("row is too big: size %zu, maximum size %zu", - len, MaxHeapTupleSize))); + len, MaxHeapTupleSizeDynamic))); /* Compute desired extra freespace due to fillfactor option */ saveFreeSpace = RelationGetTargetPageFreeSpace(state->rs_new_rel, diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c index 12edc5772a..5c235ec78c 100644 --- a/src/backend/replication/logical/reorderbuffer.c +++ b/src/backend/replication/logical/reorderbuffer.c @@ -4882,7 +4882,7 @@ ReorderBufferToastReplace(ReorderBuffer *rb, ReorderBufferTXN *txn, * the tuplebuf because attrs[] will point back into the current content. */ tmphtup = heap_form_tuple(desc, attrs, isnull); - Assert(newtup->tuple.t_len <= MaxHeapTupleSize); + Assert(newtup->tuple.t_len <= MaxHeapTupleSizeDynamic); Assert(ReorderBufferTupleBufData(newtup) == newtup->tuple.t_data); memcpy(newtup->tuple.t_data, tmphtup->t_data, tmphtup->t_len); diff --git a/src/backend/storage/freespace/freespace.c b/src/backend/storage/freespace/freespace.c index fb9440ff72..cf712182aa 100644 --- a/src/backend/storage/freespace/freespace.c +++ b/src/backend/storage/freespace/freespace.c @@ -63,7 +63,7 @@ */ #define FSM_CATEGORIES 256 #define FSM_CAT_STEP (BLCKSZ / FSM_CATEGORIES) -#define MaxFSMRequestSize MaxHeapTupleSize +#define MaxFSMRequestSize MaxHeapTupleSizeDynamic /* * Depth of the on-disk tree. We need to be able to address 2^32-1 blocks, diff --git a/src/include/access/heaptoast.h b/src/include/access/heaptoast.h index 5c0a796f66..5e649aa1ac 100644 --- a/src/include/access/heaptoast.h +++ b/src/include/access/heaptoast.h @@ -65,7 +65,7 @@ * compress it (we can't move it out-of-line, however). Note that this * number is per-datum, not per-tuple, for simplicity in index_form_tuple(). */ -#define TOAST_INDEX_TARGET (MaxHeapTupleSize / 16) +#define TOAST_INDEX_TARGET (MaxHeapTupleSizeDynamic / 16) /* * When we store an oversize datum externally, we divide it into chunks diff --git a/src/include/access/htup_details.h b/src/include/access/htup_details.h index 90ae6ca97f..c7cf689218 100644 --- a/src/include/access/htup_details.h +++ b/src/include/access/htup_details.h @@ -550,7 +550,7 @@ StaticAssertDecl(MaxOffsetNumber < SpecTokenOffsetNumber, #define BITMAPLEN(NATTS) (((int)(NATTS) + 7) / 8) /* - * MaxHeapTupleSize is the maximum allowed size of a heap tuple, including + * MaxHeapTupleSizeDynamic is the maximum allowed size of a heap tuple, including * header and MAXALIGN alignment padding. Basically it's BLCKSZ minus the * other stuff that has to be on a disk page. Since heap pages use no * "special space", there's no deduction for that. @@ -558,12 +558,11 @@ StaticAssertDecl(MaxOffsetNumber < SpecTokenOffsetNumber, * NOTE: we allow for the ItemId that must point to the tuple, ensuring that * an otherwise-empty page can indeed hold a tuple of this size. Because * ItemIds and tuples have different alignment requirements, don't assume that - * you can, say, fit 2 tuples of size MaxHeapTupleSize/2 on the same page. + * you can, say, fit 2 tuples of size MaxHeapTupleSizeDynamic/2 on the same page. */ #define CalcMaxHeapTupleSize(usablespace) ((usablespace) - MAXALIGN(sizeof(ItemIdData))) #define MaxHeapTupleSizeLimit CalcMaxHeapTupleSize(PageUsableSpaceMax) #define MaxHeapTupleSizeDynamic CalcMaxHeapTupleSize(PageUsableSpace) -#define MaxHeapTupleSize MaxHeapTupleSizeLimit #define MinHeapTupleSize MAXALIGN(SizeofHeapTupleHeader) /* diff --git a/src/test/regress/expected/insert.out b/src/test/regress/expected/insert.out index dd4354fc7d..435adf5439 100644 --- a/src/test/regress/expected/insert.out +++ b/src/test/regress/expected/insert.out @@ -86,7 +86,7 @@ drop table inserttest; -- CREATE TABLE large_tuple_test (a int, b text) WITH (fillfactor = 10); ALTER TABLE large_tuple_test ALTER COLUMN b SET STORAGE plain; --- create page w/ free space in range [nearlyEmptyFreeSpace, MaxHeapTupleSize) +-- create page w/ free space in range [nearlyEmptyFreeSpace, MaxHeapTupleSizeDynamic) INSERT INTO large_tuple_test (select 1, NULL); -- should still fit on the page INSERT INTO large_tuple_test (select 2, repeat('a', 1000)); diff --git a/src/test/regress/sql/insert.sql b/src/test/regress/sql/insert.sql index bdcffd0314..133acae4cc 100644 --- a/src/test/regress/sql/insert.sql +++ b/src/test/regress/sql/insert.sql @@ -43,7 +43,7 @@ drop table inserttest; CREATE TABLE large_tuple_test (a int, b text) WITH (fillfactor = 10); ALTER TABLE large_tuple_test ALTER COLUMN b SET STORAGE plain; --- create page w/ free space in range [nearlyEmptyFreeSpace, MaxHeapTupleSize) +-- create page w/ free space in range [nearlyEmptyFreeSpace, MaxHeapTupleSizeDynamic) INSERT INTO large_tuple_test (select 1, NULL); -- should still fit on the page -- 2.40.1