aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/commands/dbcommands.c44
-rw-r--r--src/backend/commands/tablespace.c7
-rw-r--r--src/include/commands/tablespace.h4
3 files changed, 43 insertions, 12 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
diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c
index b9fbd2b5eab..1cbeef657ae 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -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;
diff --git a/src/include/commands/tablespace.h b/src/include/commands/tablespace.h
index 7e99c7e6b78..58ad23ae161 100644
--- a/src/include/commands/tablespace.h
+++ b/src/include/commands/tablespace.h
@@ -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);