@@ -404,10 +404,9 @@ PageRestoreTempPage(Page tempPage, Page oldPage)
404404 */
405405typedef struct itemIdSortData
406406{
407- int offsetindex ;/* linp array index */
408- int itemoff ;/* page offset of item data */
409- Size alignedlen ;/* MAXALIGN(item data len) */
410- ItemIdData olditemid ;/* used only in PageIndexMultiDelete */
407+ uint16 offsetindex ;/* linp array index */
408+ int16 itemoff ;/* page offset of item data */
409+ uint16 alignedlen ;/* MAXALIGN(item data len) */
411410}itemIdSortData ;
412411typedef itemIdSortData * itemIdSort ;
413412
@@ -419,6 +418,38 @@ itemoffcompare(const void *itemidp1, const void *itemidp2)
419418((itemIdSort )itemidp1 )-> itemoff ;
420419}
421420
421+ /*
422+ * After removing or marking some line pointers unused, move the tuples to
423+ * remove the gaps caused by the removed items.
424+ */
425+ static void
426+ compactify_tuples (itemIdSort itemidbase ,int nitems ,Page page )
427+ {
428+ PageHeader phdr = (PageHeader )page ;
429+ Offset upper ;
430+ int i ;
431+
432+ /* sort itemIdSortData array into decreasing itemoff order */
433+ qsort ((char * )itemidbase ,nitems ,sizeof (itemIdSortData ),
434+ itemoffcompare );
435+
436+ upper = phdr -> pd_special ;
437+ for (i = 0 ;i < nitems ;i ++ )
438+ {
439+ itemIdSort itemidptr = & itemidbase [i ];
440+ ItemId lp ;
441+
442+ lp = PageGetItemId (page ,itemidptr -> offsetindex + 1 );
443+ upper -= itemidptr -> alignedlen ;
444+ memmove ((char * )page + upper ,
445+ (char * )page + itemidptr -> itemoff ,
446+ itemidptr -> alignedlen );
447+ lp -> lp_off = upper ;
448+ }
449+
450+ phdr -> pd_upper = upper ;
451+ }
452+
422453/*
423454 * PageRepairFragmentation
424455 *
@@ -441,7 +472,6 @@ PageRepairFragmentation(Page page)
441472nunused ;
442473int i ;
443474Size totallen ;
444- Offset upper ;
445475
446476/*
447477 * It's worth the trouble to be more paranoid here than in most places,
@@ -515,24 +545,7 @@ PageRepairFragmentation(Page page)
515545errmsg ("corrupted item lengths: total %u, available space %u" ,
516546 (unsignedint )totallen ,pd_special - pd_lower )));
517547
518- /* sort itemIdSortData array into decreasing itemoff order */
519- qsort ((char * )itemidbase ,nstorage ,sizeof (itemIdSortData ),
520- itemoffcompare );
521-
522- /* compactify page */
523- upper = pd_special ;
524-
525- for (i = 0 ,itemidptr = itemidbase ;i < nstorage ;i ++ ,itemidptr ++ )
526- {
527- lp = PageGetItemId (page ,itemidptr -> offsetindex + 1 );
528- upper -= itemidptr -> alignedlen ;
529- memmove ((char * )page + upper ,
530- (char * )page + itemidptr -> itemoff ,
531- itemidptr -> alignedlen );
532- lp -> lp_off = upper ;
533- }
534-
535- ((PageHeader )page )-> pd_upper = upper ;
548+ compactify_tuples (itemidbase ,nstorage ,page );
536549}
537550
538551/* Set hint bit for PageAddItem */
@@ -782,13 +795,12 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
782795Offset pd_upper = phdr -> pd_upper ;
783796Offset pd_special = phdr -> pd_special ;
784797itemIdSortData itemidbase [MaxIndexTuplesPerPage ];
798+ ItemIdData newitemids [MaxIndexTuplesPerPage ];
785799itemIdSort itemidptr ;
786800ItemId lp ;
787801int nline ,
788802nused ;
789- int i ;
790803Size totallen ;
791- Offset upper ;
792804Size size ;
793805unsigned offset ;
794806int nextitm ;
@@ -857,9 +869,9 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
857869{
858870itemidptr -> offsetindex = nused ;/* where it will go */
859871itemidptr -> itemoff = offset ;
860- itemidptr -> olditemid = * lp ;
861872itemidptr -> alignedlen = MAXALIGN (size );
862873totallen += itemidptr -> alignedlen ;
874+ newitemids [nused ]= * lp ;
863875itemidptr ++ ;
864876nused ++ ;
865877}
@@ -875,26 +887,15 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
875887errmsg ("corrupted item lengths: total %u, available space %u" ,
876888 (unsignedint )totallen ,pd_special - pd_lower )));
877889
878- /* sort itemIdSortData array into decreasing itemoff order */
879- qsort ((char * )itemidbase ,nused ,sizeof (itemIdSortData ),
880- itemoffcompare );
881-
882- /* compactify page and install new itemids */
883- upper = pd_special ;
884-
885- for (i = 0 ,itemidptr = itemidbase ;i < nused ;i ++ ,itemidptr ++ )
886- {
887- lp = PageGetItemId (page ,itemidptr -> offsetindex + 1 );
888- upper -= itemidptr -> alignedlen ;
889- memmove ((char * )page + upper ,
890- (char * )page + itemidptr -> itemoff ,
891- itemidptr -> alignedlen );
892- * lp = itemidptr -> olditemid ;
893- lp -> lp_off = upper ;
894- }
895-
890+ /*
891+ * Looks good. Overwrite the line pointers with the copy, from which we've
892+ * removed all the unused items.
893+ */
894+ memcpy (phdr -> pd_linp ,newitemids ,nused * sizeof (ItemIdData ));
896895phdr -> pd_lower = SizeOfPageHeaderData + nused * sizeof (ItemIdData );
897- phdr -> pd_upper = upper ;
896+
897+ /* and compactify the tuple data */
898+ compactify_tuples (itemidbase ,nused ,page );
898899}
899900
900901/*
@@ -1000,7 +1001,6 @@ PageIndexDeleteNoCompact(Page page, OffsetNumber *itemnos, int nitems)
10001001itemIdSort itemidptr ;
10011002int i ;
10021003Size totallen ;
1003- Offset upper ;
10041004
10051005/*
10061006 * Scan the page taking note of each item that we need to preserve.
@@ -1012,7 +1012,8 @@ PageIndexDeleteNoCompact(Page page, OffsetNumber *itemnos, int nitems)
10121012 */
10131013itemidptr = itemidbase ;
10141014totallen = 0 ;
1015- for (i = 0 ;i < nline ;i ++ ,itemidptr ++ )
1015+ PageClearHasFreeLinePointers (page );
1016+ for (i = 0 ;i < nline ;i ++ )
10161017{
10171018ItemId lp ;
10181019
@@ -1024,13 +1025,15 @@ PageIndexDeleteNoCompact(Page page, OffsetNumber *itemnos, int nitems)
10241025itemidptr -> itemoff = ItemIdGetOffset (lp );
10251026itemidptr -> alignedlen = MAXALIGN (ItemIdGetLength (lp ));
10261027totallen += itemidptr -> alignedlen ;
1028+ itemidptr ++ ;
10271029}
10281030else
10291031{
1030- itemidptr -> itemoff = 0 ;
1031- itemidptr -> alignedlen = 0 ;
1032+ PageSetHasFreeLinePointers ( page ) ;
1033+ ItemIdSetUnused ( lp ) ;
10321034}
10331035}
1036+ nline = itemidptr - itemidbase ;
10341037/* By here, there are exactly nline elements in itemidbase array */
10351038
10361039if (totallen > (Size ) (pd_special - pd_lower ))
@@ -1039,38 +1042,11 @@ PageIndexDeleteNoCompact(Page page, OffsetNumber *itemnos, int nitems)
10391042errmsg ("corrupted item lengths: total %u, available space %u" ,
10401043(unsignedint )totallen ,pd_special - pd_lower )));
10411044
1042- /* sort itemIdSortData array into decreasing itemoff order */
1043- qsort ((char * )itemidbase ,nline ,sizeof (itemIdSortData ),
1044- itemoffcompare );
1045-
10461045/*
10471046 * Defragment the data areas of each tuple, being careful to preserve
10481047 * each item's position in the linp array.
10491048 */
1050- upper = pd_special ;
1051- PageClearHasFreeLinePointers (page );
1052- for (i = 0 ,itemidptr = itemidbase ;i < nline ;i ++ ,itemidptr ++ )
1053- {
1054- ItemId lp ;
1055-
1056- lp = PageGetItemId (page ,itemidptr -> offsetindex + 1 );
1057- if (itemidptr -> alignedlen == 0 )
1058- {
1059- PageSetHasFreeLinePointers (page );
1060- ItemIdSetUnused (lp );
1061- continue ;
1062- }
1063- upper -= itemidptr -> alignedlen ;
1064- memmove ((char * )page + upper ,
1065- (char * )page + itemidptr -> itemoff ,
1066- itemidptr -> alignedlen );
1067- lp -> lp_off = upper ;
1068- /* lp_flags and lp_len remain the same as originally */
1069- }
1070-
1071- /* Set the new page limits */
1072- phdr -> pd_upper = upper ;
1073- phdr -> pd_lower = SizeOfPageHeaderData + i * sizeof (ItemIdData );
1049+ compactify_tuples (itemidbase ,nline ,page );
10741050}
10751051}
10761052