aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/dbcommands.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2004-10-17 20:47:21 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2004-10-17 20:47:21 +0000
commit830c168e5ce40112433fcc4784415a1abacb3e57 (patch)
tree2d7fdada045a8b7f35d0b8981f9efa775852079f /src/backend/commands/dbcommands.c
parentfae7ce83fefdb5de44ca7f364e3258aea8699edc (diff)
downloadpostgresql-830c168e5ce40112433fcc4784415a1abacb3e57.tar.gz
postgresql-830c168e5ce40112433fcc4784415a1abacb3e57.zip
Give a more user-friendly error message in situation where CREATE DATABASE
specifies a new default tablespace and the template database already has some tables in that tablespace. There isn't any way to solve this fully without modifying the clone database's pg_class contents, so for now the best we can do is issue a better error message.
Diffstat (limited to 'src/backend/commands/dbcommands.c')
-rw-r--r--src/backend/commands/dbcommands.c44
1 files changed, 36 insertions, 8 deletions
diff --git a/src/backend/commands/dbcommands.c b/src/backend/commands/dbcommands.c
index 1c9425789aa..917429c2b52 100644
--- a/src/backend/commands/dbcommands.c
+++ b/src/backend/commands/dbcommands.c
@@ -9,7 +9,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.144 2004/08/30 03:50:24 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.145 2004/10/17 20:47:20 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -281,6 +281,37 @@ createdb(const CreatedbStmt *stmt)
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_TABLESPACE,
tablespacename);
+
+ /*
+ * If we are trying to change the default tablespace of the template,
+ * we require that the template not have any files in the new default
+ * tablespace. This is necessary because otherwise the copied
+ * database would contain pg_class rows that refer to its default
+ * tablespace both explicitly (by OID) and implicitly (as zero), which
+ * would cause problems. For example another CREATE DATABASE using
+ * the copied database as template, and trying to change its default
+ * tablespace again, would yield outright incorrect results (it would
+ * improperly move tables to the new default tablespace that should
+ * stay in the same tablespace).
+ */
+ if (dst_deftablespace != src_deftablespace)
+ {
+ char *srcpath;
+ struct stat st;
+
+ srcpath = GetDatabasePath(src_dboid, dst_deftablespace);
+
+ if (stat(srcpath, &st) == 0 &&
+ S_ISDIR(st.st_mode) &&
+ !directory_is_empty(srcpath))
+ ereport(ERROR,
+ (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ errmsg("cannot assign new default tablespace \"%s\"",
+ tablespacename),
+ errdetail("There is a conflict because database \"%s\" already has some tables in this tablespace.",
+ dbtemplate)));
+ pfree(srcpath);
+ }
}
else
{
@@ -311,11 +342,6 @@ createdb(const CreatedbStmt *stmt)
/*
* Iterate through all tablespaces of the template database, and copy
* each one to the new database.
- *
- * If we are trying to change the default tablespace of the template, we
- * require that the template not have any files in the new default
- * tablespace. This avoids the need to merge two subdirectories. This
- * could probably be improved later.
*/
rel = heap_openr(TableSpaceRelationName, AccessShareLock);
scan = heap_beginscan(rel, SnapshotNow, 0, NULL);
@@ -333,7 +359,8 @@ createdb(const CreatedbStmt *stmt)
srcpath = GetDatabasePath(src_dboid, srctablespace);
- if (stat(srcpath, &st) < 0 || !S_ISDIR(st.st_mode))
+ if (stat(srcpath, &st) < 0 || !S_ISDIR(st.st_mode) ||
+ directory_is_empty(srcpath))
{
/* Assume we can ignore it */
pfree(srcpath);
@@ -352,7 +379,8 @@ createdb(const CreatedbStmt *stmt)
remove_dbtablespaces(dboid);
ereport(ERROR,
(errmsg("could not initialize database directory"),
- errdetail("Directory \"%s\" already exists.", dstpath)));
+ errdetail("Directory \"%s\" already exists.",
+ dstpath)));
}
#ifndef WIN32