From bb42e21be274a71f6868ce2fc8fae2c15c3ecf66 Mon Sep 17 00:00:00 2001
From: Heikki Linnakangas <heikki.linnakangas@iki.fi>
Date: Mon, 24 Mar 2014 18:40:26 +0200
Subject: [PATCH] Change ginMergeItemPointers to return a palloc'd array.

That seems nicer than making it the caller's responsibility to pass a
suitable-sized array. All the callers were just palloc'ing an array anyway.
---
 src/backend/access/gin/gindatapage.c    |  7 ++---
 src/backend/access/gin/gininsert.c      |  9 ++----
 src/backend/access/gin/ginpostinglist.c | 40 +++++++++++++------------
 src/include/access/gin_private.h        |  6 ++--
 4 files changed, 30 insertions(+), 32 deletions(-)

diff --git a/src/backend/access/gin/gindatapage.c b/src/backend/access/gin/gindatapage.c
index c6230f3bc5a..313d53c354f 100644
--- a/src/backend/access/gin/gindatapage.c
+++ b/src/backend/access/gin/gindatapage.c
@@ -1303,10 +1303,9 @@ addItemsToLeaf(disassembledLeaf *leaf, ItemPointer newItems, int nNewItems)
 		if (!cur->items)
 			cur->items = ginPostingListDecode(cur->seg, &cur->nitems);
 
-		tmpitems = palloc((cur->nitems + nthis) * sizeof(ItemPointerData));
-		ntmpitems = ginMergeItemPointers(tmpitems,
-										 cur->items, cur->nitems,
-										 nextnew, nthis);
+		tmpitems = ginMergeItemPointers(cur->items, cur->nitems,
+										nextnew, nthis,
+										&ntmpitems);
 		if (ntmpitems != cur->nitems)
 		{
 			cur->items = tmpitems;
diff --git a/src/backend/access/gin/gininsert.c b/src/backend/access/gin/gininsert.c
index cd9c7c120b3..3bafb6471b3 100644
--- a/src/backend/access/gin/gininsert.c
+++ b/src/backend/access/gin/gininsert.c
@@ -67,12 +67,9 @@ addItemPointersToLeafTuple(GinState *ginstate,
 	/* merge the old and new posting lists */
 	oldItems = ginReadTuple(ginstate, attnum, old, &oldNPosting);
 
-	newNPosting = oldNPosting + nitem;
-	newItems = (ItemPointerData *) palloc(sizeof(ItemPointerData) * newNPosting);
-
-	newNPosting = ginMergeItemPointers(newItems,
-									   items, nitem,
-									   oldItems, oldNPosting);
+	newItems = ginMergeItemPointers(items, nitem,
+									oldItems, oldNPosting,
+									&newNPosting);
 
 	/* Compress the posting list, and try to a build tuple with room for it */
 	res = NULL;
diff --git a/src/backend/access/gin/ginpostinglist.c b/src/backend/access/gin/ginpostinglist.c
index f532a3dbf03..4c4110d54b1 100644
--- a/src/backend/access/gin/ginpostinglist.c
+++ b/src/backend/access/gin/ginpostinglist.c
@@ -346,20 +346,18 @@ ginPostingListDecodeAllSegmentsToTbm(GinPostingList *ptr, int len,
 
 /*
  * Merge two ordered arrays of itempointers, eliminating any duplicates.
- * Returns the number of items in the result.
- * Caller is responsible that there is enough space at *dst.
  *
- * It's OK if 'dst' overlaps with the *beginning* of one of the arguments.
+ * Returns a palloc'd array, and *nmerged is set to the number of items in
+ * the result, after eliminating duplicates.
  */
-int
-ginMergeItemPointers(ItemPointerData *dst,
-					 ItemPointerData *a, uint32 na,
-					 ItemPointerData *b, uint32 nb)
+ItemPointer
+ginMergeItemPointers(ItemPointerData *a, uint32 na,
+					 ItemPointerData *b, uint32 nb,
+					 int *nmerged)
 {
-	ItemPointerData *dptr = dst;
-	ItemPointerData *aptr = a,
-			   *bptr = b;
-	int			result;
+	ItemPointerData *dst;
+
+	dst = (ItemPointer) palloc((na + nb) * sizeof(ItemPointerData));
 
 	/*
 	 * If the argument arrays don't overlap, we can just append them to
@@ -367,18 +365,22 @@ ginMergeItemPointers(ItemPointerData *dst,
 	 */
 	if (na == 0 || nb == 0 || ginCompareItemPointers(&a[na - 1], &b[0]) < 0)
 	{
-		memmove(dst, a, na * sizeof(ItemPointerData));
-		memmove(&dst[na], b, nb * sizeof(ItemPointerData));
-		result = na + nb;
+		memcpy(dst, a, na * sizeof(ItemPointerData));
+		memcpy(&dst[na], b, nb * sizeof(ItemPointerData));
+		*nmerged = na + nb;
 	}
 	else if (ginCompareItemPointers(&b[nb - 1], &a[0]) < 0)
 	{
-		memmove(dst, b, nb * sizeof(ItemPointerData));
-		memmove(&dst[nb], a, na * sizeof(ItemPointerData));
-		result = na + nb;
+		memcpy(dst, b, nb * sizeof(ItemPointerData));
+		memcpy(&dst[nb], a, na * sizeof(ItemPointerData));
+		*nmerged = na + nb;
 	}
 	else
 	{
+		ItemPointerData *dptr = dst;
+		ItemPointerData *aptr = a;
+		ItemPointerData *bptr = b;
+
 		while (aptr - a < na && bptr - b < nb)
 		{
 			int			cmp = ginCompareItemPointers(aptr, bptr);
@@ -401,8 +403,8 @@ ginMergeItemPointers(ItemPointerData *dst,
 		while (bptr - b < nb)
 			*dptr++ = *bptr++;
 
-		result = dptr - dst;
+		*nmerged = dptr - dst;
 	}
 
-	return result;
+	return dst;
 }
diff --git a/src/include/access/gin_private.h b/src/include/access/gin_private.h
index 009927282f5..a7beed1f256 100644
--- a/src/include/access/gin_private.h
+++ b/src/include/access/gin_private.h
@@ -919,9 +919,9 @@ extern int ginPostingListDecodeAllSegmentsToTbm(GinPostingList *ptr, int totalsi
 
 extern ItemPointer ginPostingListDecodeAllSegments(GinPostingList *ptr, int len, int *ndecoded);
 extern ItemPointer ginPostingListDecode(GinPostingList *ptr, int *ndecoded);
-extern int ginMergeItemPointers(ItemPointerData *dst,
-					 ItemPointerData *a, uint32 na,
-					 ItemPointerData *b, uint32 nb);
+extern ItemPointer ginMergeItemPointers(ItemPointerData *a, uint32 na,
+					 ItemPointerData *b, uint32 nb,
+					 int *nmerged);
 
 /*
  * Merging the results of several gin scans compares item pointers a lot,
-- 
GitLab