Skip to content

Commit 610abfd

Browse files
committed
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.
1 parent 445f1ac commit 610abfd

File tree

1 file changed

+36
-28
lines changed

1 file changed

+36
-28
lines changed

src/backend/commands/rename.c

Lines changed: 36 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.44 2000/05/19 03:22:29 tgl Exp $
11+
* $Header: /cvsroot/pgsql/src/backend/commands/Attic/rename.c,v 1.45 2000/05/25 21:30:20 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -19,7 +19,6 @@
1919
#include "access/heapam.h"
2020
#include "catalog/catname.h"
2121
#include "catalog/pg_type.h"
22-
#include "utils/syscache.h"
2322
#include "catalog/heap.h"
2423
#include "catalog/indexing.h"
2524
#include "catalog/catalog.h"
@@ -29,6 +28,7 @@
2928
#include "optimizer/prep.h"
3029
#include "utils/acl.h"
3130
#include "utils/relcache.h"
31+
#include "utils/syscache.h"
3232

3333

3434
/*
@@ -183,6 +183,7 @@ renamerel(const char *oldrelname, const char *newrelname)
183183
Relation targetrelation;
184184
Relation relrelation; /* for RELATION relation */
185185
HeapTuple oldreltup;
186+
Oid reloid;
186187
char relkind;
187188
char oldpath[MAXPGPATH],
188189
newpath[MAXPGPATH],
@@ -228,6 +229,7 @@ renamerel(const char *oldrelname, const char *newrelname)
228229
if (IsTransactionBlock() && !targetrelation->rd_myxactonly)
229230
elog(NOTICE, "Caution: RENAME TABLE cannot be rolled back, so don't abort now");
230231

232+
reloid = RelationGetRelid(targetrelation);
231233
relkind = targetrelation->rd_rel->relkind;
232234

233235
/*
@@ -254,13 +256,18 @@ renamerel(const char *oldrelname, const char *newrelname)
254256

255257
/*
256258
* Close rel, but keep exclusive lock!
257-
*
258-
* Note: we don't do anything about updating the relcache entry; we
259-
* assume it will be flushed by shared cache invalidate. XXX is this
260-
* good enough? What if relation is myxactonly?
261259
*/
262260
heap_close(targetrelation, NoLock);
263261

262+
/*
263+
* Flush the relcache entry (easier than trying to change it at exactly
264+
* the right instant). It'll get rebuilt on next access to relation.
265+
*
266+
* XXX What if relation is myxactonly?
267+
*/
268+
targetrelation = NULL; /* make sure I don't touch it again */
269+
RelationIdInvalidateRelationCacheByRelationId(reloid);
270+
264271
/*
265272
* Find relation's pg_class tuple, and make sure newrelname isn't in
266273
* use.
@@ -276,9 +283,31 @@ renamerel(const char *oldrelname, const char *newrelname)
276283
if (RelnameFindRelid(newrelname) != InvalidOid)
277284
elog(ERROR, "renamerel: relation \"%s\" exists", newrelname);
278285

286+
/*
287+
* Update pg_class tuple with new relname.
288+
*/
289+
StrNCpy(NameStr(((Form_pg_class) GETSTRUCT(oldreltup))->relname),
290+
newrelname, NAMEDATALEN);
291+
292+
heap_update(relrelation, &oldreltup->t_self, oldreltup, NULL);
293+
294+
/* keep the system catalog indices current */
295+
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, irelations);
296+
CatalogIndexInsert(irelations, Num_pg_class_indices, relrelation, oldreltup);
297+
CatalogCloseIndices(Num_pg_class_indices, irelations);
298+
299+
heap_close(relrelation, NoLock);
300+
301+
/*
302+
* Also rename the associated type, if any.
303+
*/
304+
if (relkind != RELKIND_INDEX)
305+
TypeRename(oldrelname, newrelname);
306+
279307
/*
280308
* Perform physical rename of files. If this fails, we haven't yet
281-
* done anything irreversible.
309+
* done anything irreversible. NOTE that this MUST be the last step;
310+
* an error occurring afterwards would leave the relation hosed!
282311
*
283312
* XXX smgr.c ought to provide an interface for this; doing it directly
284313
* is bletcherous.
@@ -304,25 +333,4 @@ renamerel(const char *oldrelname, const char *newrelname)
304333
toldpath, tnewpath);
305334
}
306335
}
307-
308-
/*
309-
* Update pg_class tuple with new relname.
310-
*/
311-
StrNCpy(NameStr(((Form_pg_class) GETSTRUCT(oldreltup))->relname),
312-
newrelname, NAMEDATALEN);
313-
314-
heap_update(relrelation, &oldreltup->t_self, oldreltup, NULL);
315-
316-
/* keep the system catalog indices current */
317-
CatalogOpenIndices(Num_pg_class_indices, Name_pg_class_indices, irelations);
318-
CatalogIndexInsert(irelations, Num_pg_class_indices, relrelation, oldreltup);
319-
CatalogCloseIndices(Num_pg_class_indices, irelations);
320-
321-
heap_close(relrelation, RowExclusiveLock);
322-
323-
/*
324-
* Also rename the associated type, if any.
325-
*/
326-
if (relkind != RELKIND_INDEX)
327-
TypeRename(oldrelname, newrelname);
328336
}

0 commit comments

Comments
 (0)