From 85376c6f7d0e2f40b3aed13d1c9c5967cdea13e1 Mon Sep 17 00:00:00 2001
From: Teodor Sigaev <teodor@sigaev.ru>
Date: Mon, 29 Oct 2007 13:49:21 +0000
Subject: [PATCH] Fix coredump during replay WAL after crash. Change
 entrySplitPage() to prevent usage of any information from system catalog,
 because it could be called during replay of WAL.

Per bug report from Craig McElroy <craig.mcelroy@contegix.com>. Patch doesn't
change on-disk storage.
---
 src/backend/access/gin/ginentrypage.c | 48 +++++++++++++++++----------
 1 file changed, 30 insertions(+), 18 deletions(-)

diff --git a/src/backend/access/gin/ginentrypage.c b/src/backend/access/gin/ginentrypage.c
index 70867ac40ba..2c335aea0cd 100644
--- a/src/backend/access/gin/ginentrypage.c
+++ b/src/backend/access/gin/ginentrypage.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *			$PostgreSQL: pgsql/src/backend/access/gin/ginentrypage.c,v 1.9 2007/09/20 17:56:30 tgl Exp $
+ *			$PostgreSQL: pgsql/src/backend/access/gin/ginentrypage.c,v 1.10 2007/10/29 13:49:21 teodor Exp $
  *-------------------------------------------------------------------------
  */
 
@@ -403,6 +403,31 @@ entryPlaceToPage(GinBtree btree, Buffer buf, OffsetNumber off, XLogRecData **prd
 	btree->entry = NULL;
 }
 
+/*
+ * Returns new tuple with copied value from source tuple.
+ * New tuple will not store posting list
+ */
+static IndexTuple
+copyIndexTuple(IndexTuple itup, Page page)
+{
+	IndexTuple	nitup;
+
+	if (GinPageIsLeaf(page) && !GinIsPostingTree(itup))
+	{
+		nitup = (IndexTuple) palloc(MAXALIGN(GinGetOrigSizePosting(itup)));
+		memcpy(nitup, itup, GinGetOrigSizePosting(itup));
+		nitup->t_info &= ~INDEX_SIZE_MASK;
+		nitup->t_info |= GinGetOrigSizePosting(itup);
+	}
+	else
+	{
+		nitup = (IndexTuple) palloc(MAXALIGN(IndexTupleSize(itup)));
+		memcpy(nitup, itup, IndexTupleSize(itup));
+	}
+
+	return nitup;
+}
+
 /*
  * Place tuple and split page, original buffer(lbuf) leaves untouched,
  * returns shadow page of lbuf filled new data.
@@ -424,8 +449,6 @@ entrySplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogR
 	IndexTuple	itup,
 				leftrightmost = NULL;
 	static ginxlogSplit data;
-	Datum		value;
-	bool		isnull;
 	Page		page;
 	Page		lpage = GinPageGetCopyPage(BufferGetPage(lbuf));
 	Page		rpage = BufferGetPage(rbuf);
@@ -494,9 +517,9 @@ entrySplitPage(GinBtree btree, Buffer lbuf, Buffer rbuf, OffsetNumber off, XLogR
 		ptr += MAXALIGN(IndexTupleSize(itup));
 	}
 
-	value = index_getattr(leftrightmost, FirstOffsetNumber, btree->ginstate->tupdesc, &isnull);
-	btree->entry = GinFormTuple(btree->ginstate, value, NULL, 0);
+	btree->entry = copyIndexTuple(leftrightmost, lpage);
 	ItemPointerSet(&(btree->entry)->t_tid, BufferGetBlockNumber(lbuf), InvalidOffsetNumber);
+
 	btree->rightblkno = BufferGetBlockNumber(rbuf);
 
 	data.node = btree->index->rd_node;
@@ -533,20 +556,9 @@ ginPageGetLinkItup(Buffer buf)
 	Page		page = BufferGetPage(buf);
 
 	itup = getRightMostTuple(page);
-	if (GinPageIsLeaf(page) && !GinIsPostingTree(itup))
-	{
-		nitup = (IndexTuple) palloc(MAXALIGN(GinGetOrigSizePosting(itup)));
-		memcpy(nitup, itup, GinGetOrigSizePosting(itup));
-		nitup->t_info &= ~INDEX_SIZE_MASK;
-		nitup->t_info |= GinGetOrigSizePosting(itup);
-	}
-	else
-	{
-		nitup = (IndexTuple) palloc(MAXALIGN(IndexTupleSize(itup)));
-		memcpy(nitup, itup, IndexTupleSize(itup));
-	}
-
+	nitup = copyIndexTuple(itup, page);
 	ItemPointerSet(&nitup->t_tid, BufferGetBlockNumber(buf), InvalidOffsetNumber);
+
 	return nitup;
 }
 
-- 
GitLab