From 0591bbd558ef23f756e6dcd2f4c5ee8250086040 Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Fri, 18 Jun 1999 16:47:23 +0000
Subject: [PATCH] Patch to allow vacuum on multi-segment tables, from Hiroshi
 Inoue

---
 src/backend/storage/smgr/md.c | 58 +++++++++++++++++++++++++++--------
 1 file changed, 46 insertions(+), 12 deletions(-)

diff --git a/src/backend/storage/smgr/md.c b/src/backend/storage/smgr/md.c
index 5d84956059f..b5d7b86c21d 100644
--- a/src/backend/storage/smgr/md.c
+++ b/src/backend/storage/smgr/md.c
@@ -7,7 +7,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.45 1999/06/11 02:39:43 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/storage/smgr/md.c,v 1.46 1999/06/18 16:47:23 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -674,11 +674,12 @@ mdnblocks(Relation reln)
 	segno = 0;
 	for (;;)
 	{
-		if (v->mdfd_lstbcnt == RELSEG_SIZE
-			|| (nblocks = _mdnblocks(v->mdfd_vfd, BLCKSZ)) == RELSEG_SIZE)
+		nblocks = _mdnblocks(v->mdfd_vfd, BLCKSZ);
+		if (nblocks > RELSEG_SIZE)
+			elog(FATAL, "segment too big in mdnblocks!");
+		v->mdfd_lstbcnt = nblocks;
+		if (nblocks == RELSEG_SIZE)
 		{
-
-			v->mdfd_lstbcnt = RELSEG_SIZE;
 			segno++;
 
 			if (v->mdfd_chain == (MdfdVec *) NULL)
@@ -711,22 +712,55 @@ mdtruncate(Relation reln, int nblocks)
 	MdfdVec    *v;
 
 #ifndef LET_OS_MANAGE_FILESIZE
-	int			curnblk;
+	int			curnblk,
+				i,
+				oldsegno,
+				newsegno,
+				lastsegblocks;
+	MdfdVec			**varray;
 
 	curnblk = mdnblocks(reln);
-	if (curnblk / RELSEG_SIZE > 0)
-	{
-		elog(NOTICE, "Can't truncate multi-segments relation %s",
-			reln->rd_rel->relname.data);
-		return curnblk;
-	}
+	if (nblocks > curnblk)
+		return -1;
+	oldsegno = curnblk / RELSEG_SIZE;
+	newsegno = nblocks / RELSEG_SIZE;
+
 #endif
 
 	fd = RelationGetFile(reln);
 	v = &Md_fdvec[fd];
 
+#ifndef LET_OS_MANAGE_FILESIZE
+	varray = (MdfdVec **)palloc((oldsegno + 1) * sizeof(MdfdVec *));
+	for (i = 0; i <= oldsegno; i++)
+	{
+		if (!v)
+			elog(ERROR,"segment isn't open in mdtruncate!");
+		varray[i] = v;
+		v = v->mdfd_chain;
+	}
+	for (i = oldsegno; i > newsegno; i--)
+	{
+		v = varray[i];
+		if (FileTruncate(v->mdfd_vfd, 0) < 0)
+		{
+			pfree(varray);
+			return -1;
+		}
+		v->mdfd_lstbcnt = 0;
+	}
+	/* Calculate the # of blocks in the last segment */
+	lastsegblocks = nblocks - (newsegno * RELSEG_SIZE);
+	v = varray[i];
+	pfree(varray);
+	if (FileTruncate(v->mdfd_vfd, lastsegblocks * BLCKSZ) < 0)
+		return -1;
+	v->mdfd_lstbcnt = lastsegblocks;
+#else
 	if (FileTruncate(v->mdfd_vfd, nblocks * BLCKSZ) < 0)
 		return -1;
+	v->mdfd_lstbcnt = nblocks;
+#endif
 
 	return nblocks;
 
-- 
GitLab