99 *
1010 *
1111 * IDENTIFICATION
12- * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.144 2004/08/30 03:50:24 tgl Exp $
12+ * $PostgreSQL: pgsql/src/backend/commands/dbcommands.c,v 1.145 2004/10/17 20:47:20 tgl Exp $
1313 *
1414 *-------------------------------------------------------------------------
1515 */
@@ -281,6 +281,37 @@ createdb(const CreatedbStmt *stmt)
281281 if (aclresult != ACLCHECK_OK )
282282 aclcheck_error (aclresult , ACL_KIND_TABLESPACE ,
283283 tablespacename );
284+
285+ /*
286+ * If we are trying to change the default tablespace of the template,
287+ * we require that the template not have any files in the new default
288+ * tablespace. This is necessary because otherwise the copied
289+ * database would contain pg_class rows that refer to its default
290+ * tablespace both explicitly (by OID) and implicitly (as zero), which
291+ * would cause problems. For example another CREATE DATABASE using
292+ * the copied database as template, and trying to change its default
293+ * tablespace again, would yield outright incorrect results (it would
294+ * improperly move tables to the new default tablespace that should
295+ * stay in the same tablespace).
296+ */
297+ if (dst_deftablespace != src_deftablespace )
298+ {
299+ char * srcpath ;
300+ struct stat st ;
301+
302+ srcpath = GetDatabasePath (src_dboid , dst_deftablespace );
303+
304+ if (stat (srcpath , & st ) == 0 &&
305+ S_ISDIR (st .st_mode ) &&
306+ !directory_is_empty (srcpath ))
307+ ereport (ERROR ,
308+ (errcode (ERRCODE_FEATURE_NOT_SUPPORTED ),
309+ errmsg ("cannot assign new default tablespace \"%s\"" ,
310+ tablespacename ),
311+ errdetail ("There is a conflict because database \"%s\" already has some tables in this tablespace." ,
312+ dbtemplate )));
313+ pfree (srcpath );
314+ }
284315 }
285316 else
286317 {
@@ -311,11 +342,6 @@ createdb(const CreatedbStmt *stmt)
311342 /*
312343 * Iterate through all tablespaces of the template database, and copy
313344 * each one to the new database.
314- *
315- * If we are trying to change the default tablespace of the template, we
316- * require that the template not have any files in the new default
317- * tablespace. This avoids the need to merge two subdirectories. This
318- * could probably be improved later.
319345 */
320346 rel = heap_openr (TableSpaceRelationName , AccessShareLock );
321347 scan = heap_beginscan (rel , SnapshotNow , 0 , NULL );
@@ -333,7 +359,8 @@ createdb(const CreatedbStmt *stmt)
333359
334360 srcpath = GetDatabasePath (src_dboid , srctablespace );
335361
336- if (stat (srcpath , & st ) < 0 || !S_ISDIR (st .st_mode ))
362+ if (stat (srcpath , & st ) < 0 || !S_ISDIR (st .st_mode ) ||
363+ directory_is_empty (srcpath ))
337364 {
338365 /* Assume we can ignore it */
339366 pfree (srcpath );
@@ -352,7 +379,8 @@ createdb(const CreatedbStmt *stmt)
352379 remove_dbtablespaces (dboid );
353380 ereport (ERROR ,
354381 (errmsg ("could not initialize database directory" ),
355- errdetail ("Directory \"%s\" already exists." , dstpath )));
382+ errdetail ("Directory \"%s\" already exists." ,
383+ dstpath )));
356384 }
357385
358386#ifndef WIN32
0 commit comments