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:
parent
fae7ce83fe
commit
830c168e5c
@ -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
|
||||
|
@ -45,7 +45,7 @@
|
||||
*
|
||||
*
|
||||
* IDENTIFICATION
|
||||
* $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.11 2004/08/30 02:54:38 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.12 2004/10/17 20:47:20 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -75,7 +75,6 @@
|
||||
|
||||
static bool remove_tablespace_directories(Oid tablespaceoid, bool redo);
|
||||
static void set_short_version(const char *path);
|
||||
static bool directory_is_empty(const char *path);
|
||||
|
||||
|
||||
/*
|
||||
@ -680,8 +679,10 @@ set_short_version(const char *path)
|
||||
|
||||
/*
|
||||
* Check if a directory is empty.
|
||||
*
|
||||
* This probably belongs somewhere else, but not sure where...
|
||||
*/
|
||||
static bool
|
||||
bool
|
||||
directory_is_empty(const char *path)
|
||||
{
|
||||
DIR *dirdesc;
|
||||
|
@ -7,7 +7,7 @@
|
||||
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
|
||||
* Portions Copyright (c) 1994, Regents of the University of California
|
||||
*
|
||||
* $PostgreSQL: pgsql/src/include/commands/tablespace.h,v 1.5 2004/08/30 02:54:40 momjian Exp $
|
||||
* $PostgreSQL: pgsql/src/include/commands/tablespace.h,v 1.6 2004/10/17 20:47:21 tgl Exp $
|
||||
*
|
||||
*-------------------------------------------------------------------------
|
||||
*/
|
||||
@ -42,6 +42,8 @@ extern void TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo);
|
||||
extern Oid get_tablespace_oid(const char *tablespacename);
|
||||
extern char *get_tablespace_name(Oid spc_oid);
|
||||
|
||||
extern bool directory_is_empty(const char *path);
|
||||
|
||||
extern void tblspc_redo(XLogRecPtr lsn, XLogRecord *rptr);
|
||||
extern void tblspc_undo(XLogRecPtr lsn, XLogRecord *rptr);
|
||||
extern void tblspc_desc(char *buf, uint8 xl_info, char *rec);
|
||||
|
Loading…
x
Reference in New Issue
Block a user