1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-16 06:01:02 +03:00

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.
This commit is contained in:
Tom Lane
2004-10-17 20:47:21 +00:00
parent fae7ce83fe
commit 830c168e5c
3 changed files with 43 additions and 12 deletions

View File

@ -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