From 75a7c04518bb5c2de945bfcbb2113b7c0aa05d17 Mon Sep 17 00:00:00 2001 From: heikki Date: Tue, 7 Oct 2008 11:15:41 +0000 Subject: [PATCH] When a relation is moved to another tablespace, we can't assume that we can use the old relfilenode in the new tablespace. There might be another relation in the new tablespace with the same relfilenode, so we must generate a fresh relfilenode in the new tablespace. The 8.3 patch to let deleted relation files linger as zero-length files until the next checkpoint made this more obvious: moving a relation from one table space another, and then back again, caused a collision with the lingering file. Back-patch to 8.1. The issue is present in 8.0 as well, but it doesn't seem worth fixing there, because we didn't have protection from OID collisions after OID wraparound before 8.1. Report by Guillaume Lelarge. --- src/backend/commands/tablecmds.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c index 890aa297fe..b039227c3c 100644 --- a/src/backend/commands/tablecmds.c +++ b/src/backend/commands/tablecmds.c @@ -6488,6 +6488,7 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace) Oid oldTableSpace; Oid reltoastrelid; Oid reltoastidxid; + Oid newrelfilenode; RelFileNode newrnode; SMgrRelation dstrel; Relation pg_class; @@ -6557,8 +6558,17 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace) */ FlushRelationBuffers(rel); + /* + * Relfilenodes are not unique across tablespaces, so we need to allocate + * a new one in the new tablespace. + */ + newrelfilenode = GetNewRelFileNode(newTableSpace, + rel->rd_rel->relisshared, + NULL); + /* Open old and new relation */ newrnode = rel->rd_node; + newrnode.relNode = newrelfilenode; newrnode.spcNode = newTableSpace; dstrel = smgropen(newrnode); @@ -6588,6 +6598,7 @@ ATExecSetTableSpace(Oid tableOid, Oid newTableSpace) /* update the pg_class row */ rd_rel->reltablespace = (newTableSpace == MyDatabaseTableSpace) ? InvalidOid : newTableSpace; + rd_rel->relfilenode = newrelfilenode; simple_heap_update(pg_class, &tuple->t_self, tuple); CatalogUpdateIndexes(pg_class, tuple); -- 2.11.4.GIT