1
/*-------------------------------------------------------------------------
4
* Commands to manipulate table spaces
6
* Tablespaces in PostgreSQL are designed to allow users to determine
7
* where the data file(s) for a given database object reside on the file
10
* A tablespace represents a directory on the file system. At tablespace
11
* creation time, the directory must be empty. To simplify things and
12
* remove the possibility of having file name conflicts, we isolate
13
* files within a tablespace into database-specific subdirectories.
15
* To support file access via the information given in RelFileNode, we
16
* maintain a symbolic-link map in $PGDATA/pg_tblspc. The symlinks are
17
* named by tablespace OIDs and point to the actual tablespace directories.
18
* There is also a per-cluster version directory in each tablespace.
19
* Thus the full path to an arbitrary file is
20
* $PGDATA/pg_tblspc/spcoid/PG_MAJORVER_CATVER/dboid/relfilenode
22
* $PGDATA/pg_tblspc/20981/PG_9.0_201002161/719849/83292814
24
* There are two tablespaces created at initdb time: pg_global (for shared
25
* tables) and pg_default (for everything else). For backwards compatibility
26
* and to remain functional on platforms without symlinks, these tablespaces
27
* are accessed specially: they are respectively
28
* $PGDATA/global/relfilenode
29
* $PGDATA/base/dboid/relfilenode
31
* To allow CREATE DATABASE to give a new database a default tablespace
32
* that's different from the template database's default, we make the
33
* provision that a zero in pg_class.reltablespace means the database's
34
* default tablespace. Without this, CREATE DATABASE would have to go in
35
* and munge the system catalogs of the new database.
38
* Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
39
* Portions Copyright (c) 1994, Regents of the University of California
43
* src/backend/commands/tablespace.c
45
*-------------------------------------------------------------------------
51
#include <sys/types.h>
54
#include "access/heapam.h"
55
#include "access/reloptions.h"
56
#include "access/sysattr.h"
57
#include "access/transam.h"
58
#include "access/xact.h"
59
#include "catalog/catalog.h"
60
#include "catalog/dependency.h"
61
#include "catalog/indexing.h"
62
#include "catalog/objectaccess.h"
63
#include "catalog/pg_tablespace.h"
64
#include "commands/comment.h"
65
#include "commands/defrem.h"
66
#include "commands/tablespace.h"
67
#include "miscadmin.h"
68
#include "postmaster/bgwriter.h"
69
#include "storage/fd.h"
70
#include "storage/procarray.h"
71
#include "storage/standby.h"
72
#include "utils/acl.h"
73
#include "utils/builtins.h"
74
#include "utils/fmgroids.h"
75
#include "utils/guc.h"
76
#include "utils/lsyscache.h"
77
#include "utils/memutils.h"
78
#include "utils/rel.h"
79
#include "utils/syscache.h"
80
#include "utils/tqual.h"
84
char *default_tablespace = NULL;
85
char *temp_tablespaces = NULL;
88
static void create_tablespace_directories(const char *location,
89
const Oid tablespaceoid);
90
static bool destroy_tablespace_directories(Oid tablespaceoid, bool redo);
94
* Each database using a table space is isolated into its own name space
95
* by a subdirectory named for the database OID. On first creation of an
96
* object in the tablespace, create the subdirectory. If the subdirectory
97
* already exists, fall through quietly.
99
* isRedo indicates that we are creating an object during WAL replay.
100
* In this case we will cope with the possibility of the tablespace
101
* directory not being there either --- this could happen if we are
102
* replaying an operation on a table in a subsequently-dropped tablespace.
103
* We handle this by making a directory in the place where the tablespace
104
* symlink would normally be. This isn't an exact replay of course, but
105
* it's the best we can do given the available information.
107
* If tablespaces are not supported, we still need it in case we have to
108
* re-create a database subdirectory (of $PGDATA/base) during WAL replay.
111
TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo)
117
* The global tablespace doesn't have per-database subdirectories, so
118
* nothing to do for it.
120
if (spcNode == GLOBALTABLESPACE_OID)
123
Assert(OidIsValid(spcNode));
124
Assert(OidIsValid(dbNode));
126
dir = GetDatabasePath(dbNode, spcNode);
128
if (stat(dir, &st) < 0)
130
/* Directory does not exist? */
134
* Acquire TablespaceCreateLock to ensure that no DROP TABLESPACE
135
* or TablespaceCreateDbspace is running concurrently.
137
LWLockAcquire(TablespaceCreateLock, LW_EXCLUSIVE);
140
* Recheck to see if someone created the directory while we were
143
if (stat(dir, &st) == 0 && S_ISDIR(st.st_mode))
145
/* Directory was created */
149
/* Directory creation failed? */
150
if (mkdir(dir, S_IRWXU) < 0)
154
/* Failure other than not exists or not in WAL replay? */
155
if (errno != ENOENT || !isRedo)
157
(errcode_for_file_access(),
158
errmsg("could not create directory \"%s\": %m",
162
* Parent directories are missing during WAL replay, so
163
* continue by creating simple parent directories rather
167
/* create two parents up if not exist */
168
parentdir = pstrdup(dir);
169
get_parent_directory(parentdir);
170
get_parent_directory(parentdir);
171
/* Can't create parent and it doesn't already exist? */
172
if (mkdir(parentdir, S_IRWXU) < 0 && errno != EEXIST)
174
(errcode_for_file_access(),
175
errmsg("could not create directory \"%s\": %m",
179
/* create one parent up if not exist */
180
parentdir = pstrdup(dir);
181
get_parent_directory(parentdir);
182
/* Can't create parent and it doesn't already exist? */
183
if (mkdir(parentdir, S_IRWXU) < 0 && errno != EEXIST)
185
(errcode_for_file_access(),
186
errmsg("could not create directory \"%s\": %m",
190
/* Create database directory */
191
if (mkdir(dir, S_IRWXU) < 0)
193
(errcode_for_file_access(),
194
errmsg("could not create directory \"%s\": %m",
199
LWLockRelease(TablespaceCreateLock);
204
(errcode_for_file_access(),
205
errmsg("could not stat directory \"%s\": %m", dir)));
210
/* Is it not a directory? */
211
if (!S_ISDIR(st.st_mode))
213
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
214
errmsg("\"%s\" exists but is not a directory",
222
* Create a table space
224
* Only superusers can create a tablespace. This seems a reasonable restriction
225
* since we're determining the system layout and, anyway, we probably have
226
* root if we're doing this kind of activity
229
CreateTableSpace(CreateTableSpaceStmt *stmt)
233
Datum values[Natts_pg_tablespace];
234
bool nulls[Natts_pg_tablespace];
240
/* Must be super user */
243
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
244
errmsg("permission denied to create tablespace \"%s\"",
245
stmt->tablespacename),
246
errhint("Must be superuser to create a tablespace.")));
248
/* However, the eventual owner of the tablespace need not be */
250
ownerId = get_role_oid(stmt->owner, false);
252
ownerId = GetUserId();
254
/* Unix-ify the offered path, and strip any trailing slashes */
255
location = pstrdup(stmt->location);
256
canonicalize_path(location);
258
/* disallow quotes, else CREATE DATABASE would be at risk */
259
if (strchr(location, '\''))
261
(errcode(ERRCODE_INVALID_NAME),
262
errmsg("tablespace location cannot contain single quotes")));
265
* Allowing relative paths seems risky
267
* this also helps us ensure that location is not empty or whitespace
269
if (!is_absolute_path(location))
271
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
272
errmsg("tablespace location must be an absolute path")));
275
* Check that location isn't too long. Remember that we're going to append
276
* 'PG_XXX/<dboid>/<relid>.<nnn>'. FYI, we never actually reference the
277
* whole path, but mkdir() uses the first two parts.
279
if (strlen(location) + 1 + strlen(TABLESPACE_VERSION_DIRECTORY) + 1 +
280
OIDCHARS + 1 + OIDCHARS + 1 + OIDCHARS > MAXPGPATH)
282
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
283
errmsg("tablespace location \"%s\" is too long",
287
* Disallow creation of tablespaces named "pg_xxx"; we reserve this
288
* namespace for system purposes.
290
if (!allowSystemTableMods && IsReservedName(stmt->tablespacename))
292
(errcode(ERRCODE_RESERVED_NAME),
293
errmsg("unacceptable tablespace name \"%s\"",
294
stmt->tablespacename),
295
errdetail("The prefix \"pg_\" is reserved for system tablespaces.")));
298
* Check that there is no other tablespace by this name. (The unique
299
* index would catch this anyway, but might as well give a friendlier
302
if (OidIsValid(get_tablespace_oid(stmt->tablespacename, true)))
304
(errcode(ERRCODE_DUPLICATE_OBJECT),
305
errmsg("tablespace \"%s\" already exists",
306
stmt->tablespacename)));
309
* Insert tuple into pg_tablespace. The purpose of doing this first is to
310
* lock the proposed tablename against other would-be creators. The
311
* insertion will roll back if we find problems below.
313
rel = heap_open(TableSpaceRelationId, RowExclusiveLock);
315
MemSet(nulls, false, sizeof(nulls));
317
values[Anum_pg_tablespace_spcname - 1] =
318
DirectFunctionCall1(namein, CStringGetDatum(stmt->tablespacename));
319
values[Anum_pg_tablespace_spcowner - 1] =
320
ObjectIdGetDatum(ownerId);
321
values[Anum_pg_tablespace_spclocation - 1] =
322
CStringGetTextDatum(location);
323
nulls[Anum_pg_tablespace_spcacl - 1] = true;
324
nulls[Anum_pg_tablespace_spcoptions - 1] = true;
326
tuple = heap_form_tuple(rel->rd_att, values, nulls);
328
tablespaceoid = simple_heap_insert(rel, tuple);
330
CatalogUpdateIndexes(rel, tuple);
332
heap_freetuple(tuple);
334
/* Record dependency on owner */
335
recordDependencyOnOwner(TableSpaceRelationId, tablespaceoid, ownerId);
337
/* Post creation hook for new tablespace */
338
InvokeObjectAccessHook(OAT_POST_CREATE,
339
TableSpaceRelationId, tablespaceoid, 0);
341
create_tablespace_directories(location, tablespaceoid);
343
/* Record the filesystem change in XLOG */
345
xl_tblspc_create_rec xlrec;
346
XLogRecData rdata[2];
348
xlrec.ts_id = tablespaceoid;
349
rdata[0].data = (char *) &xlrec;
350
rdata[0].len = offsetof(xl_tblspc_create_rec, ts_path);
351
rdata[0].buffer = InvalidBuffer;
352
rdata[0].next = &(rdata[1]);
354
rdata[1].data = (char *) location;
355
rdata[1].len = strlen(location) + 1;
356
rdata[1].buffer = InvalidBuffer;
357
rdata[1].next = NULL;
359
(void) XLogInsert(RM_TBLSPC_ID, XLOG_TBLSPC_CREATE, rdata);
363
* Force synchronous commit, to minimize the window between creating the
364
* symlink on-disk and marking the transaction committed. It's not great
365
* that there is any window at all, but definitely we don't want to make
366
* it larger than necessary.
372
/* We keep the lock on pg_tablespace until commit */
373
heap_close(rel, NoLock);
374
#else /* !HAVE_SYMLINK */
376
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
377
errmsg("tablespaces are not supported on this platform")));
378
#endif /* HAVE_SYMLINK */
384
* Be careful to check that the tablespace is empty.
387
DropTableSpace(DropTableSpaceStmt *stmt)
390
char *tablespacename = stmt->tablespacename;
391
HeapScanDesc scandesc;
394
ScanKeyData entry[1];
398
* Find the target tuple
400
rel = heap_open(TableSpaceRelationId, RowExclusiveLock);
402
ScanKeyInit(&entry[0],
403
Anum_pg_tablespace_spcname,
404
BTEqualStrategyNumber, F_NAMEEQ,
405
CStringGetDatum(tablespacename));
406
scandesc = heap_beginscan(rel, SnapshotNow, 1, entry);
407
tuple = heap_getnext(scandesc, ForwardScanDirection);
409
if (!HeapTupleIsValid(tuple))
411
if (!stmt->missing_ok)
414
(errcode(ERRCODE_UNDEFINED_OBJECT),
415
errmsg("tablespace \"%s\" does not exist",
421
(errmsg("tablespace \"%s\" does not exist, skipping",
423
/* XXX I assume I need one or both of these next two calls */
424
heap_endscan(scandesc);
425
heap_close(rel, NoLock);
430
tablespaceoid = HeapTupleGetOid(tuple);
432
/* Must be tablespace owner */
433
if (!pg_tablespace_ownercheck(tablespaceoid, GetUserId()))
434
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TABLESPACE,
437
/* Disallow drop of the standard tablespaces, even by superuser */
438
if (tablespaceoid == GLOBALTABLESPACE_OID ||
439
tablespaceoid == DEFAULTTABLESPACE_OID)
440
aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_TABLESPACE,
444
* Remove the pg_tablespace tuple (this will roll back if we fail below)
446
simple_heap_delete(rel, &tuple->t_self);
448
heap_endscan(scandesc);
451
* Remove any comments on this tablespace.
453
DeleteSharedComments(tablespaceoid, TableSpaceRelationId);
456
* Remove dependency on owner.
458
deleteSharedDependencyRecordsFor(TableSpaceRelationId, tablespaceoid, 0);
461
* Acquire TablespaceCreateLock to ensure that no TablespaceCreateDbspace
462
* is running concurrently.
464
LWLockAcquire(TablespaceCreateLock, LW_EXCLUSIVE);
467
* Try to remove the physical infrastructure.
469
if (!destroy_tablespace_directories(tablespaceoid, false))
472
* Not all files deleted? However, there can be lingering empty files
473
* in the directories, left behind by for example DROP TABLE, that
474
* have been scheduled for deletion at next checkpoint (see comments
475
* in mdunlink() for details). We could just delete them immediately,
476
* but we can't tell them apart from important data files that we
477
* mustn't delete. So instead, we force a checkpoint which will clean
478
* out any lingering files, and try again.
480
RequestCheckpoint(CHECKPOINT_IMMEDIATE | CHECKPOINT_FORCE | CHECKPOINT_WAIT);
481
if (!destroy_tablespace_directories(tablespaceoid, false))
483
/* Still not empty, the files must be important then */
485
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
486
errmsg("tablespace \"%s\" is not empty",
491
/* Record the filesystem change in XLOG */
493
xl_tblspc_drop_rec xlrec;
494
XLogRecData rdata[1];
496
xlrec.ts_id = tablespaceoid;
497
rdata[0].data = (char *) &xlrec;
498
rdata[0].len = sizeof(xl_tblspc_drop_rec);
499
rdata[0].buffer = InvalidBuffer;
500
rdata[0].next = NULL;
502
(void) XLogInsert(RM_TBLSPC_ID, XLOG_TBLSPC_DROP, rdata);
506
* Note: because we checked that the tablespace was empty, there should be
507
* no need to worry about flushing shared buffers or free space map
508
* entries for relations in the tablespace.
512
* Force synchronous commit, to minimize the window between removing the
513
* files on-disk and marking the transaction committed. It's not great
514
* that there is any window at all, but definitely we don't want to make
515
* it larger than necessary.
520
* Allow TablespaceCreateDbspace again.
522
LWLockRelease(TablespaceCreateLock);
524
/* We keep the lock on pg_tablespace until commit */
525
heap_close(rel, NoLock);
526
#else /* !HAVE_SYMLINK */
528
(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
529
errmsg("tablespaces are not supported on this platform")));
530
#endif /* HAVE_SYMLINK */
535
* create_tablespace_directories
537
* Attempt to create filesystem infrastructure linking $PGDATA/pg_tblspc/
538
* to the specified directory
541
create_tablespace_directories(const char *location, const Oid tablespaceoid)
543
char *linkloc = palloc(OIDCHARS + OIDCHARS + 1);
544
char *location_with_version_dir = palloc(strlen(location) + 1 +
545
strlen(TABLESPACE_VERSION_DIRECTORY) + 1);
547
sprintf(linkloc, "pg_tblspc/%u", tablespaceoid);
548
sprintf(location_with_version_dir, "%s/%s", location,
549
TABLESPACE_VERSION_DIRECTORY);
552
* Attempt to coerce target directory to safe permissions. If this fails,
553
* it doesn't exist or has the wrong owner.
555
if (chmod(location, S_IRWXU) != 0)
559
(errcode(ERRCODE_UNDEFINED_FILE),
560
errmsg("directory \"%s\" does not exist", location),
561
InRecovery ? errhint("Create this directory for the tablespace before "
562
"restarting the server.") : 0));
565
(errcode_for_file_access(),
566
errmsg("could not set permissions on directory \"%s\": %m",
575
* Our theory for replaying a CREATE is to forcibly drop the target
576
* subdirectory if present, and then recreate it. This may be more
577
* work than needed, but it is simple to implement.
579
if (stat(location_with_version_dir, &st) == 0 && S_ISDIR(st.st_mode))
581
if (!rmtree(location_with_version_dir, true))
582
/* If this failed, mkdir() below is going to error. */
584
(errmsg("some useless files may be left behind in old database directory \"%s\"",
585
location_with_version_dir)));
590
* The creation of the version directory prevents more than one tablespace
591
* in a single location.
593
if (mkdir(location_with_version_dir, S_IRWXU) < 0)
597
(errcode(ERRCODE_OBJECT_IN_USE),
598
errmsg("directory \"%s\" already in use as a tablespace",
599
location_with_version_dir)));
602
(errcode_for_file_access(),
603
errmsg("could not create directory \"%s\": %m",
604
location_with_version_dir)));
607
/* Remove old symlink in recovery, in case it points to the wrong place */
610
if (unlink(linkloc) < 0 && errno != ENOENT)
612
(errcode_for_file_access(),
613
errmsg("could not remove symbolic link \"%s\": %m",
618
* Create the symlink under PGDATA
620
if (symlink(location, linkloc) < 0)
622
(errcode_for_file_access(),
623
errmsg("could not create symbolic link \"%s\": %m",
627
pfree(location_with_version_dir);
632
* destroy_tablespace_directories
634
* Attempt to remove filesystem infrastructure
636
* 'redo' indicates we are redoing a drop from XLOG; okay if nothing there
638
* Returns TRUE if successful, FALSE if some subdirectory is not empty
641
destroy_tablespace_directories(Oid tablespaceoid, bool redo)
644
char *linkloc_with_version_dir;
650
linkloc_with_version_dir = palloc(9 + 1 + OIDCHARS + 1 +
651
strlen(TABLESPACE_VERSION_DIRECTORY));
652
sprintf(linkloc_with_version_dir, "pg_tblspc/%u/%s", tablespaceoid,
653
TABLESPACE_VERSION_DIRECTORY);
656
* Check if the tablespace still contains any files. We try to rmdir each
657
* per-database directory we find in it. rmdir failure implies there are
658
* still files in that subdirectory, so give up. (We do not have to worry
659
* about undoing any already completed rmdirs, since the next attempt to
660
* use the tablespace from that database will simply recreate the
661
* subdirectory via TablespaceCreateDbspace.)
663
* Since we hold TablespaceCreateLock, no one else should be creating any
664
* fresh subdirectories in parallel. It is possible that new files are
665
* being created within subdirectories, though, so the rmdir call could
666
* fail. Worst consequence is a less friendly error message.
668
* If redo is true then ENOENT is a likely outcome here, and we allow it
669
* to pass without comment. In normal operation we still allow it, but
670
* with a warning. This is because even though ProcessUtility disallows
671
* DROP TABLESPACE in a transaction block, it's possible that a previous
672
* DROP failed and rolled back after removing the tablespace directories
673
* and symlink. We want to allow a new DROP attempt to succeed at
674
* removing the catalog entries, so we should not give a hard error here.
676
dirdesc = AllocateDir(linkloc_with_version_dir);
683
(errcode_for_file_access(),
684
errmsg("could not open directory \"%s\": %m",
685
linkloc_with_version_dir)));
686
pfree(linkloc_with_version_dir);
689
/* else let ReadDir report the error */
692
while ((de = ReadDir(dirdesc, linkloc_with_version_dir)) != NULL)
694
if (strcmp(de->d_name, ".") == 0 ||
695
strcmp(de->d_name, "..") == 0)
698
subfile = palloc(strlen(linkloc_with_version_dir) + 1 + strlen(de->d_name) + 1);
699
sprintf(subfile, "%s/%s", linkloc_with_version_dir, de->d_name);
701
/* This check is just to deliver a friendlier error message */
702
if (!directory_is_empty(subfile))
706
pfree(linkloc_with_version_dir);
710
/* remove empty directory */
711
if (rmdir(subfile) < 0)
713
(errcode_for_file_access(),
714
errmsg("could not remove directory \"%s\": %m",
722
/* remove version directory */
723
if (rmdir(linkloc_with_version_dir) < 0)
725
(errcode_for_file_access(),
726
errmsg("could not remove directory \"%s\": %m",
727
linkloc_with_version_dir)));
730
* Try to remove the symlink. We must however deal with the possibility
731
* that it's a directory instead of a symlink --- this could happen during
732
* WAL replay (see TablespaceCreateDbspace), and it is also the case on
733
* Windows where junction points lstat() as directories.
735
linkloc = pstrdup(linkloc_with_version_dir);
736
get_parent_directory(linkloc);
737
if (lstat(linkloc, &st) == 0 && S_ISDIR(st.st_mode))
739
if (rmdir(linkloc) < 0)
741
(errcode_for_file_access(),
742
errmsg("could not remove directory \"%s\": %m",
747
if (unlink(linkloc) < 0)
749
(errcode_for_file_access(),
750
errmsg("could not remove symbolic link \"%s\": %m",
754
pfree(linkloc_with_version_dir);
762
* Check if a directory is empty.
764
* This probably belongs somewhere else, but not sure where...
767
directory_is_empty(const char *path)
772
dirdesc = AllocateDir(path);
774
while ((de = ReadDir(dirdesc, path)) != NULL)
776
if (strcmp(de->d_name, ".") == 0 ||
777
strcmp(de->d_name, "..") == 0)
789
* Rename a tablespace
792
RenameTableSpace(const char *oldname, const char *newname)
795
ScanKeyData entry[1];
799
Form_pg_tablespace newform;
801
/* Search pg_tablespace */
802
rel = heap_open(TableSpaceRelationId, RowExclusiveLock);
804
ScanKeyInit(&entry[0],
805
Anum_pg_tablespace_spcname,
806
BTEqualStrategyNumber, F_NAMEEQ,
807
CStringGetDatum(oldname));
808
scan = heap_beginscan(rel, SnapshotNow, 1, entry);
809
tup = heap_getnext(scan, ForwardScanDirection);
810
if (!HeapTupleIsValid(tup))
812
(errcode(ERRCODE_UNDEFINED_OBJECT),
813
errmsg("tablespace \"%s\" does not exist",
816
newtuple = heap_copytuple(tup);
817
newform = (Form_pg_tablespace) GETSTRUCT(newtuple);
822
if (!pg_tablespace_ownercheck(HeapTupleGetOid(newtuple), GetUserId()))
823
aclcheck_error(ACLCHECK_NO_PRIV, ACL_KIND_TABLESPACE, oldname);
825
/* Validate new name */
826
if (!allowSystemTableMods && IsReservedName(newname))
828
(errcode(ERRCODE_RESERVED_NAME),
829
errmsg("unacceptable tablespace name \"%s\"", newname),
830
errdetail("The prefix \"pg_\" is reserved for system tablespaces.")));
832
/* Make sure the new name doesn't exist */
833
ScanKeyInit(&entry[0],
834
Anum_pg_tablespace_spcname,
835
BTEqualStrategyNumber, F_NAMEEQ,
836
CStringGetDatum(newname));
837
scan = heap_beginscan(rel, SnapshotNow, 1, entry);
838
tup = heap_getnext(scan, ForwardScanDirection);
839
if (HeapTupleIsValid(tup))
841
(errcode(ERRCODE_DUPLICATE_OBJECT),
842
errmsg("tablespace \"%s\" already exists",
847
/* OK, update the entry */
848
namestrcpy(&(newform->spcname), newname);
850
simple_heap_update(rel, &newtuple->t_self, newtuple);
851
CatalogUpdateIndexes(rel, newtuple);
853
heap_close(rel, NoLock);
857
* Change tablespace owner
860
AlterTableSpaceOwner(const char *name, Oid newOwnerId)
863
ScanKeyData entry[1];
864
HeapScanDesc scandesc;
865
Form_pg_tablespace spcForm;
868
/* Search pg_tablespace */
869
rel = heap_open(TableSpaceRelationId, RowExclusiveLock);
871
ScanKeyInit(&entry[0],
872
Anum_pg_tablespace_spcname,
873
BTEqualStrategyNumber, F_NAMEEQ,
874
CStringGetDatum(name));
875
scandesc = heap_beginscan(rel, SnapshotNow, 1, entry);
876
tup = heap_getnext(scandesc, ForwardScanDirection);
877
if (!HeapTupleIsValid(tup))
879
(errcode(ERRCODE_UNDEFINED_OBJECT),
880
errmsg("tablespace \"%s\" does not exist", name)));
882
spcForm = (Form_pg_tablespace) GETSTRUCT(tup);
885
* If the new owner is the same as the existing owner, consider the
886
* command to have succeeded. This is for dump restoration purposes.
888
if (spcForm->spcowner != newOwnerId)
890
Datum repl_val[Natts_pg_tablespace];
891
bool repl_null[Natts_pg_tablespace];
892
bool repl_repl[Natts_pg_tablespace];
898
/* Otherwise, must be owner of the existing object */
899
if (!pg_tablespace_ownercheck(HeapTupleGetOid(tup), GetUserId()))
900
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TABLESPACE,
903
/* Must be able to become new owner */
904
check_is_member_of_role(GetUserId(), newOwnerId);
907
* Normally we would also check for create permissions here, but there
908
* are none for tablespaces so we follow what rename tablespace does
909
* and omit the create permissions check.
911
* NOTE: Only superusers may create tablespaces to begin with and so
912
* initially only a superuser would be able to change its ownership
916
memset(repl_null, false, sizeof(repl_null));
917
memset(repl_repl, false, sizeof(repl_repl));
919
repl_repl[Anum_pg_tablespace_spcowner - 1] = true;
920
repl_val[Anum_pg_tablespace_spcowner - 1] = ObjectIdGetDatum(newOwnerId);
923
* Determine the modified ACL for the new owner. This is only
924
* necessary when the ACL is non-null.
926
aclDatum = heap_getattr(tup,
927
Anum_pg_tablespace_spcacl,
928
RelationGetDescr(rel),
932
newAcl = aclnewowner(DatumGetAclP(aclDatum),
933
spcForm->spcowner, newOwnerId);
934
repl_repl[Anum_pg_tablespace_spcacl - 1] = true;
935
repl_val[Anum_pg_tablespace_spcacl - 1] = PointerGetDatum(newAcl);
938
newtuple = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, repl_null, repl_repl);
940
simple_heap_update(rel, &newtuple->t_self, newtuple);
941
CatalogUpdateIndexes(rel, newtuple);
943
heap_freetuple(newtuple);
945
/* Update owner dependency reference */
946
changeDependencyOnOwner(TableSpaceRelationId, HeapTupleGetOid(tup),
950
heap_endscan(scandesc);
951
heap_close(rel, NoLock);
956
* Alter table space options
959
AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt)
962
ScanKeyData entry[1];
963
HeapScanDesc scandesc;
967
Datum repl_val[Natts_pg_tablespace];
969
bool repl_null[Natts_pg_tablespace];
970
bool repl_repl[Natts_pg_tablespace];
973
/* Search pg_tablespace */
974
rel = heap_open(TableSpaceRelationId, RowExclusiveLock);
976
ScanKeyInit(&entry[0],
977
Anum_pg_tablespace_spcname,
978
BTEqualStrategyNumber, F_NAMEEQ,
979
CStringGetDatum(stmt->tablespacename));
980
scandesc = heap_beginscan(rel, SnapshotNow, 1, entry);
981
tup = heap_getnext(scandesc, ForwardScanDirection);
982
if (!HeapTupleIsValid(tup))
984
(errcode(ERRCODE_UNDEFINED_OBJECT),
985
errmsg("tablespace \"%s\" does not exist",
986
stmt->tablespacename)));
988
/* Must be owner of the existing object */
989
if (!pg_tablespace_ownercheck(HeapTupleGetOid(tup), GetUserId()))
990
aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TABLESPACE,
991
stmt->tablespacename);
993
/* Generate new proposed spcoptions (text array) */
994
datum = heap_getattr(tup, Anum_pg_tablespace_spcoptions,
995
RelationGetDescr(rel), &isnull);
996
newOptions = transformRelOptions(isnull ? (Datum) 0 : datum,
997
stmt->options, NULL, NULL, false,
999
(void) tablespace_reloptions(newOptions, true);
1001
/* Build new tuple. */
1002
memset(repl_null, false, sizeof(repl_null));
1003
memset(repl_repl, false, sizeof(repl_repl));
1004
if (newOptions != (Datum) 0)
1005
repl_val[Anum_pg_tablespace_spcoptions - 1] = newOptions;
1007
repl_null[Anum_pg_tablespace_spcoptions - 1] = true;
1008
repl_repl[Anum_pg_tablespace_spcoptions - 1] = true;
1009
newtuple = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val,
1010
repl_null, repl_repl);
1012
/* Update system catalog. */
1013
simple_heap_update(rel, &newtuple->t_self, newtuple);
1014
CatalogUpdateIndexes(rel, newtuple);
1015
heap_freetuple(newtuple);
1017
/* Conclude heap scan. */
1018
heap_endscan(scandesc);
1019
heap_close(rel, NoLock);
1023
* Routines for handling the GUC variable 'default_tablespace'.
1026
/* check_hook: validate new default_tablespace */
1028
check_default_tablespace(char **newval, void **extra, GucSource source)
1031
* If we aren't inside a transaction, we cannot do database access so
1032
* cannot verify the name. Must accept the value on faith.
1034
if (IsTransactionState())
1036
if (**newval != '\0' &&
1037
!OidIsValid(get_tablespace_oid(*newval, true)))
1039
GUC_check_errdetail("Tablespace \"%s\" does not exist.",
1049
* GetDefaultTablespace -- get the OID of the current default tablespace
1051
* Temporary objects have different default tablespaces, hence the
1052
* relpersistence parameter must be specified.
1054
* May return InvalidOid to indicate "use the database's default tablespace".
1056
* Note that caller is expected to check appropriate permissions for any
1057
* result other than InvalidOid.
1059
* This exists to hide (and possibly optimize the use of) the
1060
* default_tablespace GUC variable.
1063
GetDefaultTablespace(char relpersistence)
1067
/* The temp-table case is handled elsewhere */
1068
if (relpersistence == RELPERSISTENCE_TEMP)
1070
PrepareTempTablespaces();
1071
return GetNextTempTableSpace();
1074
/* Fast path for default_tablespace == "" */
1075
if (default_tablespace == NULL || default_tablespace[0] == '\0')
1079
* It is tempting to cache this lookup for more speed, but then we would
1080
* fail to detect the case where the tablespace was dropped since the GUC
1081
* variable was set. Note also that we don't complain if the value fails
1082
* to refer to an existing tablespace; we just silently return InvalidOid,
1083
* causing the new object to be created in the database's tablespace.
1085
result = get_tablespace_oid(default_tablespace, true);
1088
* Allow explicit specification of database's default tablespace in
1089
* default_tablespace without triggering permissions checks.
1091
if (result == MyDatabaseTableSpace)
1092
result = InvalidOid;
1098
* Routines for handling the GUC variable 'temp_tablespaces'.
1104
Oid tblSpcs[1]; /* VARIABLE LENGTH ARRAY */
1105
} temp_tablespaces_extra;
1107
/* check_hook: validate new temp_tablespaces */
1109
check_temp_tablespaces(char **newval, void **extra, GucSource source)
1114
/* Need a modifiable copy of string */
1115
rawname = pstrdup(*newval);
1117
/* Parse string into list of identifiers */
1118
if (!SplitIdentifierString(rawname, ',', &namelist))
1120
/* syntax error in name list */
1121
GUC_check_errdetail("List syntax is invalid.");
1123
list_free(namelist);
1128
* If we aren't inside a transaction, we cannot do database access so
1129
* cannot verify the individual names. Must accept the list on faith.
1130
* Fortunately, there's then also no need to pass the data to fd.c.
1132
if (IsTransactionState())
1134
temp_tablespaces_extra *myextra;
1139
/* temporary workspace until we are done verifying the list */
1140
tblSpcs = (Oid *) palloc(list_length(namelist) * sizeof(Oid));
1142
foreach(l, namelist)
1144
char *curname = (char *) lfirst(l);
1146
AclResult aclresult;
1148
/* Allow an empty string (signifying database default) */
1149
if (curname[0] == '\0')
1151
tblSpcs[numSpcs++] = InvalidOid;
1156
* In an interactive SET command, we ereport for bad info.
1157
* Otherwise, silently ignore any bad list elements.
1159
curoid = get_tablespace_oid(curname, source < PGC_S_INTERACTIVE);
1160
if (curoid == InvalidOid)
1164
* Allow explicit specification of database's default tablespace
1165
* in temp_tablespaces without triggering permissions checks.
1167
if (curoid == MyDatabaseTableSpace)
1169
tblSpcs[numSpcs++] = InvalidOid;
1173
/* Check permissions, similarly complaining only if interactive */
1174
aclresult = pg_tablespace_aclcheck(curoid, GetUserId(),
1176
if (aclresult != ACLCHECK_OK)
1178
if (source >= PGC_S_INTERACTIVE)
1179
aclcheck_error(aclresult, ACL_KIND_TABLESPACE, curname);
1183
tblSpcs[numSpcs++] = curoid;
1186
/* Now prepare an "extra" struct for assign_temp_tablespaces */
1187
myextra = malloc(offsetof(temp_tablespaces_extra, tblSpcs) +
1188
numSpcs * sizeof(Oid));
1191
myextra->numSpcs = numSpcs;
1192
memcpy(myextra->tblSpcs, tblSpcs, numSpcs * sizeof(Oid));
1193
*extra = (void *) myextra;
1199
list_free(namelist);
1204
/* assign_hook: do extra actions as needed */
1206
assign_temp_tablespaces(const char *newval, void *extra)
1208
temp_tablespaces_extra *myextra = (temp_tablespaces_extra *) extra;
1211
* If check_temp_tablespaces was executed inside a transaction, then pass
1212
* the list it made to fd.c. Otherwise, clear fd.c's list; we must be
1213
* still outside a transaction, or else restoring during transaction exit,
1214
* and in either case we can just let the next PrepareTempTablespaces call
1218
SetTempTablespaces(myextra->tblSpcs, myextra->numSpcs);
1220
SetTempTablespaces(NULL, 0);
1224
* PrepareTempTablespaces -- prepare to use temp tablespaces
1226
* If we have not already done so in the current transaction, parse the
1227
* temp_tablespaces GUC variable and tell fd.c which tablespace(s) to use
1231
PrepareTempTablespaces(void)
1239
/* No work if already done in current transaction */
1240
if (TempTablespacesAreSet())
1244
* Can't do catalog access unless within a transaction. This is just a
1245
* safety check in case this function is called by low-level code that
1246
* could conceivably execute outside a transaction. Note that in such a
1247
* scenario, fd.c will fall back to using the current database's default
1248
* tablespace, which should always be OK.
1250
if (!IsTransactionState())
1253
/* Need a modifiable copy of string */
1254
rawname = pstrdup(temp_tablespaces);
1256
/* Parse string into list of identifiers */
1257
if (!SplitIdentifierString(rawname, ',', &namelist))
1259
/* syntax error in name list */
1260
SetTempTablespaces(NULL, 0);
1262
list_free(namelist);
1266
/* Store tablespace OIDs in an array in TopTransactionContext */
1267
tblSpcs = (Oid *) MemoryContextAlloc(TopTransactionContext,
1268
list_length(namelist) * sizeof(Oid));
1270
foreach(l, namelist)
1272
char *curname = (char *) lfirst(l);
1274
AclResult aclresult;
1276
/* Allow an empty string (signifying database default) */
1277
if (curname[0] == '\0')
1279
tblSpcs[numSpcs++] = InvalidOid;
1283
/* Else verify that name is a valid tablespace name */
1284
curoid = get_tablespace_oid(curname, true);
1285
if (curoid == InvalidOid)
1287
/* Skip any bad list elements */
1292
* Allow explicit specification of database's default tablespace in
1293
* temp_tablespaces without triggering permissions checks.
1295
if (curoid == MyDatabaseTableSpace)
1297
tblSpcs[numSpcs++] = InvalidOid;
1301
/* Check permissions similarly */
1302
aclresult = pg_tablespace_aclcheck(curoid, GetUserId(),
1304
if (aclresult != ACLCHECK_OK)
1307
tblSpcs[numSpcs++] = curoid;
1310
SetTempTablespaces(tblSpcs, numSpcs);
1313
list_free(namelist);
1318
* get_tablespace_oid - given a tablespace name, look up the OID
1320
* If missing_ok is false, throw an error if tablespace name not found. If
1321
* true, just return InvalidOid.
1324
get_tablespace_oid(const char *tablespacename, bool missing_ok)
1328
HeapScanDesc scandesc;
1330
ScanKeyData entry[1];
1333
* Search pg_tablespace. We use a heapscan here even though there is an
1334
* index on name, on the theory that pg_tablespace will usually have just
1335
* a few entries and so an indexed lookup is a waste of effort.
1337
rel = heap_open(TableSpaceRelationId, AccessShareLock);
1339
ScanKeyInit(&entry[0],
1340
Anum_pg_tablespace_spcname,
1341
BTEqualStrategyNumber, F_NAMEEQ,
1342
CStringGetDatum(tablespacename));
1343
scandesc = heap_beginscan(rel, SnapshotNow, 1, entry);
1344
tuple = heap_getnext(scandesc, ForwardScanDirection);
1346
/* We assume that there can be at most one matching tuple */
1347
if (HeapTupleIsValid(tuple))
1348
result = HeapTupleGetOid(tuple);
1350
result = InvalidOid;
1352
heap_endscan(scandesc);
1353
heap_close(rel, AccessShareLock);
1355
if (!OidIsValid(result) && !missing_ok)
1357
(errcode(ERRCODE_UNDEFINED_OBJECT),
1358
errmsg("tablespace \"%s\" does not exist",
1365
* get_tablespace_name - given a tablespace OID, look up the name
1367
* Returns a palloc'd string, or NULL if no such tablespace.
1370
get_tablespace_name(Oid spc_oid)
1374
HeapScanDesc scandesc;
1376
ScanKeyData entry[1];
1379
* Search pg_tablespace. We use a heapscan here even though there is an
1380
* index on oid, on the theory that pg_tablespace will usually have just a
1381
* few entries and so an indexed lookup is a waste of effort.
1383
rel = heap_open(TableSpaceRelationId, AccessShareLock);
1385
ScanKeyInit(&entry[0],
1386
ObjectIdAttributeNumber,
1387
BTEqualStrategyNumber, F_OIDEQ,
1388
ObjectIdGetDatum(spc_oid));
1389
scandesc = heap_beginscan(rel, SnapshotNow, 1, entry);
1390
tuple = heap_getnext(scandesc, ForwardScanDirection);
1392
/* We assume that there can be at most one matching tuple */
1393
if (HeapTupleIsValid(tuple))
1394
result = pstrdup(NameStr(((Form_pg_tablespace) GETSTRUCT(tuple))->spcname));
1398
heap_endscan(scandesc);
1399
heap_close(rel, AccessShareLock);
1406
* TABLESPACE resource manager's routines
1409
tblspc_redo(XLogRecPtr lsn, XLogRecord *record)
1411
uint8 info = record->xl_info & ~XLR_INFO_MASK;
1413
/* Backup blocks are not used in tblspc records */
1414
Assert(!(record->xl_info & XLR_BKP_BLOCK_MASK));
1416
if (info == XLOG_TBLSPC_CREATE)
1418
xl_tblspc_create_rec *xlrec = (xl_tblspc_create_rec *) XLogRecGetData(record);
1419
char *location = xlrec->ts_path;
1421
create_tablespace_directories(location, xlrec->ts_id);
1423
else if (info == XLOG_TBLSPC_DROP)
1425
xl_tblspc_drop_rec *xlrec = (xl_tblspc_drop_rec *) XLogRecGetData(record);
1428
* If we issued a WAL record for a drop tablespace it is because there
1429
* were no files in it at all. That means that no permanent objects
1430
* can exist in it at this point.
1432
* It is possible for standby users to be using this tablespace as a
1433
* location for their temporary files, so if we fail to remove all
1434
* files then do conflict processing and try again, if currently
1437
if (!destroy_tablespace_directories(xlrec->ts_id, true))
1439
ResolveRecoveryConflictWithTablespace(xlrec->ts_id);
1442
* If we did recovery processing then hopefully the backends who
1443
* wrote temp files should have cleaned up and exited by now. So
1444
* lets recheck before we throw an error. If !process_conflicts
1445
* then this will just fail again.
1447
if (!destroy_tablespace_directories(xlrec->ts_id, true))
1449
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1450
errmsg("tablespace %u is not empty",
1455
elog(PANIC, "tblspc_redo: unknown op code %u", info);
1459
tblspc_desc(StringInfo buf, uint8 xl_info, char *rec)
1461
uint8 info = xl_info & ~XLR_INFO_MASK;
1463
if (info == XLOG_TBLSPC_CREATE)
1465
xl_tblspc_create_rec *xlrec = (xl_tblspc_create_rec *) rec;
1467
appendStringInfo(buf, "create ts: %u \"%s\"",
1468
xlrec->ts_id, xlrec->ts_path);
1470
else if (info == XLOG_TBLSPC_DROP)
1472
xl_tblspc_drop_rec *xlrec = (xl_tblspc_drop_rec *) rec;
1474
appendStringInfo(buf, "drop ts: %u", xlrec->ts_id);
1477
appendStringInfo(buf, "UNKNOWN");