@@ -415,8 +415,7 @@ PageRestoreTempPage(Page tempPage, Page oldPage)
415415}
416416
417417/*
418- * sorting support for PageRepairFragmentation, PageIndexMultiDelete,
419- * PageIndexDeleteNoCompact
418+ * sorting support for PageRepairFragmentation and PageIndexMultiDelete
420419 */
421420typedef struct itemIdSortData
422421{
@@ -762,15 +761,14 @@ PageIndexTupleDelete(Page page, OffsetNumber offnum)
762761 * Now move everything between the old upper bound (beginning of tuple
763762 * space) and the beginning of the deleted tuple forward, so that space in
764763 * the middle of the page is left free. If we've just deleted the tuple
765- * at the beginning of tuple space, then there's no need to do the copy
766- * (and bcopy on some architectures SEGV's if asked to move zero bytes).
764+ * at the beginning of tuple space, then there's no need to do the copy.
767765 */
768766
769767/* beginning of tuple space */
770768addr = (char * )page + phdr -> pd_upper ;
771769
772770if (offset > phdr -> pd_upper )
773- memmove (addr + size ,addr ,( int ) ( offset - phdr -> pd_upper ) );
771+ memmove (addr + size ,addr ,offset - phdr -> pd_upper );
774772
775773/* adjust free space boundary pointers */
776774phdr -> pd_upper += size ;
@@ -918,155 +916,105 @@ PageIndexMultiDelete(Page page, OffsetNumber *itemnos, int nitems)
918916compactify_tuples (itemidbase ,nused ,page );
919917}
920918
919+
921920/*
922- * PageIndexDeleteNoCompact
923- *Delete the given items for an index page, and defragment the resulting
924- *free space, but do not compact the item pointers array.
925- *
926- * itemnos is the array of tuples to delete; nitems is its size. maxIdxTuples
927- * is the maximum number of tuples that can exist in a page.
921+ * PageIndexTupleDeleteNoCompact
928922 *
929- * Unused items at the end of the array are removed.
923+ * Remove the specified tuple from an index page, but set its line pointer
924+ * to "unused" instead of compacting it out, except that it can be removed
925+ * if it's the last line pointer on the page.
930926 *
931927 * This is used for index AMs that require that existing TIDs of live tuples
932- * remain unchanged.
928+ * remain unchanged, and are willing to allow unused line pointers instead .
933929 */
934930void
935- PageIndexDeleteNoCompact (Page page ,OffsetNumber * itemnos , int nitems )
931+ PageIndexTupleDeleteNoCompact (Page page ,OffsetNumber offnum )
936932{
937933PageHeader phdr = (PageHeader )page ;
938- LocationIndex pd_lower = phdr -> pd_lower ;
939- LocationIndex pd_upper = phdr -> pd_upper ;
940- LocationIndex pd_special = phdr -> pd_special ;
934+ char * addr ;
935+ ItemId tup ;
936+ Size size ;
937+ unsigned offset ;
941938int nline ;
942- bool empty ;
943- OffsetNumber offnum ;
944- int nextitm ;
945939
946940/*
947941 * As with PageRepairFragmentation, paranoia seems justified.
948942 */
949- if (pd_lower < SizeOfPageHeaderData ||
950- pd_lower > pd_upper ||
951- pd_upper > pd_special ||
952- pd_special > BLCKSZ ||
953- pd_special != MAXALIGN (pd_special ))
943+ if (phdr -> pd_lower < SizeOfPageHeaderData ||
944+ phdr -> pd_lower > phdr -> pd_upper ||
945+ phdr -> pd_upper > phdr -> pd_special ||
946+ phdr -> pd_special > BLCKSZ ||
947+ phdr -> pd_special != MAXALIGN (phdr -> pd_special ))
954948ereport (ERROR ,
955949(errcode (ERRCODE_DATA_CORRUPTED ),
956950errmsg ("corrupted page pointers: lower = %u, upper = %u, special = %u" ,
957- pd_lower ,pd_upper ,pd_special )));
951+ phdr -> pd_lower ,phdr -> pd_upper ,phdr -> pd_special )));
952+
953+ nline = PageGetMaxOffsetNumber (page );
954+ if ((int )offnum <=0 || (int )offnum > nline )
955+ elog (ERROR ,"invalid index offnum: %u" ,offnum );
956+
957+ tup = PageGetItemId (page ,offnum );
958+ Assert (ItemIdHasStorage (tup ));
959+ size = ItemIdGetLength (tup );
960+ offset = ItemIdGetOffset (tup );
961+
962+ if (offset < phdr -> pd_upper || (offset + size )> phdr -> pd_special ||
963+ offset != MAXALIGN (offset ))
964+ ereport (ERROR ,
965+ (errcode (ERRCODE_DATA_CORRUPTED ),
966+ errmsg ("corrupted item pointer: offset = %u, size = %u" ,
967+ offset , (unsignedint )size )));
968+
969+ /* Amount of space to actually be deleted */
970+ size = MAXALIGN (size );
958971
959972/*
960- *Scan theexisting item pointerarray and mark as unused those that are
961- *in our kill-list; make sure any non-interesting ones aremarked unused
962- *as well.
973+ *Either set the item pointerto "unused", or zap it if it's the last
974+ *one. (Note: it's possible that the next-to-last one(s) arealready
975+ *unused, but we do not trouble to try to compact them out if so.)
963976 */
964- nline = PageGetMaxOffsetNumber (page );
965- empty = true;
966- nextitm = 0 ;
967- for (offnum = FirstOffsetNumber ;offnum <=nline ;offnum = OffsetNumberNext (offnum ))
977+ if ((int )offnum < nline )
978+ ItemIdSetUnused (tup );
979+ else
968980{
969- ItemId lp ;
970- ItemLength itemlen ;
971- ItemOffset offset ;
981+ phdr -> pd_lower -= sizeof ( ItemIdData ) ;
982+ nline -- ; /* there's one less than when we started */
983+ }
972984
973- lp = PageGetItemId (page ,offnum );
985+ /*
986+ * Now move everything between the old upper bound (beginning of tuple
987+ * space) and the beginning of the deleted tuple forward, so that space in
988+ * the middle of the page is left free. If we've just deleted the tuple
989+ * at the beginning of tuple space, then there's no need to do the copy.
990+ */
974991
975- itemlen = ItemIdGetLength ( lp );
976- offset = ItemIdGetOffset ( lp ) ;
992+ /* beginning of tuple space */
993+ addr = ( char * ) page + phdr -> pd_upper ;
977994
978- if (ItemIdIsUsed (lp ))
979- {
980- if (offset < pd_upper ||
981- (offset + itemlen )> pd_special ||
982- offset != MAXALIGN (offset ))
983- ereport (ERROR ,
984- (errcode (ERRCODE_DATA_CORRUPTED ),
985- errmsg ("corrupted item pointer: offset = %u, length = %u" ,
986- offset , (unsignedint )itemlen )));
987-
988- if (nextitm < nitems && offnum == itemnos [nextitm ])
989- {
990- /* this one is on our list to delete, so mark it unused */
991- ItemIdSetUnused (lp );
992- nextitm ++ ;
993- }
994- else if (ItemIdHasStorage (lp ))
995- {
996- /* This one's live -- must do the compaction dance */
997- empty = false;
998- }
999- else
1000- {
1001- /* get rid of this one too */
1002- ItemIdSetUnused (lp );
1003- }
1004- }
1005- }
995+ if (offset > phdr -> pd_upper )
996+ memmove (addr + size ,addr ,offset - phdr -> pd_upper );
1006997
1007- /* this will catch invalid or out-of-order itemnos[] */
1008- if (nextitm != nitems )
1009- elog (ERROR ,"incorrect index offsets supplied" );
998+ /* adjust free space boundary pointer */
999+ phdr -> pd_upper += size ;
10101000
1011- if ( empty )
1012- {
1013- /* Page is completely empty, so just reset it quickly */
1014- phdr -> pd_lower = SizeOfPageHeaderData ;
1015- phdr -> pd_upper = pd_special ;
1016- }
1017- else
1001+ /*
1002+ * Finally, we need to adjust the linp entries that remain.
1003+ *
1004+ * Anything that used to be before the deleted tuple's data was moved
1005+ * forward by the size of the deleted tuple.
1006+ */
1007+ if (! PageIsEmpty ( page ))
10181008{
1019- /* There are live items: need to compact the page the hard way */
1020- itemIdSortData itemidbase [MaxOffsetNumber ];
1021- itemIdSort itemidptr ;
10221009int i ;
1023- Size totallen ;
10241010
1025- /*
1026- * Scan the page taking note of each item that we need to preserve.
1027- * This includes both live items (those that contain data) and
1028- * interspersed unused ones. It's critical to preserve these unused
1029- * items, because otherwise the offset numbers for later live items
1030- * would change, which is not acceptable. Unused items might get used
1031- * again later; that is fine.
1032- */
1033- itemidptr = itemidbase ;
1034- totallen = 0 ;
1035- PageClearHasFreeLinePointers (page );
1036- for (i = 0 ;i < nline ;i ++ )
1011+ for (i = 1 ;i <=nline ;i ++ )
10371012{
1038- ItemId lp ;
1039-
1040- itemidptr -> offsetindex = i ;
1013+ ItemId ii = PageGetItemId (phdr ,i );
10411014
1042- lp = PageGetItemId (page ,i + 1 );
1043- if (ItemIdHasStorage (lp ))
1044- {
1045- itemidptr -> itemoff = ItemIdGetOffset (lp );
1046- itemidptr -> alignedlen = MAXALIGN (ItemIdGetLength (lp ));
1047- totallen += itemidptr -> alignedlen ;
1048- itemidptr ++ ;
1049- }
1050- else
1051- {
1052- PageSetHasFreeLinePointers (page );
1053- ItemIdSetUnused (lp );
1054- }
1015+ if (ItemIdHasStorage (ii )&& ItemIdGetOffset (ii ) <=offset )
1016+ ii -> lp_off += size ;
10551017}
1056- nline = itemidptr - itemidbase ;
1057- /* By here, there are exactly nline elements in itemidbase array */
1058-
1059- if (totallen > (Size ) (pd_special - pd_lower ))
1060- ereport (ERROR ,
1061- (errcode (ERRCODE_DATA_CORRUPTED ),
1062- errmsg ("corrupted item lengths: total %u, available space %u" ,
1063- (unsignedint )totallen ,pd_special - pd_lower )));
1064-
1065- /*
1066- * Defragment the data areas of each tuple, being careful to preserve
1067- * each item's position in the linp array.
1068- */
1069- compactify_tuples (itemidbase ,nline ,page );
10701018}
10711019}
10721020