diff --git a/src/backend/storage/page/bufpage.c b/src/backend/storage/page/bufpage.c index d708117a40..5bf35aff37 100644 --- a/src/backend/storage/page/bufpage.c +++ b/src/backend/storage/page/bufpage.c @@ -440,22 +440,53 @@ compactify_tuples(itemIdSort itemidbase, int nitems, Page page) Offset upper; int i; - /* sort itemIdSortData array into decreasing itemoff order */ - qsort((char *) itemidbase, nitems, sizeof(itemIdSortData), - itemoffcompare); + if (nitems > MaxHeapTuplesPerPage / 2) + { + char buffer[BLCKSZ + MAXIMUM_ALIGNOF]; + char *bufp = (char *) MAXALIGN(&buffer); + + /* + * Make a temp copy of the tuple data so that we can rearange + * the tuples freely without having to worry about stomping + * on the memory of other tuples. + */ + memcpy(bufp + phdr->pd_upper, + page + phdr->pd_upper, + phdr->pd_special - phdr->pd_upper); - upper = phdr->pd_special; - for (i = 0; i < nitems; i++) + upper = phdr->pd_special; + for (i = 0; i < nitems; i++) + { + itemIdSort itemidptr = &itemidbase[i]; + ItemId lp; + + lp = PageGetItemId(page, itemidptr->offsetindex + 1); + upper -= itemidptr->alignedlen; + memcpy((char *) page + upper, + bufp + itemidptr->itemoff, + itemidptr->alignedlen); + lp->lp_off = upper; + } + } + else { - itemIdSort itemidptr = &itemidbase[i]; - ItemId lp; - - lp = PageGetItemId(page, itemidptr->offsetindex + 1); - upper -= itemidptr->alignedlen; - memmove((char *) page + upper, - (char *) page + itemidptr->itemoff, - itemidptr->alignedlen); - lp->lp_off = upper; + /* sort itemIdSortData array into decreasing itemoff order */ + qsort((char *) itemidbase, nitems, sizeof(itemIdSortData), + itemoffcompare); + + upper = phdr->pd_special; + for (i = 0; i < nitems; i++) + { + itemIdSort itemidptr = &itemidbase[i]; + ItemId lp; + + lp = PageGetItemId(page, itemidptr->offsetindex + 1); + upper -= itemidptr->alignedlen; + memmove((char *) page + upper, + (char *) page + itemidptr->itemoff, + itemidptr->alignedlen); + lp->lp_off = upper; + } } phdr->pd_upper = upper;