diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2004-10-17 20:47:21 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2004-10-17 20:47:21 +0000 |
commit | 830c168e5ce40112433fcc4784415a1abacb3e57 (patch) | |
tree | 2d7fdada045a8b7f35d0b8981f9efa775852079f /src/backend/commands/dbcommands.c | |
parent | fae7ce83fefdb5de44ca7f364e3258aea8699edc (diff) | |
download | postgresql-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.c | 44 |
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 |