@@ -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)
441472 nunused ;
442473 int i ;
443474 Size 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)
515545 errmsg ("corrupted item lengths: total %u, available space %u" ,
516546 (unsigned int ) 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)
782795 Offset pd_upper = phdr -> pd_upper ;
783796 Offset pd_special = phdr -> pd_special ;
784797 itemIdSortData itemidbase [MaxIndexTuplesPerPage ];
798+ ItemIdData newitemids [MaxIndexTuplesPerPage ];
785799 itemIdSort itemidptr ;
786800 ItemId lp ;
787801 int nline ,
788802 nused ;
789- int i ;
790803 Size totallen ;
791- Offset upper ;
792804 Size size ;
793805 unsigned offset ;
794806 int nextitm ;
@@ -857,9 +869,9 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
857869 {
858870 itemidptr -> offsetindex = nused ; /* where it will go */
859871 itemidptr -> itemoff = offset ;
860- itemidptr -> olditemid = * lp ;
861872 itemidptr -> alignedlen = MAXALIGN (size );
862873 totallen += itemidptr -> alignedlen ;
874+ newitemids [nused ] = * lp ;
863875 itemidptr ++ ;
864876 nused ++ ;
865877 }
@@ -875,26 +887,15 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
875887 errmsg ("corrupted item lengths: total %u, available space %u" ,
876888 (unsigned int ) 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 ));
896895 phdr -> 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)
10001001 itemIdSort itemidptr ;
10011002 int i ;
10021003 Size 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 */
10131013 itemidptr = itemidbase ;
10141014 totallen = 0 ;
1015- for (i = 0 ; i < nline ; i ++ , itemidptr ++ )
1015+ PageClearHasFreeLinePointers (page );
1016+ for (i = 0 ; i < nline ; i ++ )
10161017 {
10171018 ItemId lp ;
10181019
@@ -1024,13 +1025,15 @@ PageIndexDeleteNoCompact(Page page, OffsetNumber *itemnos, int nitems)
10241025 itemidptr -> itemoff = ItemIdGetOffset (lp );
10251026 itemidptr -> alignedlen = MAXALIGN (ItemIdGetLength (lp ));
10261027 totallen += itemidptr -> alignedlen ;
1028+ itemidptr ++ ;
10271029 }
10281030 else
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
10361039 if (totallen > (Size ) (pd_special - pd_lower ))
@@ -1039,38 +1042,11 @@ PageIndexDeleteNoCompact(Page page, OffsetNumber *itemnos, int nitems)
10391042 errmsg ("corrupted item lengths: total %u, available space %u" ,
10401043 (unsigned int ) 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
0 commit comments