aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeikki Linnakangas <heikki.linnakangas@iki.fi>2008-10-07 11:15:41 +0000
committerHeikki Linnakangas <heikki.linnakangas@iki.fi>2008-10-07 11:15:41 +0000
commitfa3938fcb1c8e1e8d5da0e62dbf094f5f1c641c4 (patch)
treebda2e1b642b98c0b27b4f1fb8b0675172bd3c760
parent078aaf796eda274cd6cd241331278d4f089a6d7e (diff)
downloadpostgresql-fa3938fcb1c8e1e8d5da0e62dbf094f5f1c641c4.tar.gz
postgresql-fa3938fcb1c8e1e8d5da0e62dbf094f5f1c641c4.zip
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.
-rw-r--r--src/backend/commands/tablecmds.c13
1 files changed, 12 insertions, 1 deletions
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 62aeb2f3e6a..3c7bc2a56b9 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.266 2008/09/08 00:47:40 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.267 2008/10/07 11:15:41 heikki Exp $
*
*-------------------------------------------------------------------------
*/
@@ -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);