From f33ea0541a5115e5bcd2b3881c48c20598994220 Mon Sep 17 00:00:00 2001 From: David Christensen Date: Tue, 18 Oct 2022 14:28:09 -0400 Subject: [PATCH v2 2/5] Add reserved_page_space to Page structure This space is reserved for extended data on the Page structure which will be ultimately used for encrypted data, extended checksums, and potentially other things. This data appears at the end of the Page, after any `pd_special` area, and will be calculated at runtime based on specific ControlFile features. No effort is made to ensure this is backwards-compatible with existing clusters for `pg_upgrade`, as we will require logical replication to move data into a cluster with different settings here. --- contrib/amcheck/verify_nbtree.c | 4 +- contrib/pg_surgery/heap_surgery.c | 4 +- src/backend/access/brin/brin_bloom.c | 8 ++-- src/backend/access/brin/brin_minmax_multi.c | 8 ++-- src/backend/access/brin/brin_tuple.c | 2 +- src/backend/access/common/indextuple.c | 2 +- src/backend/access/gin/gindatapage.c | 20 +++++----- src/backend/access/gin/ginentrypage.c | 4 +- src/backend/access/gin/ginfast.c | 10 ++--- src/backend/access/gin/gininsert.c | 4 +- src/backend/access/gin/ginpostinglist.c | 6 +-- src/backend/access/gin/ginvacuum.c | 2 +- src/backend/access/heap/README.HOT | 2 +- src/backend/access/heap/heapam.c | 14 +++---- src/backend/access/heap/heapam_handler.c | 8 ++-- src/backend/access/heap/hio.c | 8 ++-- src/backend/access/heap/pruneheap.c | 24 +++++------ src/backend/access/heap/rewriteheap.c | 4 +- src/backend/access/heap/vacuumlazy.c | 22 +++++----- src/backend/access/nbtree/nbtdedup.c | 6 +-- src/backend/access/nbtree/nbtinsert.c | 4 +- src/backend/access/nbtree/nbtree.c | 4 +- src/backend/access/nbtree/nbtsearch.c | 8 ++-- src/backend/access/nbtree/nbtsplitloc.c | 2 +- src/backend/nodes/tidbitmap.c | 2 +- .../replication/logical/reorderbuffer.c | 2 +- src/backend/storage/freespace/freespace.c | 30 +++++++------- src/backend/storage/page/bufpage.c | 34 ++++++++-------- src/backend/utils/adt/tsgistidx.c | 2 +- src/backend/utils/init/globals.c | 3 ++ src/backend/utils/misc/guc_tables.c | 13 ++++++ src/bin/initdb/initdb.c | 1 + src/include/access/ginblock.h | 27 +++++++++---- src/include/access/hash.h | 5 ++- src/include/access/heapam.h | 2 +- src/include/access/heaptoast.h | 4 +- src/include/access/htup_details.h | 40 ++++++++++++++----- src/include/access/nbtree.h | 32 ++++++++++----- src/include/access/spgist_private.h | 1 + src/include/storage/bufpage.h | 21 +++++++--- .../test_ginpostinglist/test_ginpostinglist.c | 6 +-- src/test/regress/expected/insert.out | 4 +- src/test/regress/expected/vacuum.out | 4 +- src/test/regress/sql/insert.sql | 4 +- src/test/regress/sql/vacuum.sql | 4 +- 45 files changed, 249 insertions(+), 172 deletions(-) diff --git a/contrib/amcheck/verify_nbtree.c b/contrib/amcheck/verify_nbtree.c index 9021d156eb..affb513ad0 100644 --- a/contrib/amcheck/verify_nbtree.c +++ b/contrib/amcheck/verify_nbtree.c @@ -488,12 +488,12 @@ bt_check_every_level(Relation rel, Relation heaprel, bool heapkeyspace, /* * Size Bloom filter based on estimated number of tuples in index, * while conservatively assuming that each block must contain at least - * MaxTIDsPerBTreePage / 3 "plain" tuples -- see + * MaxTIDsPerBTreePage() / 3 "plain" tuples -- see * bt_posting_plain_tuple() for definition, and details of how posting * list tuples are handled. */ total_pages = RelationGetNumberOfBlocks(rel); - total_elems = Max(total_pages * (MaxTIDsPerBTreePage / 3), + total_elems = Max(total_pages * (MaxTIDsPerBTreePage() / 3), (int64) state->rel->rd_rel->reltuples); /* Generate a random seed to avoid repetition */ seed = pg_prng_uint64(&pg_global_prng_state); diff --git a/contrib/pg_surgery/heap_surgery.c b/contrib/pg_surgery/heap_surgery.c index 8a2ad9773d..52ffcc9782 100644 --- a/contrib/pg_surgery/heap_surgery.c +++ b/contrib/pg_surgery/heap_surgery.c @@ -89,7 +89,7 @@ heap_force_common(FunctionCallInfo fcinfo, HeapTupleForceOption heap_force_opt) Relation rel; OffsetNumber curr_start_ptr, next_start_ptr; - bool include_this_tid[MaxHeapTuplesPerPage]; + bool include_this_tid[MaxHeapTuplesPerPageLimit]; if (RecoveryInProgress()) ereport(ERROR, @@ -225,7 +225,7 @@ heap_force_common(FunctionCallInfo fcinfo, HeapTupleForceOption heap_force_opt) } /* Mark it for processing. */ - Assert(offno < MaxHeapTuplesPerPage); + Assert(offno < MaxHeapTuplesPerPage()); include_this_tid[offno] = true; } diff --git a/src/backend/access/brin/brin_bloom.c b/src/backend/access/brin/brin_bloom.c index 6b0af7267d..fee460fb29 100644 --- a/src/backend/access/brin/brin_bloom.c +++ b/src/backend/access/brin/brin_bloom.c @@ -166,7 +166,7 @@ typedef struct BloomOptions * on the fact that the filter header is ~20B alone, which is about * the same as the filter bitmap for 16 distinct items with 1% false * positive rate. So by allowing lower values we'd not gain much. In - * any case, the min should not be larger than MaxHeapTuplesPerPage + * any case, the min should not be larger than MaxHeapTuplesPerPage() * (~290), which is the theoretical maximum for single-page ranges. */ #define BLOOM_MIN_NDISTINCT_PER_RANGE 16 @@ -448,7 +448,7 @@ brin_bloom_opcinfo(PG_FUNCTION_ARGS) * * Adjust the ndistinct value based on the pagesPerRange value. First, * if it's negative, it's assumed to be relative to maximum number of - * tuples in the range (assuming each page gets MaxHeapTuplesPerPage + * tuples in the range (assuming each page gets MaxHeapTuplesPerPage() * tuples, which is likely a significant over-estimate). We also clamp * the value, not to over-size the bloom filter unnecessarily. * @@ -463,7 +463,7 @@ brin_bloom_opcinfo(PG_FUNCTION_ARGS) * seems better to rely on the upper estimate. * * XXX We might also calculate a better estimate of rows per BRIN range, - * instead of using MaxHeapTuplesPerPage (which probably produces values + * instead of using MaxHeapTuplesPerPage() (which probably produces values * much higher than reality). */ static int @@ -478,7 +478,7 @@ brin_bloom_get_ndistinct(BrinDesc *bdesc, BloomOptions *opts) Assert(BlockNumberIsValid(pagesPerRange)); - maxtuples = MaxHeapTuplesPerPage * pagesPerRange; + maxtuples = MaxHeapTuplesPerPage() * pagesPerRange; /* * Similarly to n_distinct, negative values are relative - in this case to diff --git a/src/backend/access/brin/brin_minmax_multi.c b/src/backend/access/brin/brin_minmax_multi.c index 9a0bcf6698..37d31e5d38 100644 --- a/src/backend/access/brin/brin_minmax_multi.c +++ b/src/backend/access/brin/brin_minmax_multi.c @@ -1997,10 +1997,10 @@ brin_minmax_multi_distance_tid(PG_FUNCTION_ARGS) * We use the no-check variants here, because user-supplied values may * have (ip_posid == 0). See ItemPointerCompare. */ - da1 = ItemPointerGetBlockNumberNoCheck(pa1) * MaxHeapTuplesPerPage + + da1 = ItemPointerGetBlockNumberNoCheck(pa1) * MaxHeapTuplesPerPage() + ItemPointerGetOffsetNumberNoCheck(pa1); - da2 = ItemPointerGetBlockNumberNoCheck(pa2) * MaxHeapTuplesPerPage + + da2 = ItemPointerGetBlockNumberNoCheck(pa2) * MaxHeapTuplesPerPage() + ItemPointerGetOffsetNumberNoCheck(pa2); PG_RETURN_FLOAT8(da2 - da1); @@ -2477,7 +2477,7 @@ brin_minmax_multi_add_value(PG_FUNCTION_ARGS) * much lower, but meh. */ maxvalues = Min(target_maxvalues * MINMAX_BUFFER_FACTOR, - MaxHeapTuplesPerPage * pagesPerRange); + MaxHeapTuplesPerPage() * pagesPerRange); /* but always at least the original value */ maxvalues = Max(maxvalues, target_maxvalues); @@ -2523,7 +2523,7 @@ brin_minmax_multi_add_value(PG_FUNCTION_ARGS) * much lower, but meh. */ maxvalues = Min(serialized->maxvalues * MINMAX_BUFFER_FACTOR, - MaxHeapTuplesPerPage * pagesPerRange); + MaxHeapTuplesPerPage() * pagesPerRange); /* but always at least the original value */ maxvalues = Max(maxvalues, serialized->maxvalues); diff --git a/src/backend/access/brin/brin_tuple.c b/src/backend/access/brin/brin_tuple.c index c0e2dbd23b..86eaf55619 100644 --- a/src/backend/access/brin/brin_tuple.c +++ b/src/backend/access/brin/brin_tuple.c @@ -217,7 +217,7 @@ brin_form_tuple(BrinDesc *brdesc, BlockNumber blkno, BrinMemTuple *tuple, * datatype, try to compress it in-line. */ if (!VARATT_IS_EXTENDED(DatumGetPointer(value)) && - VARSIZE(DatumGetPointer(value)) > TOAST_INDEX_TARGET && + VARSIZE(DatumGetPointer(value)) > TOAST_INDEX_TARGET() && (atttype->typstorage == TYPSTORAGE_EXTENDED || atttype->typstorage == TYPSTORAGE_MAIN)) { diff --git a/src/backend/access/common/indextuple.c b/src/backend/access/common/indextuple.c index c0bad3cd95..bda67b1dd3 100644 --- a/src/backend/access/common/indextuple.c +++ b/src/backend/access/common/indextuple.c @@ -118,7 +118,7 @@ index_form_tuple_context(TupleDesc tupleDescriptor, * try to compress it in-line. */ if (!VARATT_IS_EXTENDED(DatumGetPointer(untoasted_values[i])) && - VARSIZE(DatumGetPointer(untoasted_values[i])) > TOAST_INDEX_TARGET && + VARSIZE(DatumGetPointer(untoasted_values[i])) > TOAST_INDEX_TARGET() && (att->attstorage == TYPSTORAGE_EXTENDED || att->attstorage == TYPSTORAGE_MAIN)) { diff --git a/src/backend/access/gin/gindatapage.c b/src/backend/access/gin/gindatapage.c index 7c76d1f90d..c6d641f4e8 100644 --- a/src/backend/access/gin/gindatapage.c +++ b/src/backend/access/gin/gindatapage.c @@ -535,7 +535,7 @@ dataBeginPlaceToPageLeaf(GinBtree btree, Buffer buf, GinBtreeStack *stack, * a single byte, and we can use all the free space on the old page as * well as the new page. For simplicity, ignore segment overhead etc. */ - maxitems = Min(maxitems, freespace + GinDataPageMaxDataSize); + maxitems = Min(maxitems, freespace + GinDataPageMaxDataSize()); } else { @@ -550,7 +550,7 @@ dataBeginPlaceToPageLeaf(GinBtree btree, Buffer buf, GinBtreeStack *stack, int nnewsegments; nnewsegments = freespace / GinPostingListSegmentMaxSize; - nnewsegments += GinDataPageMaxDataSize / GinPostingListSegmentMaxSize; + nnewsegments += GinDataPageMaxDataSize() / GinPostingListSegmentMaxSize; maxitems = Min(maxitems, nnewsegments * MinTuplesPerSegment); } @@ -665,8 +665,8 @@ dataBeginPlaceToPageLeaf(GinBtree btree, Buffer buf, GinBtreeStack *stack, leaf->lastleft = dlist_prev_node(&leaf->segments, leaf->lastleft); } } - Assert(leaf->lsize <= GinDataPageMaxDataSize); - Assert(leaf->rsize <= GinDataPageMaxDataSize); + Assert(leaf->lsize <= GinDataPageMaxDataSize()); + Assert(leaf->rsize <= GinDataPageMaxDataSize()); /* * Fetch the max item in the left page's last segment; it becomes the @@ -755,7 +755,7 @@ ginVacuumPostingTreeLeaf(Relation indexrel, Buffer buffer, GinVacuumState *gvs) if (seginfo->seg) oldsegsize = SizeOfGinPostingList(seginfo->seg); else - oldsegsize = GinDataPageMaxDataSize; + oldsegsize = GinDataPageMaxDataSize(); cleaned = ginVacuumItemPointers(gvs, seginfo->items, @@ -1015,7 +1015,7 @@ dataPlaceToPageLeafRecompress(Buffer buf, disassembledLeaf *leaf) } } - Assert(newsize <= GinDataPageMaxDataSize); + Assert(newsize <= GinDataPageMaxDataSize()); GinDataPageSetDataSize(page, newsize); } @@ -1684,7 +1684,7 @@ leafRepackItems(disassembledLeaf *leaf, ItemPointer remaining) * copying to the page. Did we exceed the size that fits on one page? */ segsize = SizeOfGinPostingList(seginfo->seg); - if (pgused + segsize > GinDataPageMaxDataSize) + if (pgused + segsize > GinDataPageMaxDataSize()) { if (!needsplit) { @@ -1724,8 +1724,8 @@ leafRepackItems(disassembledLeaf *leaf, ItemPointer remaining) else leaf->rsize = pgused; - Assert(leaf->lsize <= GinDataPageMaxDataSize); - Assert(leaf->rsize <= GinDataPageMaxDataSize); + Assert(leaf->lsize <= GinDataPageMaxDataSize()); + Assert(leaf->rsize <= GinDataPageMaxDataSize()); /* * Make a palloc'd copy of every segment after the first modified one, @@ -1801,7 +1801,7 @@ createPostingTree(Relation index, ItemPointerData *items, uint32 nitems, GinPostingListSegmentMaxSize, &npacked); segsize = SizeOfGinPostingList(segment); - if (rootsize + segsize > GinDataPageMaxDataSize) + if (rootsize + segsize > GinDataPageMaxDataSize()) break; memcpy(ptr, segment, segsize); diff --git a/src/backend/access/gin/ginentrypage.c b/src/backend/access/gin/ginentrypage.c index 382f8bb4d6..51adfe7b4e 100644 --- a/src/backend/access/gin/ginentrypage.c +++ b/src/backend/access/gin/ginentrypage.c @@ -102,13 +102,13 @@ GinFormTuple(GinState *ginstate, newsize = MAXALIGN(newsize); - if (newsize > GinMaxItemSize) + if (newsize > GinMaxItemSize()) { if (errorTooBig) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("index row size %zu exceeds maximum %zu for index \"%s\"", - (Size) newsize, (Size) GinMaxItemSize, + (Size) newsize, (Size) GinMaxItemSize(), RelationGetRelationName(ginstate->index)))); pfree(itup); return NULL; diff --git a/src/backend/access/gin/ginfast.c b/src/backend/access/gin/ginfast.c index f750b5ed9e..46b487b53a 100644 --- a/src/backend/access/gin/ginfast.c +++ b/src/backend/access/gin/ginfast.c @@ -38,8 +38,8 @@ /* GUC parameter */ int gin_pending_list_limit = 0; -#define GIN_PAGE_FREESIZE \ - ( BLCKSZ - MAXALIGN(SizeOfPageHeaderData) - MAXALIGN(sizeof(GinPageOpaqueData)) ) +#define GIN_PAGE_FREESIZE() \ + ( BLCKSZ - MAXALIGN(SizeOfPageHeaderData) - MAXALIGN(sizeof(GinPageOpaqueData)) - SizeOfPageReservedSpace() ) typedef struct KeyArray { @@ -183,7 +183,7 @@ makeSublist(Relation index, IndexTuple *tuples, int32 ntuples, tupsize = MAXALIGN(IndexTupleSize(tuples[i])) + sizeof(ItemIdData); - if (size + tupsize > GinListPageSize) + if (size + tupsize > GinListPageSize()) { /* won't fit, force a new page and reprocess */ i--; @@ -249,7 +249,7 @@ ginHeapTupleFastInsert(GinState *ginstate, GinTupleCollector *collector) */ CheckForSerializableConflictIn(index, NULL, GIN_METAPAGE_BLKNO); - if (collector->sumsize + collector->ntuples * sizeof(ItemIdData) > GinListPageSize) + if (collector->sumsize + collector->ntuples * sizeof(ItemIdData) > GinListPageSize()) { /* * Total size is greater than one page => make sublist @@ -450,7 +450,7 @@ ginHeapTupleFastInsert(GinState *ginstate, GinTupleCollector *collector) * ginInsertCleanup() should not be called inside our CRIT_SECTION. */ cleanupSize = GinGetPendingListCleanupSize(index); - if (metadata->nPendingPages * GIN_PAGE_FREESIZE > cleanupSize * 1024L) + if (metadata->nPendingPages * GIN_PAGE_FREESIZE() > cleanupSize * 1024L) needCleanup = true; UnlockReleaseBuffer(metabuffer); diff --git a/src/backend/access/gin/gininsert.c b/src/backend/access/gin/gininsert.c index ea1c4184fb..b39237a964 100644 --- a/src/backend/access/gin/gininsert.c +++ b/src/backend/access/gin/gininsert.c @@ -75,7 +75,7 @@ addItemPointersToLeafTuple(GinState *ginstate, /* Compress the posting list, and try to a build tuple with room for it */ res = NULL; - compressedList = ginCompressPostingList(newItems, newNPosting, GinMaxItemSize, + compressedList = ginCompressPostingList(newItems, newNPosting, GinMaxItemSize(), NULL); pfree(newItems); if (compressedList) @@ -135,7 +135,7 @@ buildFreshLeafTuple(GinState *ginstate, GinPostingList *compressedList; /* try to build a posting list tuple with all the items */ - compressedList = ginCompressPostingList(items, nitem, GinMaxItemSize, NULL); + compressedList = ginCompressPostingList(items, nitem, GinMaxItemSize(), NULL); if (compressedList) { res = GinFormTuple(ginstate, attnum, key, category, diff --git a/src/backend/access/gin/ginpostinglist.c b/src/backend/access/gin/ginpostinglist.c index 68356d55c0..6206f6102e 100644 --- a/src/backend/access/gin/ginpostinglist.c +++ b/src/backend/access/gin/ginpostinglist.c @@ -26,7 +26,7 @@ * lowest 32 bits are the block number. That leaves 21 bits unused, i.e. * only 43 low bits are used. * - * 11 bits is enough for the offset number, because MaxHeapTuplesPerPage < + * 11 bits is enough for the offset number, because MaxHeapTuplesPerPage() < * 2^11 on all supported block sizes. We are frugal with the bits, because * smaller integers use fewer bytes in the varbyte encoding, saving disk * space. (If we get a new table AM in the future that wants to use the full @@ -74,9 +74,9 @@ /* * How many bits do you need to encode offset number? OffsetNumber is a 16-bit * integer, but you can't fit that many items on a page. 11 ought to be more - * than enough. It's tempting to derive this from MaxHeapTuplesPerPage, and + * than enough. It's tempting to derive this from MaxHeapTuplesPerPage(), and * use the minimum number of bits, but that would require changing the on-disk - * format if MaxHeapTuplesPerPage changes. Better to leave some slack. + * format if MaxHeapTuplesPerPage() changes. Better to leave some slack. */ #define MaxHeapTuplesPerPageBits 11 diff --git a/src/backend/access/gin/ginvacuum.c b/src/backend/access/gin/ginvacuum.c index b4fa5f6bf8..031a1b796d 100644 --- a/src/backend/access/gin/ginvacuum.c +++ b/src/backend/access/gin/ginvacuum.c @@ -514,7 +514,7 @@ ginVacuumEntryPage(GinVacuumState *gvs, Buffer buffer, BlockNumber *roots, uint3 if (nitems > 0) { - plist = ginCompressPostingList(items, nitems, GinMaxItemSize, NULL); + plist = ginCompressPostingList(items, nitems, GinMaxItemSize(), NULL); plistsize = SizeOfGinPostingList(plist); } else diff --git a/src/backend/access/heap/README.HOT b/src/backend/access/heap/README.HOT index 68c6709aa8..8835926a24 100644 --- a/src/backend/access/heap/README.HOT +++ b/src/backend/access/heap/README.HOT @@ -243,7 +243,7 @@ of line pointer bloat: we might end up with huge numbers of line pointers and just a few actual tuples on a page. To limit the damage in the worst case, and to keep various work arrays as well as the bitmaps in bitmap scans reasonably sized, the maximum number of line pointers per page -is arbitrarily capped at MaxHeapTuplesPerPage (the most tuples that +is arbitrarily capped at MaxHeapTuplesPerPage() (the most tuples that could fit without HOT pruning). Effectively, space reclamation happens during tuple retrieval when the diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 12be87efed..265ac277ab 100644 --- a/src/backend/access/heap/heapam.c +++ b/src/backend/access/heap/heapam.c @@ -477,7 +477,7 @@ heapgetpage(TableScanDesc sscan, BlockNumber page) LockBuffer(buffer, BUFFER_LOCK_UNLOCK); - Assert(ntup <= MaxHeapTuplesPerPage); + Assert(ntup <= MaxHeapTuplesPerPage()); scan->rs_ntuples = ntup; } @@ -9088,7 +9088,7 @@ heap_xlog_insert(XLogReaderState *record) union { HeapTupleHeaderData hdr; - char data[MaxHeapTupleSize]; + char data[MaxHeapTupleSizeLimit]; } tbuf; HeapTupleHeader htup; xl_heap_header xlhdr; @@ -9144,7 +9144,7 @@ heap_xlog_insert(XLogReaderState *record) data = XLogRecGetBlockData(record, 0, &datalen); newlen = datalen - SizeOfHeapHeader; - Assert(datalen > SizeOfHeapHeader && newlen <= MaxHeapTupleSize); + Assert(datalen > SizeOfHeapHeader && newlen <= MaxHeapTupleSize()); memcpy((char *) &xlhdr, data, SizeOfHeapHeader); data += SizeOfHeapHeader; @@ -9210,7 +9210,7 @@ heap_xlog_multi_insert(XLogReaderState *record) union { HeapTupleHeaderData hdr; - char data[MaxHeapTupleSize]; + char data[MaxHeapTupleSizeLimit]; } tbuf; HeapTupleHeader htup; uint32 newlen; @@ -9288,7 +9288,7 @@ heap_xlog_multi_insert(XLogReaderState *record) tupdata = ((char *) xlhdr) + SizeOfMultiInsertTuple; newlen = xlhdr->datalen; - Assert(newlen <= MaxHeapTupleSize); + Assert(newlen <= MaxHeapTupleSize()); htup = &tbuf.hdr; MemSet((char *) htup, 0, SizeofHeapTupleHeader); /* PG73FORMAT: get bitmap [+ padding] [+ oid] + data */ @@ -9367,7 +9367,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; @@ -9523,7 +9523,7 @@ heap_xlog_update(XLogReaderState *record, bool hot_update) recdata += SizeOfHeapHeader; tuplen = recdata_end - recdata; - Assert(tuplen <= MaxHeapTupleSize); + Assert(tuplen <= MaxHeapTupleSize()); htup = &tbuf.hdr; MemSet((char *) htup, 0, SizeofHeapTupleHeader); diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c index 41f1ca65d0..0ea35f8a4e 100644 --- a/src/backend/access/heap/heapam_handler.c +++ b/src/backend/access/heap/heapam_handler.c @@ -1184,7 +1184,7 @@ heapam_index_build_range_scan(Relation heapRelation, TransactionId OldestXmin; BlockNumber previous_blkno = InvalidBlockNumber; BlockNumber root_blkno = InvalidBlockNumber; - OffsetNumber root_offsets[MaxHeapTuplesPerPage]; + OffsetNumber root_offsets[MaxHeapTuplesPerPageLimit]; /* * sanity checks @@ -1747,8 +1747,8 @@ heapam_index_validate_scan(Relation heapRelation, EState *estate; ExprContext *econtext; BlockNumber root_blkno = InvalidBlockNumber; - OffsetNumber root_offsets[MaxHeapTuplesPerPage]; - bool in_index[MaxHeapTuplesPerPage]; + OffsetNumber root_offsets[MaxHeapTuplesPerPageLimit]; + bool in_index[MaxHeapTuplesPerPageLimit]; BlockNumber previous_blkno = InvalidBlockNumber; /* state variables for the merge */ @@ -2211,7 +2211,7 @@ heapam_scan_bitmap_next_block(TableScanDesc scan, LockBuffer(buffer, BUFFER_LOCK_UNLOCK); - Assert(ntup <= MaxHeapTuplesPerPage); + Assert(ntup <= MaxHeapTuplesPerPage()); hscan->rs_ntuples = ntup; return ntup > 0; diff --git a/src/backend/access/heap/hio.c b/src/backend/access/heap/hio.c index b0ece66629..4a525fb451 100644 --- a/src/backend/access/heap/hio.c +++ b/src/backend/access/heap/hio.c @@ -354,11 +354,11 @@ RelationGetBufferForTuple(Relation relation, Size len, /* * If we're gonna fail for oversize tuple, do it right away */ - if (len > MaxHeapTupleSize) + if (len > MaxHeapTupleSize()) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("row is too big: size %zu, maximum size %zu", - len, MaxHeapTupleSize))); + len, MaxHeapTupleSize()))); /* Compute desired extra freespace due to fillfactor option */ saveFreeSpace = RelationGetTargetPageFreeSpace(relation, @@ -370,8 +370,8 @@ 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 - - (MaxHeapTuplesPerPage / 8 * sizeof(ItemIdData)); + nearlyEmptyFreeSpace = MaxHeapTupleSize() - + (MaxHeapTuplesPerPage() / 8 * sizeof(ItemIdData)); if (len + saveFreeSpace > nearlyEmptyFreeSpace) targetFreeSpace = Max(len, nearlyEmptyFreeSpace); else diff --git a/src/backend/access/heap/pruneheap.c b/src/backend/access/heap/pruneheap.c index 9f43bbe25f..2673f8f4c5 100644 --- a/src/backend/access/heap/pruneheap.c +++ b/src/backend/access/heap/pruneheap.c @@ -54,17 +54,17 @@ typedef struct int ndead; int nunused; /* arrays that accumulate indexes of items to be changed */ - OffsetNumber redirected[MaxHeapTuplesPerPage * 2]; - OffsetNumber nowdead[MaxHeapTuplesPerPage]; - OffsetNumber nowunused[MaxHeapTuplesPerPage]; + OffsetNumber redirected[MaxHeapTuplesPerPageLimit * 2]; + OffsetNumber nowdead[MaxHeapTuplesPerPageLimit]; + OffsetNumber nowunused[MaxHeapTuplesPerPageLimit]; /* * marked[i] is true if item i is entered in one of the above arrays. * - * This needs to be MaxHeapTuplesPerPage + 1 long as FirstOffsetNumber is + * This needs to be MaxHeapTuplesPerPage() + 1 long as FirstOffsetNumber is * 1. Otherwise every access would need to subtract 1. */ - bool marked[MaxHeapTuplesPerPage + 1]; + bool marked[MaxHeapTuplesPerPageLimit + 1]; /* * Tuple visibility is only computed once for each tuple, for correctness @@ -74,7 +74,7 @@ typedef struct * * Same indexing as ->marked. */ - int8 htsv[MaxHeapTuplesPerPage + 1]; + int8 htsv[MaxHeapTuplesPerPageLimit + 1]; } PruneState; /* Local functions */ @@ -598,7 +598,7 @@ heap_prune_chain(Buffer buffer, OffsetNumber rootoffnum, PruneState *prstate) OffsetNumber latestdead = InvalidOffsetNumber, maxoff = PageGetMaxOffsetNumber(dp), offnum; - OffsetNumber chainitems[MaxHeapTuplesPerPage]; + OffsetNumber chainitems[MaxHeapTuplesPerPageLimit]; int nchain = 0, i; @@ -870,7 +870,7 @@ static void heap_prune_record_redirect(PruneState *prstate, OffsetNumber offnum, OffsetNumber rdoffnum) { - Assert(prstate->nredirected < MaxHeapTuplesPerPage); + Assert(prstate->nredirected < MaxHeapTuplesPerPage()); prstate->redirected[prstate->nredirected * 2] = offnum; prstate->redirected[prstate->nredirected * 2 + 1] = rdoffnum; prstate->nredirected++; @@ -884,7 +884,7 @@ heap_prune_record_redirect(PruneState *prstate, static void heap_prune_record_dead(PruneState *prstate, OffsetNumber offnum) { - Assert(prstate->ndead < MaxHeapTuplesPerPage); + Assert(prstate->ndead < MaxHeapTuplesPerPage()); prstate->nowdead[prstate->ndead] = offnum; prstate->ndead++; Assert(!prstate->marked[offnum]); @@ -895,7 +895,7 @@ heap_prune_record_dead(PruneState *prstate, OffsetNumber offnum) static void heap_prune_record_unused(PruneState *prstate, OffsetNumber offnum) { - Assert(prstate->nunused < MaxHeapTuplesPerPage); + Assert(prstate->nunused < MaxHeapTuplesPerPage()); prstate->nowunused[prstate->nunused] = offnum; prstate->nunused++; Assert(!prstate->marked[offnum]); @@ -1097,7 +1097,7 @@ page_verify_redirects(Page page) * If item k is part of a HOT-chain with root at item j, then we set * root_offsets[k - 1] = j. * - * The passed-in root_offsets array must have MaxHeapTuplesPerPage entries. + * The passed-in root_offsets array must have MaxHeapTuplesPerPage() entries. * Unused entries are filled with InvalidOffsetNumber (zero). * * The function must be called with at least share lock on the buffer, to @@ -1114,7 +1114,7 @@ heap_get_root_tuples(Page page, OffsetNumber *root_offsets) maxoff; MemSet(root_offsets, InvalidOffsetNumber, - MaxHeapTuplesPerPage * sizeof(OffsetNumber)); + MaxHeapTuplesPerPage() * sizeof(OffsetNumber)); maxoff = PageGetMaxOffsetNumber(page); for (offnum = FirstOffsetNumber; offnum <= maxoff; offnum = OffsetNumberNext(offnum)) diff --git a/src/backend/access/heap/rewriteheap.c b/src/backend/access/heap/rewriteheap.c index a34e9b352d..5b1d8bb184 100644 --- a/src/backend/access/heap/rewriteheap.c +++ b/src/backend/access/heap/rewriteheap.c @@ -654,11 +654,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 > MaxHeapTupleSize()) ereport(ERROR, (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), errmsg("row is too big: size %zu, maximum size %zu", - len, MaxHeapTupleSize))); + len, MaxHeapTupleSize()))); /* Compute desired extra freespace due to fillfactor option */ saveFreeSpace = RelationGetTargetPageFreeSpace(state->rs_new_rel, diff --git a/src/backend/access/heap/vacuumlazy.c b/src/backend/access/heap/vacuumlazy.c index dfbe37472f..daec556c36 100644 --- a/src/backend/access/heap/vacuumlazy.c +++ b/src/backend/access/heap/vacuumlazy.c @@ -942,8 +942,8 @@ lazy_scan_heap(LVRelState *vacrel) * dead_items TIDs, pause and do a cycle of vacuuming before we tackle * this page. */ - Assert(dead_items->max_items >= MaxHeapTuplesPerPage); - if (dead_items->max_items - dead_items->num_items < MaxHeapTuplesPerPage) + Assert(dead_items->max_items >= MaxHeapTuplesPerPage()); + if (dead_items->max_items - dead_items->num_items < MaxHeapTuplesPerPage()) { /* * Before beginning index vacuuming, we release any pin we may @@ -1565,8 +1565,8 @@ lazy_scan_prune(LVRelState *vacrel, int nnewlpdead; TransactionId NewRelfrozenXid; MultiXactId NewRelminMxid; - OffsetNumber deadoffsets[MaxHeapTuplesPerPage]; - xl_heap_freeze_tuple frozen[MaxHeapTuplesPerPage]; + OffsetNumber deadoffsets[MaxHeapTuplesPerPageLimit]; + xl_heap_freeze_tuple frozen[MaxHeapTuplesPerPageLimit]; Assert(BufferGetBlockNumber(buf) == blkno); @@ -1968,7 +1968,7 @@ lazy_scan_noprune(LVRelState *vacrel, HeapTupleHeader tupleheader; TransactionId NewRelfrozenXid = vacrel->NewRelfrozenXid; MultiXactId NewRelminMxid = vacrel->NewRelminMxid; - OffsetNumber deadoffsets[MaxHeapTuplesPerPage]; + OffsetNumber deadoffsets[MaxHeapTuplesPerPageLimit]; Assert(BufferGetBlockNumber(buf) == blkno); @@ -2497,7 +2497,7 @@ lazy_vacuum_heap_page(LVRelState *vacrel, BlockNumber blkno, Buffer buffer, { VacDeadItems *dead_items = vacrel->dead_items; Page page = BufferGetPage(buffer); - OffsetNumber unused[MaxHeapTuplesPerPage]; + OffsetNumber unused[MaxHeapTuplesPerPageLimit]; int uncnt = 0; TransactionId visibility_cutoff_xid; bool all_frozen; @@ -3130,16 +3130,16 @@ dead_items_max_items(LVRelState *vacrel) max_items = Min(max_items, MAXDEADITEMS(MaxAllocSize)); /* curious coding here to ensure the multiplication can't overflow */ - if ((BlockNumber) (max_items / MaxHeapTuplesPerPage) > rel_pages) - max_items = rel_pages * MaxHeapTuplesPerPage; + if ((BlockNumber) (max_items / MaxHeapTuplesPerPage()) > rel_pages) + max_items = rel_pages * MaxHeapTuplesPerPage(); /* stay sane if small maintenance_work_mem */ - max_items = Max(max_items, MaxHeapTuplesPerPage); + max_items = Max(max_items, MaxHeapTuplesPerPage()); } else { /* One-pass case only stores a single heap page's TIDs at a time */ - max_items = MaxHeapTuplesPerPage; + max_items = MaxHeapTuplesPerPage(); } return (int) max_items; @@ -3159,7 +3159,7 @@ dead_items_alloc(LVRelState *vacrel, int nworkers) int max_items; max_items = dead_items_max_items(vacrel); - Assert(max_items >= MaxHeapTuplesPerPage); + Assert(max_items >= MaxHeapTuplesPerPage()); /* * Initialize state for a parallel vacuum. As of now, only one worker can diff --git a/src/backend/access/nbtree/nbtdedup.c b/src/backend/access/nbtree/nbtdedup.c index 93a025b0a9..04d7aa5c9f 100644 --- a/src/backend/access/nbtree/nbtdedup.c +++ b/src/backend/access/nbtree/nbtdedup.c @@ -355,8 +355,8 @@ _bt_bottomupdel_pass(Relation rel, Buffer buf, Relation heapRel, delstate.bottomup = true; delstate.bottomupfreespace = Max(BLCKSZ / 16, newitemsz); delstate.ndeltids = 0; - delstate.deltids = palloc(MaxTIDsPerBTreePage * sizeof(TM_IndexDelete)); - delstate.status = palloc(MaxTIDsPerBTreePage * sizeof(TM_IndexStatus)); + delstate.deltids = palloc(MaxTIDsPerBTreePage() * sizeof(TM_IndexDelete)); + delstate.status = palloc(MaxTIDsPerBTreePage() * sizeof(TM_IndexStatus)); minoff = P_FIRSTDATAKEY(opaque); maxoff = PageGetMaxOffsetNumber(page); @@ -826,7 +826,7 @@ _bt_singleval_fillfactor(Page page, BTDedupState state, Size newitemsz) /* This calculation needs to match nbtsplitloc.c */ leftfree = PageGetPageSize(page) - SizeOfPageHeaderData - - MAXALIGN(sizeof(BTPageOpaqueData)); + MAXALIGN(sizeof(BTPageOpaqueData)) - SizeOfPageReservedSpace(); /* Subtract size of new high key (includes pivot heap TID space) */ leftfree -= newitemsz + MAXALIGN(sizeof(ItemPointerData)); diff --git a/src/backend/access/nbtree/nbtinsert.c b/src/backend/access/nbtree/nbtinsert.c index f6f4af8bfe..e4924b4a0f 100644 --- a/src/backend/access/nbtree/nbtinsert.c +++ b/src/backend/access/nbtree/nbtinsert.c @@ -2816,8 +2816,8 @@ _bt_simpledel_pass(Relation rel, Buffer buffer, Relation heapRel, delstate.bottomup = false; delstate.bottomupfreespace = 0; delstate.ndeltids = 0; - delstate.deltids = palloc(MaxTIDsPerBTreePage * sizeof(TM_IndexDelete)); - delstate.status = palloc(MaxTIDsPerBTreePage * sizeof(TM_IndexStatus)); + delstate.deltids = palloc(MaxTIDsPerBTreePage() * sizeof(TM_IndexDelete)); + delstate.status = palloc(MaxTIDsPerBTreePage() * sizeof(TM_IndexStatus)); for (offnum = minoff; offnum <= maxoff; diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c index b52eca8f38..19b8cffa4f 100644 --- a/src/backend/access/nbtree/nbtree.c +++ b/src/backend/access/nbtree/nbtree.c @@ -258,8 +258,8 @@ btgettuple(IndexScanDesc scan, ScanDirection dir) */ if (so->killedItems == NULL) so->killedItems = (int *) - palloc(MaxTIDsPerBTreePage * sizeof(int)); - if (so->numKilled < MaxTIDsPerBTreePage) + palloc(MaxTIDsPerBTreePage() * sizeof(int)); + if (so->numKilled < MaxTIDsPerBTreePage()) so->killedItems[so->numKilled++] = so->currPos.itemIndex; } diff --git a/src/backend/access/nbtree/nbtsearch.c b/src/backend/access/nbtree/nbtsearch.c index c74543bfde..e26c6a8d47 100644 --- a/src/backend/access/nbtree/nbtsearch.c +++ b/src/backend/access/nbtree/nbtsearch.c @@ -1668,7 +1668,7 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum) if (!continuescan) so->currPos.moreRight = false; - Assert(itemIndex <= MaxTIDsPerBTreePage); + Assert(itemIndex <= MaxTIDsPerBTreePage()); so->currPos.firstItem = 0; so->currPos.lastItem = itemIndex - 1; so->currPos.itemIndex = 0; @@ -1676,7 +1676,7 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum) else { /* load items[] in descending order */ - itemIndex = MaxTIDsPerBTreePage; + itemIndex = MaxTIDsPerBTreePage(); offnum = Min(offnum, maxoff); @@ -1765,8 +1765,8 @@ _bt_readpage(IndexScanDesc scan, ScanDirection dir, OffsetNumber offnum) Assert(itemIndex >= 0); so->currPos.firstItem = itemIndex; - so->currPos.lastItem = MaxTIDsPerBTreePage - 1; - so->currPos.itemIndex = MaxTIDsPerBTreePage - 1; + so->currPos.lastItem = MaxTIDsPerBTreePage() - 1; + so->currPos.itemIndex = MaxTIDsPerBTreePage() - 1; } return (so->currPos.firstItem <= so->currPos.lastItem); diff --git a/src/backend/access/nbtree/nbtsplitloc.c b/src/backend/access/nbtree/nbtsplitloc.c index 241e26d338..694f7d17b1 100644 --- a/src/backend/access/nbtree/nbtsplitloc.c +++ b/src/backend/access/nbtree/nbtsplitloc.c @@ -156,7 +156,7 @@ _bt_findsplitloc(Relation rel, /* Total free space available on a btree page, after fixed overhead */ leftspace = rightspace = - PageGetPageSize(origpage) - SizeOfPageHeaderData - + PageGetPageSize(origpage) - SizeOfPageHeaderData - SizeOfPageReservedSpace() - MAXALIGN(sizeof(BTPageOpaqueData)); /* The right page will have the same high key as the old page */ diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c index a7a6b26668..19adae4d23 100644 --- a/src/backend/nodes/tidbitmap.c +++ b/src/backend/nodes/tidbitmap.c @@ -53,7 +53,7 @@ * the per-page bitmaps variable size. We just legislate that the size * is this: */ -#define MAX_TUPLES_PER_PAGE MaxHeapTuplesPerPage +#define MAX_TUPLES_PER_PAGE MaxHeapTuplesPerPageLimit /* * When we have to switch over to lossy storage, we use a data structure diff --git a/src/backend/replication/logical/reorderbuffer.c b/src/backend/replication/logical/reorderbuffer.c index 22a15a482a..d01a325174 100644 --- a/src/backend/replication/logical/reorderbuffer.c +++ b/src/backend/replication/logical/reorderbuffer.c @@ -4824,7 +4824,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 <= MaxHeapTupleSize()); 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 a6b0533103..b880f059fe 100644 --- a/src/backend/storage/freespace/freespace.c +++ b/src/backend/storage/freespace/freespace.c @@ -37,12 +37,12 @@ * We use just one byte to store the amount of free space on a page, so we * divide the amount of free space a page can have into 256 different * categories. The highest category, 255, represents a page with at least - * MaxFSMRequestSize bytes of free space, and the second highest category + * MaxFSMRequestSize() bytes of free space, and the second highest category * represents the range from 254 * FSM_CAT_STEP, inclusive, to - * MaxFSMRequestSize, exclusive. + * MaxFSMRequestSize(), exclusive. * - * MaxFSMRequestSize depends on the architecture and BLCKSZ, but assuming - * default 8k BLCKSZ, and that MaxFSMRequestSize is 8164 bytes, the + * MaxFSMRequestSize() depends on the architecture and BLCKSZ, but assuming + * default 8k BLCKSZ, and that MaxFSMRequestSize() is 8164 bytes, the * categories look like this: * * @@ -54,16 +54,16 @@ * 8128 - 8163 254 * 8164 - 8192 255 * - * The reason that MaxFSMRequestSize is special is that if MaxFSMRequestSize - * isn't equal to a range boundary, a page with exactly MaxFSMRequestSize - * bytes of free space wouldn't satisfy a request for MaxFSMRequestSize - * bytes. If there isn't more than MaxFSMRequestSize bytes of free space on a + * The reason that MaxFSMRequestSize() is special is that if MaxFSMRequestSize() + * isn't equal to a range boundary, a page with exactly MaxFSMRequestSize() + * bytes of free space wouldn't satisfy a request for MaxFSMRequestSize() + * bytes. If there isn't more than MaxFSMRequestSize() bytes of free space on a * completely empty page, that would mean that we could never satisfy a - * request of exactly MaxFSMRequestSize bytes. + * request of exactly MaxFSMRequestSize() bytes. */ #define FSM_CATEGORIES 256 #define FSM_CAT_STEP (BLCKSZ / FSM_CATEGORIES) -#define MaxFSMRequestSize MaxHeapTupleSize +#define MaxFSMRequestSize() MaxHeapTupleSize() /* * Depth of the on-disk tree. We need to be able to address 2^32-1 blocks, @@ -372,13 +372,13 @@ fsm_space_avail_to_cat(Size avail) Assert(avail < BLCKSZ); - if (avail >= MaxFSMRequestSize) + if (avail >= MaxFSMRequestSize()) return 255; cat = avail / FSM_CAT_STEP; /* - * The highest category, 255, is reserved for MaxFSMRequestSize bytes or + * The highest category, 255, is reserved for MaxFSMRequestSize() bytes or * more. */ if (cat > 254) @@ -394,9 +394,9 @@ fsm_space_avail_to_cat(Size avail) static Size fsm_space_cat_to_avail(uint8 cat) { - /* The highest category represents exactly MaxFSMRequestSize bytes. */ + /* The highest category represents exactly MaxFSMRequestSize() bytes. */ if (cat == 255) - return MaxFSMRequestSize; + return MaxFSMRequestSize(); else return cat * FSM_CAT_STEP; } @@ -411,7 +411,7 @@ fsm_space_needed_to_cat(Size needed) int cat; /* Can't ask for more space than the highest category represents */ - if (needed > MaxFSMRequestSize) + if (needed > MaxFSMRequestSize()) elog(ERROR, "invalid FSM request size %zu", needed); if (needed == 0) diff --git a/src/backend/storage/page/bufpage.c b/src/backend/storage/page/bufpage.c index 8b617c7e79..cf4b9a3bfa 100644 --- a/src/backend/storage/page/bufpage.c +++ b/src/backend/storage/page/bufpage.c @@ -43,7 +43,7 @@ PageInit(Page page, Size pageSize, Size specialSize) { PageHeader p = (PageHeader) page; - specialSize = MAXALIGN(specialSize); + specialSize = MAXALIGN(specialSize) + reserved_page_size; Assert(pageSize == BLCKSZ); Assert(pageSize > specialSize + SizeOfPageHeaderData); @@ -117,7 +117,7 @@ PageIsVerifiedExtended(Page page, BlockNumber blkno, int flags) if ((p->pd_flags & ~PD_VALID_FLAG_BITS) == 0 && p->pd_lower <= p->pd_upper && p->pd_upper <= p->pd_special && - p->pd_special <= BLCKSZ && + p->pd_special + reserved_page_size <= BLCKSZ && p->pd_special == MAXALIGN(p->pd_special)) header_sane = true; @@ -186,7 +186,7 @@ PageIsVerifiedExtended(Page page, BlockNumber blkno, int flags) * one that is both unused and deallocated. * * If flag PAI_IS_HEAP is set, we enforce that there can't be more than - * MaxHeapTuplesPerPage line pointers on the page. + * MaxHeapTuplesPerPage() line pointers on the page. * * !!! EREPORT(ERROR) IS DISALLOWED HERE !!! */ @@ -211,7 +211,7 @@ PageAddItemExtended(Page page, if (phdr->pd_lower < SizeOfPageHeaderData || phdr->pd_lower > phdr->pd_upper || phdr->pd_upper > phdr->pd_special || - phdr->pd_special > BLCKSZ) + phdr->pd_special + reserved_page_size > BLCKSZ) ereport(PANIC, (errcode(ERRCODE_DATA_CORRUPTED), errmsg("corrupted page pointers: lower = %u, upper = %u, special = %u", @@ -295,9 +295,9 @@ PageAddItemExtended(Page page, } /* Reject placing items beyond heap boundary, if heap */ - if ((flags & PAI_IS_HEAP) != 0 && offsetNumber > MaxHeapTuplesPerPage) + if ((flags & PAI_IS_HEAP) != 0 && offsetNumber > MaxHeapTuplesPerPage()) { - elog(WARNING, "can't put more than MaxHeapTuplesPerPage items in a heap page"); + elog(WARNING, "can't put more than MaxHeapTuplesPerPage() items in a heap page"); return InvalidOffsetNumber; } @@ -702,7 +702,7 @@ PageRepairFragmentation(Page page) Offset pd_upper = ((PageHeader) page)->pd_upper; Offset pd_special = ((PageHeader) page)->pd_special; Offset last_offset; - itemIdCompactData itemidbase[MaxHeapTuplesPerPage]; + itemIdCompactData itemidbase[MaxHeapTuplesPerPageLimit]; itemIdCompact itemidptr; ItemId lp; int nline, @@ -723,7 +723,7 @@ PageRepairFragmentation(Page page) if (pd_lower < SizeOfPageHeaderData || pd_lower > pd_upper || pd_upper > pd_special || - pd_special > BLCKSZ || + pd_special + reserved_page_size > BLCKSZ || pd_special != MAXALIGN(pd_special)) ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), @@ -979,12 +979,12 @@ PageGetExactFreeSpace(Page page) * reduced by the space needed for a new line pointer. * * The difference between this and PageGetFreeSpace is that this will return - * zero if there are already MaxHeapTuplesPerPage line pointers in the page + * zero if there are already MaxHeapTuplesPerPage() line pointers in the page * and none are free. We use this to enforce that no more than - * MaxHeapTuplesPerPage line pointers are created on a heap page. (Although + * MaxHeapTuplesPerPage() line pointers are created on a heap page. (Although * no more tuples than that could fit anyway, in the presence of redirected * or dead line pointers it'd be possible to have too many line pointers. - * To avoid breaking code that assumes MaxHeapTuplesPerPage is a hard limit + * To avoid breaking code that assumes MaxHeapTuplesPerPage() is a hard limit * on the number of line pointers, we make this extra check.) */ Size @@ -999,10 +999,10 @@ PageGetHeapFreeSpace(Page page) nline; /* - * Are there already MaxHeapTuplesPerPage line pointers in the page? + * Are there already MaxHeapTuplesPerPage() line pointers in the page? */ nline = PageGetMaxOffsetNumber(page); - if (nline >= MaxHeapTuplesPerPage) + if (nline >= MaxHeapTuplesPerPage()) { if (PageHasFreeLinePointers(page)) { @@ -1066,7 +1066,7 @@ PageIndexTupleDelete(Page page, OffsetNumber offnum) if (phdr->pd_lower < SizeOfPageHeaderData || phdr->pd_lower > phdr->pd_upper || phdr->pd_upper > phdr->pd_special || - phdr->pd_special > BLCKSZ || + phdr->pd_special + reserved_page_size > BLCKSZ || phdr->pd_special != MAXALIGN(phdr->pd_special)) ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), @@ -1201,7 +1201,7 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems) if (pd_lower < SizeOfPageHeaderData || pd_lower > pd_upper || pd_upper > pd_special || - pd_special > BLCKSZ || + pd_special + reserved_page_size > BLCKSZ || pd_special != MAXALIGN(pd_special)) ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), @@ -1307,7 +1307,7 @@ PageIndexTupleDeleteNoCompact(Page page, OffsetNumber offnum) if (phdr->pd_lower < SizeOfPageHeaderData || phdr->pd_lower > phdr->pd_upper || phdr->pd_upper > phdr->pd_special || - phdr->pd_special > BLCKSZ || + phdr->pd_special + reserved_page_size > BLCKSZ || phdr->pd_special != MAXALIGN(phdr->pd_special)) ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), @@ -1419,7 +1419,7 @@ PageIndexTupleOverwrite(Page page, OffsetNumber offnum, if (phdr->pd_lower < SizeOfPageHeaderData || phdr->pd_lower > phdr->pd_upper || phdr->pd_upper > phdr->pd_special || - phdr->pd_special > BLCKSZ || + phdr->pd_special + reserved_page_size > BLCKSZ || phdr->pd_special != MAXALIGN(phdr->pd_special)) ereport(ERROR, (errcode(ERRCODE_DATA_CORRUPTED), diff --git a/src/backend/utils/adt/tsgistidx.c b/src/backend/utils/adt/tsgistidx.c index 728b5e9e71..18e48684f4 100644 --- a/src/backend/utils/adt/tsgistidx.c +++ b/src/backend/utils/adt/tsgistidx.c @@ -207,7 +207,7 @@ gtsvector_compress(PG_FUNCTION_ARGS) } /* make signature, if array is too long */ - if (VARSIZE(res) > TOAST_INDEX_TARGET) + if (VARSIZE(res) > TOAST_INDEX_TARGET()) { SignTSVector *ressign = gtsvector_alloc(SIGNKEY, siglen, NULL); diff --git a/src/backend/utils/init/globals.c b/src/backend/utils/init/globals.c index 00bceec8fa..879c054ae0 100644 --- a/src/backend/utils/init/globals.c +++ b/src/backend/utils/init/globals.c @@ -151,3 +151,6 @@ int64 VacuumPageDirty = 0; int VacuumCostBalance = 0; /* working state for vacuum */ bool VacuumCostActive = false; + +int reserved_page_size = 0; /* how much page space to reserve for extended unencrypted metadata */ + diff --git a/src/backend/utils/misc/guc_tables.c b/src/backend/utils/misc/guc_tables.c index 836b49484a..4c30d0d37a 100644 --- a/src/backend/utils/misc/guc_tables.c +++ b/src/backend/utils/misc/guc_tables.c @@ -2630,6 +2630,19 @@ struct config_int ConfigureNamesInt[] = NULL, assign_max_wal_size, NULL }, + { + {"reserved_page_size", PGC_INTERNAL, PRESET_OPTIONS, + gettext_noop("Shows the size of reserved space for extended pages."), + NULL, + GUC_NOT_IN_SAMPLE | GUC_DISALLOW_IN_FILE + }, + &reserved_page_size, + 0, + 0, + PG_UINT8_MAX, + NULL, NULL, NULL + }, + { {"checkpoint_timeout", PGC_SIGHUP, WAL_CHECKPOINTS, gettext_noop("Sets the maximum time between automatic WAL checkpoints."), diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c index f61a043055..40561d5d61 100644 --- a/src/bin/initdb/initdb.c +++ b/src/bin/initdb/initdb.c @@ -77,6 +77,7 @@ #include "getopt_long.h" #include "mb/pg_wchar.h" #include "miscadmin.h" +#include "storage/bufpage.h" /* MaxSizeOfPageReservedSpace */ /* Ideally this would be in a .h file, but it hardly seems worth the trouble */ diff --git a/src/include/access/ginblock.h b/src/include/access/ginblock.h index 9347f464f3..5630f3efa0 100644 --- a/src/include/access/ginblock.h +++ b/src/include/access/ginblock.h @@ -162,7 +162,7 @@ extern bool GinPageIsRecyclable(Page page); * pointers for that page * Note that these are all distinguishable from an "invalid" item pointer * (which is InvalidBlockNumber/0) as well as from all normal item - * pointers (which have item numbers in the range 1..MaxHeapTuplesPerPage). + * pointers (which have item numbers in the range 1..MaxHeapTuplesPerPage()). */ #define ItemPointerSetMin(p) \ ItemPointerSet((p), (BlockNumber)0, (OffsetNumber)0) @@ -246,7 +246,13 @@ typedef signed char GinNullCategory; * currently store the high key explicitly, we just use the rightmost item on * the page, so it would actually be enough to fit two items.) */ -#define GinMaxItemSize \ +#define GinMaxItemSize() \ + Min(INDEX_SIZE_MASK, \ + MAXALIGN_DOWN(((BLCKSZ - \ + SizeOfPageReservedSpace() - \ + MAXALIGN(SizeOfPageHeaderData + 3 * sizeof(ItemIdData)) - \ + MAXALIGN(sizeof(GinPageOpaqueData))) / 3))) +#define GinMaxItemSizeLimit \ Min(INDEX_SIZE_MASK, \ MAXALIGN_DOWN(((BLCKSZ - \ MAXALIGN(SizeOfPageHeaderData + 3 * sizeof(ItemIdData)) - \ @@ -309,15 +315,20 @@ typedef signed char GinNullCategory; */ #define GinDataPageSetDataSize(page, size) \ { \ - Assert(size <= GinDataPageMaxDataSize); \ + Assert(size <= GinDataPageMaxDataSize()); \ ((PageHeader) page)->pd_lower = (size) + MAXALIGN(SizeOfPageHeaderData) + MAXALIGN(sizeof(ItemPointerData)); \ } #define GinNonLeafDataPageGetFreeSpace(page) \ - (GinDataPageMaxDataSize - \ + (GinDataPageMaxDataSize() - \ GinPageGetOpaque(page)->maxoff * sizeof(PostingItem)) -#define GinDataPageMaxDataSize \ +#define GinDataPageMaxDataSize() \ + (BLCKSZ - MAXALIGN(SizeOfPageHeaderData) \ + - SizeOfPageReservedSpace() \ + - MAXALIGN(sizeof(ItemPointerData)) \ + - MAXALIGN(sizeof(GinPageOpaqueData))) +#define GinDataPageMaxDataSizeLimit \ (BLCKSZ - MAXALIGN(SizeOfPageHeaderData) \ - MAXALIGN(sizeof(ItemPointerData)) \ - MAXALIGN(sizeof(GinPageOpaqueData))) @@ -325,8 +336,10 @@ typedef signed char GinNullCategory; /* * List pages */ -#define GinListPageSize \ - ( BLCKSZ - SizeOfPageHeaderData - MAXALIGN(sizeof(GinPageOpaqueData)) ) +#define GinListPageSize() \ + ( BLCKSZ - SizeOfPageHeaderData - MAXALIGN(sizeof(GinPageOpaqueData)) - SizeOfPageReservedSpace()) +#define GinListPageSizeLimit \ + ( BLCKSZ - SizeOfPageHeaderData - MAXALIGN(sizeof(GinPageOpaqueData))) /* * A compressed posting list. diff --git a/src/include/access/hash.h b/src/include/access/hash.h index da372841c4..c17a528d80 100644 --- a/src/include/access/hash.h +++ b/src/include/access/hash.h @@ -287,6 +287,7 @@ typedef struct HashOptions #define HashMaxItemSize(page) \ MAXALIGN_DOWN(PageGetPageSize(page) - \ SizeOfPageHeaderData - \ + SizeOfPageReservedSpace() - \ sizeof(ItemIdData) - \ MAXALIGN(sizeof(HashPageOpaqueData))) @@ -318,7 +319,9 @@ typedef struct HashOptions #define HashGetMaxBitmapSize(page) \ (PageGetPageSize((Page) page) - \ - (MAXALIGN(SizeOfPageHeaderData) + MAXALIGN(sizeof(HashPageOpaqueData)))) + (MAXALIGN(SizeOfPageHeaderData) + \ + SizeOfPageReservedSpace() + \ + MAXALIGN(sizeof(HashPageOpaqueData)))) #define HashPageGetMeta(page) \ ((HashMetaPage) PageGetContents(page)) diff --git a/src/include/access/heapam.h b/src/include/access/heapam.h index 9dab35551e..84a1472ac0 100644 --- a/src/include/access/heapam.h +++ b/src/include/access/heapam.h @@ -74,7 +74,7 @@ typedef struct HeapScanDescData /* these fields only used in page-at-a-time mode and for bitmap scans */ int rs_cindex; /* current tuple's index in vistuples */ int rs_ntuples; /* number of visible tuples on page */ - OffsetNumber rs_vistuples[MaxHeapTuplesPerPage]; /* their offsets */ + OffsetNumber rs_vistuples[MaxHeapTuplesPerPageLimit]; /* their offsets */ } HeapScanDescData; typedef struct HeapScanDescData *HeapScanDesc; diff --git a/src/include/access/heaptoast.h b/src/include/access/heaptoast.h index a75699054a..3421e4ac8b 100644 --- a/src/include/access/heaptoast.h +++ b/src/include/access/heaptoast.h @@ -61,11 +61,11 @@ #define TOAST_TUPLE_TARGET_MAIN MaximumBytesPerTuple(TOAST_TUPLES_PER_PAGE_MAIN) /* - * If an index value is larger than TOAST_INDEX_TARGET, we will try to + * If an index value is larger than TOAST_INDEX_TARGET(), we will try to * 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() (MaxHeapTupleSize() / 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 9561c835f2..6bd2b8f3c2 100644 --- a/src/include/access/htup_details.h +++ b/src/include/access/htup_details.h @@ -546,31 +546,51 @@ do { \ #define BITMAPLEN(NATTS) (((int)(NATTS) + 7) / 8) /* - * MaxHeapTupleSize is the maximum allowed size of a heap tuple, including + * MaxHeapTupleSize() 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. + * other stuff that has to be on a disk page. We also include + * SizeOfPageReservedSpace() bytes in this calculation to account for page + * trailers. + * + * MaxHeapTupleSizeLimit is the maximum buffer-size required for any cluster, + * explicitly excluding the PageReservedSpace. This is needed for any data + * structure which uses a fixed-size buffer, since compilers do not want a + * variable-sized array, and MaxHeapTupleSize() is now variable. * * 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 MaxHeapTupleSize()/2 on the same page. */ -#define MaxHeapTupleSize (BLCKSZ - MAXALIGN(SizeOfPageHeaderData + sizeof(ItemIdData))) +#define MaxHeapTupleSize() (BLCKSZ - MAXALIGN(SizeOfPageHeaderData + sizeof(ItemIdData) + SizeOfPageReservedSpace())) +#define MaxHeapTupleSizeLimit (BLCKSZ - MAXALIGN(SizeOfPageHeaderData + sizeof(ItemIdData))) #define MinHeapTupleSize MAXALIGN(SizeofHeapTupleHeader) /* - * MaxHeapTuplesPerPage is an upper bound on the number of tuples that can - * fit on one heap page. (Note that indexes could have more, because they - * use a smaller tuple header.) We arrive at the divisor because each tuple - * must be maxaligned, and it must have an associated line pointer. + * MaxHeapTuplesPerPage() is an upper bound on the number of tuples that can fit + * on one heap page. (Note that indexes could have more, because they use a + * smaller tuple header.) We arrive at the divisor because each tuple must be + * maxaligned, and it must have an associated line pointer. This is a dynamic + * value, accounting for PageReservedSpace on the end. + * + * MaxHeapTuplesPerPageLimit is this same limit, but discounting + * PageReservedSpace (which can be zero), so is appropriate for defining data + * structures which require fixed-size buffers. Code should not assume + * MaxHeapTuplesPerPage() == MaxHeapTuplesPerPageLimit, so if iterating over + * such a structure, the *size* of the buffer should be + * MaxHeapTuplesPerPageLimit, but the limits of iteration should be + * MaxHeapTuplesPerPage(), implying that MaxHeapTuplesPerPage() <= + * MaxHeapTuplesPerPageLimit. * * Note: with HOT, there could theoretically be more line pointers (not actual * tuples) than this on a heap page. However we constrain the number of line * pointers to this anyway, to avoid excessive line-pointer bloat and not * require increases in the size of work arrays. */ -#define MaxHeapTuplesPerPage \ +#define MaxHeapTuplesPerPage() \ + ((int) ((BLCKSZ - SizeOfPageHeaderData - SizeOfPageReservedSpace()) / \ + (MAXALIGN(SizeofHeapTupleHeader) + sizeof(ItemIdData)))) +#define MaxHeapTuplesPerPageLimit \ ((int) ((BLCKSZ - SizeOfPageHeaderData) / \ (MAXALIGN(SizeofHeapTupleHeader) + sizeof(ItemIdData)))) diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h index 8e4f6864e5..18a2831443 100644 --- a/src/include/access/nbtree.h +++ b/src/include/access/nbtree.h @@ -162,29 +162,43 @@ typedef struct BTMetaPageData * attribute, which we account for here. */ #define BTMaxItemSize(page) \ - (MAXALIGN_DOWN((PageGetPageSize(page) - \ + (MAXALIGN_DOWN((PageGetPageSize(page) - SizeOfPageReservedSpace() - \ MAXALIGN(SizeOfPageHeaderData + 3*sizeof(ItemIdData)) - \ MAXALIGN(sizeof(BTPageOpaqueData))) / 3) - \ MAXALIGN(sizeof(ItemPointerData))) #define BTMaxItemSizeNoHeapTid(page) \ - MAXALIGN_DOWN((PageGetPageSize(page) - \ + MAXALIGN_DOWN((PageGetPageSize(page) - SizeOfPageReservedSpace() - \ MAXALIGN(SizeOfPageHeaderData + 3*sizeof(ItemIdData)) - \ MAXALIGN(sizeof(BTPageOpaqueData))) / 3) /* - * MaxTIDsPerBTreePage is an upper bound on the number of heap TIDs tuples - * that may be stored on a btree leaf page. It is used to size the - * per-page temporary buffers. + * MaxTIDsPerBTreePage() is an upper bound on the number of heap TIDs tuples + * that may be stored on a btree leaf page. It is used to size the per-page + * temporary buffers. This accounts for PageReservedSpace limit as well, so + * is a dynamic value depending on cluster settings. + * + * MaxTIDsPerBTreePageLimit is the same value without considering + * PageReservedSpace limit as well, so is used for fixed-size buffers, however + * code accessing these buffers should consider only MaxTIDsPerBTreePage() when + * iterating over then. * * Note: we don't bother considering per-tuple overheads here to keep * things simple (value is based on how many elements a single array of * heap TIDs must have to fill the space between the page header and * special area). The value is slightly higher (i.e. more conservative) * than necessary as a result, which is considered acceptable. + * + * Since this is a fixed-size upper limit we restrict to the max size of page + * reserved space; this does mean that we pay a cost of + * (MaxSizeOfPageReservedSpace / sizeof(ItemPointerData)) less tuples stored + * on a page. */ -#define MaxTIDsPerBTreePage \ - (int) ((BLCKSZ - SizeOfPageHeaderData - sizeof(BTPageOpaqueData)) / \ - sizeof(ItemPointerData)) +#define MaxTIDsPerBTreePage() \ + (int) ((BLCKSZ - SizeOfPageHeaderData - SizeOfPageReservedSpace() - \ + sizeof(BTPageOpaqueData)) / sizeof(ItemPointerData)) +#define MaxTIDsPerBTreePageLimit \ + (int) ((BLCKSZ - SizeOfPageHeaderData - \ + sizeof(BTPageOpaqueData)) / sizeof(ItemPointerData)) /* * The leaf-page fillfactor defaults to 90% but is user-adjustable. @@ -981,7 +995,7 @@ typedef struct BTScanPosData int lastItem; /* last valid index in items[] */ int itemIndex; /* current index in items[] */ - BTScanPosItem items[MaxTIDsPerBTreePage]; /* MUST BE LAST */ + BTScanPosItem items[MaxTIDsPerBTreePageLimit]; /* MUST BE LAST */ } BTScanPosData; typedef BTScanPosData *BTScanPos; diff --git a/src/include/access/spgist_private.h b/src/include/access/spgist_private.h index eb56b1c6b8..cfa2d622a7 100644 --- a/src/include/access/spgist_private.h +++ b/src/include/access/spgist_private.h @@ -447,6 +447,7 @@ typedef SpGistDeadTupleData *SpGistDeadTuple; #define SPGIST_PAGE_CAPACITY \ MAXALIGN_DOWN(BLCKSZ - \ SizeOfPageHeaderData - \ + SizeOfPageReservedSpace() - \ MAXALIGN(sizeof(SpGistPageOpaqueData))) /* diff --git a/src/include/storage/bufpage.h b/src/include/storage/bufpage.h index 2708c4b683..ea0dfc2645 100644 --- a/src/include/storage/bufpage.h +++ b/src/include/storage/bufpage.h @@ -19,6 +19,13 @@ #include "storage/item.h" #include "storage/off.h" +extern int reserved_page_size; + +#define SizeOfPageReservedSpace() reserved_page_size + +/* strict upper bound on the amount of space occupied we have reserved on + * pages in this cluster */ + /* * A postgres disk page is an abstraction layered on top of a postgres * disk block (which is simply a unit of i/o, see block.h). @@ -36,10 +43,10 @@ * | v pd_upper | * +-------------+------------------------------------+ * | | tupleN ... | - * +-------------+------------------+-----------------+ - * | ... tuple3 tuple2 tuple1 | "special space" | - * +--------------------------------+-----------------+ - * ^ pd_special + * +-------------+-----+------------+-----------------+ + * | ... tuple2 tuple1 | "special space" | "reserved" | + * +-------------------+------------+-----------------+ + * ^ pd_special ^ reserved_page_space * * a page is full when nothing can be added between pd_lower and * pd_upper. @@ -73,6 +80,8 @@ * stored as the page trailer. an access method should always * initialize its pages with PageInit and then set its own opaque * fields. + * + * XXX - update more comments here about reserved_page_space */ typedef Pointer Page; @@ -313,7 +322,7 @@ PageSetPageSizeAndVersion(Page page, Size size, uint8 version) static inline uint16 PageGetSpecialSize(Page page) { - return (PageGetPageSize(page) - ((PageHeader) page)->pd_special); + return (PageGetPageSize(page) - ((PageHeader) page)->pd_special - reserved_page_size); } /* @@ -325,7 +334,7 @@ static inline void PageValidateSpecialPointer(Page page) { Assert(page); - Assert(((PageHeader) page)->pd_special <= BLCKSZ); + Assert((((PageHeader) page)->pd_special + reserved_page_size) <= BLCKSZ); Assert(((PageHeader) page)->pd_special >= SizeOfPageHeaderData); } diff --git a/src/test/modules/test_ginpostinglist/test_ginpostinglist.c b/src/test/modules/test_ginpostinglist/test_ginpostinglist.c index 9a230097db..0416f0d504 100644 --- a/src/test/modules/test_ginpostinglist/test_ginpostinglist.c +++ b/src/test/modules/test_ginpostinglist/test_ginpostinglist.c @@ -88,9 +88,9 @@ Datum test_ginpostinglist(PG_FUNCTION_ARGS) { test_itemptr_pair(0, 2, 14); - test_itemptr_pair(0, MaxHeapTuplesPerPage, 14); - test_itemptr_pair(MaxBlockNumber, MaxHeapTuplesPerPage, 14); - test_itemptr_pair(MaxBlockNumber, MaxHeapTuplesPerPage, 16); + test_itemptr_pair(0, MaxHeapTuplesPerPage(), 14); + test_itemptr_pair(MaxBlockNumber, MaxHeapTuplesPerPage(), 14); + test_itemptr_pair(MaxBlockNumber, MaxHeapTuplesPerPage(), 16); PG_RETURN_VOID(); } diff --git a/src/test/regress/expected/insert.out b/src/test/regress/expected/insert.out index dd4354fc7d..b530ac0038 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, MaxHeapTupleSize()) INSERT INTO large_tuple_test (select 1, NULL); -- should still fit on the page INSERT INTO large_tuple_test (select 2, repeat('a', 1000)); @@ -100,7 +100,7 @@ SELECT pg_size_pretty(pg_relation_size('large_tuple_test'::regclass, 'main')); INSERT INTO large_tuple_test (select 3, NULL); -- now this tuple won't fit on the second page, but the insert should -- still succeed by extending the relation -INSERT INTO large_tuple_test (select 4, repeat('a', 8126)); +INSERT INTO large_tuple_test (select 4, repeat('a', 8062)); DROP TABLE large_tuple_test; -- -- check indirection (field/array assignment), cf bug #14265 diff --git a/src/test/regress/expected/vacuum.out b/src/test/regress/expected/vacuum.out index c63a157e5f..583a5a91ae 100644 --- a/src/test/regress/expected/vacuum.out +++ b/src/test/regress/expected/vacuum.out @@ -134,7 +134,7 @@ CREATE TABLE no_index_cleanup (i INT PRIMARY KEY, t TEXT); CREATE INDEX no_index_cleanup_idx ON no_index_cleanup(t); ALTER TABLE no_index_cleanup ALTER COLUMN t SET STORAGE EXTERNAL; INSERT INTO no_index_cleanup(i, t) VALUES (generate_series(1,30), - repeat('1234567890',269)); + repeat('1234567890',266)); -- index cleanup option is ignored if VACUUM FULL VACUUM (INDEX_CLEANUP TRUE, FULL TRUE) no_index_cleanup; VACUUM (FULL TRUE) no_index_cleanup; @@ -150,7 +150,7 @@ ALTER TABLE no_index_cleanup SET (vacuum_index_cleanup = auto); VACUUM no_index_cleanup; -- Parameter is set for both the parent table and its toast relation. INSERT INTO no_index_cleanup(i, t) VALUES (generate_series(31,60), - repeat('1234567890',269)); + repeat('1234567890',266)); DELETE FROM no_index_cleanup WHERE i < 45; -- Only toast index is cleaned up. ALTER TABLE no_index_cleanup SET (vacuum_index_cleanup = off, diff --git a/src/test/regress/sql/insert.sql b/src/test/regress/sql/insert.sql index bdcffd0314..0e31dcd1f8 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, MaxHeapTupleSize()) INSERT INTO large_tuple_test (select 1, NULL); -- should still fit on the page @@ -55,7 +55,7 @@ INSERT INTO large_tuple_test (select 3, NULL); -- now this tuple won't fit on the second page, but the insert should -- still succeed by extending the relation -INSERT INTO large_tuple_test (select 4, repeat('a', 8126)); +INSERT INTO large_tuple_test (select 4, repeat('a', 8062)); DROP TABLE large_tuple_test; diff --git a/src/test/regress/sql/vacuum.sql b/src/test/regress/sql/vacuum.sql index 9faa8a34a6..0aec01b88e 100644 --- a/src/test/regress/sql/vacuum.sql +++ b/src/test/regress/sql/vacuum.sql @@ -115,7 +115,7 @@ CREATE TABLE no_index_cleanup (i INT PRIMARY KEY, t TEXT); CREATE INDEX no_index_cleanup_idx ON no_index_cleanup(t); ALTER TABLE no_index_cleanup ALTER COLUMN t SET STORAGE EXTERNAL; INSERT INTO no_index_cleanup(i, t) VALUES (generate_series(1,30), - repeat('1234567890',269)); + repeat('1234567890',266)); -- index cleanup option is ignored if VACUUM FULL VACUUM (INDEX_CLEANUP TRUE, FULL TRUE) no_index_cleanup; VACUUM (FULL TRUE) no_index_cleanup; @@ -131,7 +131,7 @@ ALTER TABLE no_index_cleanup SET (vacuum_index_cleanup = auto); VACUUM no_index_cleanup; -- Parameter is set for both the parent table and its toast relation. INSERT INTO no_index_cleanup(i, t) VALUES (generate_series(31,60), - repeat('1234567890',269)); + repeat('1234567890',266)); DELETE FROM no_index_cleanup WHERE i < 45; -- Only toast index is cleaned up. ALTER TABLE no_index_cleanup SET (vacuum_index_cleanup = off, -- 2.31.1