Skip to content

Commit 830c168

Browse files
committed
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.
1 parent fae7ce8 commit 830c168

File tree

3 files changed

+43
-12
lines changed

3 files changed

+43
-12
lines changed

src/backend/commands/dbcommands.c

Lines changed: 36 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
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

src/backend/commands/tablespace.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@
4545
*
4646
*
4747
* IDENTIFICATION
48-
* $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.11 2004/08/30 02:54:38 momjian Exp $
48+
* $PostgreSQL: pgsql/src/backend/commands/tablespace.c,v 1.12 2004/10/17 20:47:20 tgl Exp $
4949
*
5050
*-------------------------------------------------------------------------
5151
*/
@@ -75,7 +75,6 @@
7575

7676
static bool remove_tablespace_directories(Oid tablespaceoid, bool redo);
7777
static void set_short_version(const char *path);
78-
static bool directory_is_empty(const char *path);
7978

8079

8180
/*
@@ -680,8 +679,10 @@ set_short_version(const char *path)
680679

681680
/*
682681
* Check if a directory is empty.
682+
*
683+
* This probably belongs somewhere else, but not sure where...
683684
*/
684-
static bool
685+
bool
685686
directory_is_empty(const char *path)
686687
{
687688
DIR *dirdesc;

src/include/commands/tablespace.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
* Portions Copyright (c) 1996-2004, PostgreSQL Global Development Group
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
10-
* $PostgreSQL: pgsql/src/include/commands/tablespace.h,v 1.5 2004/08/30 02:54:40 momjian Exp $
10+
* $PostgreSQL: pgsql/src/include/commands/tablespace.h,v 1.6 2004/10/17 20:47:21 tgl Exp $
1111
*
1212
*-------------------------------------------------------------------------
1313
*/
@@ -42,6 +42,8 @@ extern void TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo);
4242
extern Oid get_tablespace_oid(const char *tablespacename);
4343
extern char *get_tablespace_name(Oid spc_oid);
4444

45+
extern bool directory_is_empty(const char *path);
46+
4547
extern void tblspc_redo(XLogRecPtr lsn, XLogRecord *rptr);
4648
extern void tblspc_undo(XLogRecPtr lsn, XLogRecord *rptr);
4749
extern void tblspc_desc(char *buf, uint8 xl_info, char *rec);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy