From 610abfd57b2315a145d800e8f2d97b03509237df Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Thu, 25 May 2000 21:30:20 +0000
Subject: [PATCH] Do table renaming in a sane order: physical file rename must
 happen *last*, after all updating of system catalogs.  In old code, an error
 detected during TypeRename left the relation hosed.  Also, add a call to
 flush the relation's relcache entry, rather than trusting to shared cache
 invalidation to flush it for us.

---
 src/backend/commands/rename.c | 64 ++++++++++++++++++++---------------
 1 file changed, 36 insertions(+), 28 deletions(-)

diff --git a/src/backend/commands/rename.c b/src/backend/commands/rename.c
index 2531a084b31..7f46a3d83be 100644
--- a/src/backend/commands/rename.c
+++ b/src/backend/commands/rename.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.44 2000/05/19 03:22:29 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.45 2000/05/25 21:30:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -19,7 +19,6 @@
 #include "access/heapam.h"
 #include "catalog/catname.h"
 #include "catalog/pg_type.h"
-#include "utils/syscache.h"
 #include "catalog/heap.h"
 #include "catalog/indexing.h"
 #include "catalog/catalog.h"
@@ -29,6 +28,7 @@
 #include "optimizer/prep.h"
 #include "utils/acl.h"
 #include "utils/relcache.h"
+#include "utils/syscache.h"
 
 
 /*
@@ -183,6 +183,7 @@ renamerel(const char *oldrelname, const char *newrelname)
 	Relation	targetrelation;
 	Relation	relrelation;	/* for RELATION relation */
 	HeapTuple	oldreltup;
+	Oid			reloid;
 	char		relkind;
 	char		oldpath[MAXPGPATH],
 				newpath[MAXPGPATH],
@@ -228,6 +229,7 @@ renamerel(const char *oldrelname, const char *newrelname)
 	if (IsTransactionBlock() && !targetrelation->rd_myxactonly)
 		elog(NOTICE, "Caution: RENAME TABLE cannot be rolled back, so don't abort now");
 
+	reloid = RelationGetRelid(targetrelation);
 	relkind = targetrelation->rd_rel->relkind;
 
 	/*
@@ -254,13 +256,18 @@ renamerel(const char *oldrelname, const char *newrelname)
 
 	/*
 	 * Close rel, but keep exclusive lock!
-	 *
-	 * Note: we don't do anything about updating the relcache entry; we
-	 * assume it will be flushed by shared cache invalidate. XXX is this
-	 * good enough?  What if relation is myxactonly?
 	 */
 	heap_close(targetrelation, NoLock);
 
+	/*
+	 * Flush the relcache entry (easier than trying to change it at exactly
+	 * the right instant).  It'll get rebuilt on next access to relation.
+	 *
+	 * XXX What if relation is myxactonly?
+	 */
+	targetrelation = NULL;		/* make sure I don't touch it again */
+	RelationIdInvalidateRelationCacheByRelationId(reloid);
+
 	/*
 	 * Find relation's pg_class tuple, and make sure newrelname isn't in
 	 * use.
@@ -276,9 +283,31 @@ renamerel(const char *oldrelname, const char *newrelname)
 	if (RelnameFindRelid(newrelname) != InvalidOid)
 		elog(ERROR, "renamerel: relation \"%s\" exists", newrelname);
 
+	/*
+	 * Update pg_class tuple with new relname.
+	 */
+	StrNCpy(NameStr(((Form_pg_class) GETSTRUCT(oldreltup))->relname),
+			newrelname, NAMEDATALEN);
+
+	heap_update(relrelation, &oldreltup->t_self, oldreltup, NULL);
+
+	/* keep the system catalog indices current */
+	CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, irelations);
+	CatalogIndexInsert(irelations, Num_pg_class_indices, relrelation, oldreltup);
+	CatalogCloseIndices(Num_pg_class_indices, irelations);
+
+	heap_close(relrelation, NoLock);
+
+	/*
+	 * Also rename the associated type, if any.
+	 */
+	if (relkind != RELKIND_INDEX)
+		TypeRename(oldrelname, newrelname);
+
 	/*
 	 * Perform physical rename of files.  If this fails, we haven't yet
-	 * done anything irreversible.
+	 * done anything irreversible.  NOTE that this MUST be the last step;
+	 * an error occurring afterwards would leave the relation hosed!
 	 *
 	 * XXX smgr.c ought to provide an interface for this; doing it directly
 	 * is bletcherous.
@@ -304,25 +333,4 @@ renamerel(const char *oldrelname, const char *newrelname)
 				 toldpath, tnewpath);
 		}
 	}
-
-	/*
-	 * Update pg_class tuple with new relname.
-	 */
-	StrNCpy(NameStr(((Form_pg_class) GETSTRUCT(oldreltup))->relname),
-			newrelname, NAMEDATALEN);
-
-	heap_update(relrelation, &oldreltup->t_self, oldreltup, NULL);
-
-	/* keep the system catalog indices current */
-	CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, irelations);
-	CatalogIndexInsert(irelations, Num_pg_class_indices, relrelation, oldreltup);
-	CatalogCloseIndices(Num_pg_class_indices, irelations);
-
-	heap_close(relrelation, RowExclusiveLock);
-
-	/*
-	 * Also rename the associated type, if any.
-	 */
-	if (relkind != RELKIND_INDEX)
-		TypeRename(oldrelname, newrelname);
 }
-- 
GitLab