@@ -1847,7 +1847,8 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
18471847 */
18481848 buffer = RelationGetBufferForTuple (relation , heaptup -> t_len ,
18491849 InvalidBuffer , options , bistate ,
1850- & vmbuffer , NULL );
1850+ & vmbuffer , NULL ,
1851+ 0 );
18511852
18521853 /*
18531854 * We're about to do the actual insert -- but check for conflict first, to
@@ -2050,6 +2051,32 @@ heap_prepare_insert(Relation relation, HeapTuple tup, TransactionId xid,
20502051 return tup ;
20512052}
20522053
2054+ /*
2055+ * Helper for heap_multi_insert() that computes the number of entire pages
2056+ * that inserting the remaining heaptuples requires. Used to determine how
2057+ * much the relation needs to be extended by.
2058+ */
2059+ static int
2060+ heap_multi_insert_pages (HeapTuple * heaptuples , int done , int ntuples , Size saveFreeSpace )
2061+ {
2062+ size_t page_avail = BLCKSZ - SizeOfPageHeaderData - saveFreeSpace ;
2063+ int npages = 1 ;
2064+
2065+ for (int i = done ; i < ntuples ; i ++ )
2066+ {
2067+ size_t tup_sz = sizeof (ItemIdData ) + MAXALIGN (heaptuples [i ]-> t_len );
2068+
2069+ if (page_avail < tup_sz )
2070+ {
2071+ npages ++ ;
2072+ page_avail = BLCKSZ - SizeOfPageHeaderData - saveFreeSpace ;
2073+ }
2074+ page_avail -= tup_sz ;
2075+ }
2076+
2077+ return npages ;
2078+ }
2079+
20532080/*
20542081 * heap_multi_insert - insert multiple tuples into a heap
20552082 *
@@ -2076,6 +2103,9 @@ heap_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples,
20762103 Size saveFreeSpace ;
20772104 bool need_tuple_data = RelationIsLogicallyLogged (relation );
20782105 bool need_cids = RelationIsAccessibleInLogicalDecoding (relation );
2106+ bool starting_with_empty_page = false;
2107+ int npages = 0 ;
2108+ int npages_used = 0 ;
20792109
20802110 /* currently not needed (thus unsupported) for heap_multi_insert() */
20812111 Assert (!(options & HEAP_INSERT_NO_LOGICAL ));
@@ -2126,13 +2156,31 @@ heap_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples,
21262156 while (ndone < ntuples )
21272157 {
21282158 Buffer buffer ;
2129- bool starting_with_empty_page ;
21302159 bool all_visible_cleared = false;
21312160 bool all_frozen_set = false;
21322161 int nthispage ;
21332162
21342163 CHECK_FOR_INTERRUPTS ();
21352164
2165+ /*
2166+ * Compute number of pages needed to fit the to-be-inserted tuples in
2167+ * the worst case. This will be used to determine how much to extend
2168+ * the relation by in RelationGetBufferForTuple(), if needed. If we
2169+ * filled a prior page from scratch, we can just update our last
2170+ * computation, but if we started with a partially filled page,
2171+ * recompute from scratch, the number of potentially required pages
2172+ * can vary due to tuples needing to fit onto the page, page headers
2173+ * etc.
2174+ */
2175+ if (ndone == 0 || !starting_with_empty_page )
2176+ {
2177+ npages = heap_multi_insert_pages (heaptuples , ndone , ntuples ,
2178+ saveFreeSpace );
2179+ npages_used = 0 ;
2180+ }
2181+ else
2182+ npages_used ++ ;
2183+
21362184 /*
21372185 * Find buffer where at least the next tuple will fit. If the page is
21382186 * all-visible, this will also pin the requisite visibility map page.
@@ -2142,7 +2190,8 @@ heap_multi_insert(Relation relation, TupleTableSlot **slots, int ntuples,
21422190 */
21432191 buffer = RelationGetBufferForTuple (relation , heaptuples [ndone ]-> t_len ,
21442192 InvalidBuffer , options , bistate ,
2145- & vmbuffer , NULL );
2193+ & vmbuffer , NULL ,
2194+ npages - npages_used );
21462195 page = BufferGetPage (buffer );
21472196
21482197 starting_with_empty_page = PageGetMaxOffsetNumber (page ) == 0 ;
@@ -3576,7 +3625,8 @@ heap_update(Relation relation, ItemPointer otid, HeapTuple newtup,
35763625 /* It doesn't fit, must use RelationGetBufferForTuple. */
35773626 newbuf = RelationGetBufferForTuple (relation , heaptup -> t_len ,
35783627 buffer , 0 , NULL ,
3579- & vmbuffer_new , & vmbuffer );
3628+ & vmbuffer_new , & vmbuffer ,
3629+ 0 );
35803630 /* We're all done. */
35813631 break ;
35823632 }
0 commit comments