51 #include <sys/types.h>
79 #include "utils/fmgroids.h"
93 const Oid tablespaceoid);
132 if (stat(dir, &st) < 0)
147 if (stat(dir, &st) == 0 && S_ISDIR(st.st_mode))
154 if (
mkdir(dir, S_IRWXU) < 0)
159 if (errno != ENOENT || !isRedo)
162 errmsg(
"could not create directory \"%s\": %m",
176 if (
mkdir(parentdir, S_IRWXU) < 0 && errno != EEXIST)
179 errmsg(
"could not create directory \"%s\": %m",
187 if (
mkdir(parentdir, S_IRWXU) < 0 && errno != EEXIST)
190 errmsg(
"could not create directory \"%s\": %m",
195 if (
mkdir(dir, S_IRWXU) < 0)
198 errmsg(
"could not create directory \"%s\": %m",
209 errmsg(
"could not stat directory \"%s\": %m", dir)));
215 if (!S_ISDIR(st.st_mode))
217 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
218 errmsg(
"\"%s\" exists but is not a directory",
248 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
249 errmsg(
"permission denied to create tablespace \"%s\"",
251 errhint(
"Must be superuser to create a tablespace.")));
264 if (strchr(location,
'\''))
266 (
errcode(ERRCODE_INVALID_NAME),
267 errmsg(
"tablespace location cannot contain single quotes")));
276 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
277 errmsg(
"tablespace location must be an absolute path")));
287 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
288 errmsg(
"tablespace location \"%s\" is too long",
294 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
295 errmsg(
"tablespace location should not be inside the data directory")));
303 (
errcode(ERRCODE_RESERVED_NAME),
304 errmsg(
"unacceptable tablespace name \"%s\"",
306 errdetail(
"The prefix \"pg_\" is reserved for system tablespaces.")));
316 errmsg(
"tablespace \"%s\" already exists",
326 MemSet(nulls,
false,
sizeof(nulls));
339 if (newOptions != (
Datum) 0)
364 xlrec.
ts_id = tablespaceoid;
387 return tablespaceoid;
390 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
391 errmsg(
"tablespaces are not supported on this platform")));
429 (
errcode(ERRCODE_UNDEFINED_OBJECT),
430 errmsg(
"tablespace \"%s\" does not exist",
436 (
errmsg(
"tablespace \"%s\" does not exist, skipping",
511 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
512 errmsg(
"tablespace \"%s\" is not empty",
521 xlrec.
ts_id = tablespaceoid;
552 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
553 errmsg(
"tablespaces are not supported on this platform")));
568 char *location_with_version_dir;
571 linkloc =
psprintf(
"pg_tblspc/%u", tablespaceoid);
572 location_with_version_dir =
psprintf(
"%s/%s", location,
579 if (chmod(location, S_IRWXU) != 0)
583 (
errcode(ERRCODE_UNDEFINED_FILE),
584 errmsg(
"directory \"%s\" does not exist", location),
586 "restarting the server.") : 0));
590 errmsg(
"could not set permissions on directory \"%s\": %m",
601 if (stat(location_with_version_dir, &st) == 0 && S_ISDIR(st.st_mode))
603 if (!
rmtree(location_with_version_dir,
true))
606 (
errmsg(
"some useless files may be left behind in old database directory \"%s\"",
607 location_with_version_dir)));
615 if (
mkdir(location_with_version_dir, S_IRWXU) < 0)
619 (
errcode(ERRCODE_OBJECT_IN_USE),
620 errmsg(
"directory \"%s\" already in use as a tablespace",
621 location_with_version_dir)));
625 errmsg(
"could not create directory \"%s\": %m",
626 location_with_version_dir)));
638 if (symlink(location, linkloc) < 0)
641 errmsg(
"could not create symbolic link \"%s\": %m",
645 pfree(location_with_version_dir);
666 char *linkloc_with_version_dir;
672 linkloc_with_version_dir =
psprintf(
"pg_tblspc/%u/%s", tablespaceoid,
705 errmsg(
"could not open directory \"%s\": %m",
706 linkloc_with_version_dir)));
715 errmsg(
"could not open directory \"%s\": %m",
716 linkloc_with_version_dir)));
717 pfree(linkloc_with_version_dir);
723 while ((de =
ReadDir(dirdesc, linkloc_with_version_dir)) !=
NULL)
725 if (strcmp(de->
d_name,
".") == 0 ||
726 strcmp(de->
d_name,
"..") == 0)
729 subfile =
psprintf(
"%s/%s", linkloc_with_version_dir, de->
d_name);
736 pfree(linkloc_with_version_dir);
741 if (rmdir(subfile) < 0)
744 errmsg(
"could not remove directory \"%s\": %m",
753 if (rmdir(linkloc_with_version_dir) < 0)
757 errmsg(
"could not remove directory \"%s\": %m",
758 linkloc_with_version_dir)));
759 pfree(linkloc_with_version_dir);
774 linkloc =
pstrdup(linkloc_with_version_dir);
776 if (
lstat(linkloc, &st) < 0)
778 int saved_errno = errno;
782 errmsg(
"could not stat file \"%s\": %m",
785 else if (S_ISDIR(st.st_mode))
787 if (rmdir(linkloc) < 0)
789 int saved_errno = errno;
793 errmsg(
"could not remove directory \"%s\": %m",
798 else if (S_ISLNK(st.st_mode))
802 int saved_errno = errno;
806 errmsg(
"could not remove symbolic link \"%s\": %m",
815 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
816 errmsg(
"\"%s\" is not a directory or symbolic link",
820 pfree(linkloc_with_version_dir);
842 if (strcmp(de->
d_name,
".") == 0 ||
843 strcmp(de->
d_name,
"..") == 0)
867 if (
lstat(linkloc, &st) < 0)
873 errmsg(
"could not stat file \"%s\": %m", linkloc)));
876 if (S_ISDIR(st.st_mode))
882 if (rmdir(linkloc) < 0 && errno != ENOENT)
885 errmsg(
"could not remove directory \"%s\": %m",
889 else if (S_ISLNK(st.st_mode))
891 if (
unlink(linkloc) < 0 && errno != ENOENT)
894 errmsg(
"could not remove symbolic link \"%s\": %m",
902 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
903 errmsg(
"\"%s\" is not a directory or symbolic link",
934 (
errcode(ERRCODE_UNDEFINED_OBJECT),
935 errmsg(
"tablespace \"%s\" does not exist",
951 (
errcode(ERRCODE_RESERVED_NAME),
952 errmsg(
"unacceptable tablespace name \"%s\"", newname),
953 errdetail(
"The prefix \"pg_\" is reserved for system tablespaces.")));
965 errmsg(
"tablespace \"%s\" already exists",
1015 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1016 errmsg(
"tablespace \"%s\" does not exist",
1035 memset(repl_null,
false,
sizeof(repl_null));
1036 memset(repl_repl,
false,
sizeof(repl_repl));
1037 if (newOptions != (
Datum) 0)
1043 repl_null, repl_repl);
1057 return tablespaceoid;
1074 if (**newval !=
'\0' &&
1084 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1085 errmsg(
"tablespace \"%s\" does not exist",
1156 Oid tblSpcs[FLEXIBLE_ARRAY_MEMBER];
1194 foreach(l, namelist)
1196 char *curname = (
char *)
lfirst(l);
1201 if (curname[0] ==
'\0')
1217 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1218 errmsg(
"tablespace \"%s\" does not exist",
1243 tblSpcs[numSpcs++] = curoid;
1248 numSpcs *
sizeof(
Oid));
1252 memcpy(myextra->
tblSpcs, tblSpcs, numSpcs *
sizeof(
Oid));
1253 *extra = (
void *) myextra;
1330 foreach(l, namelist)
1332 char *curname = (
char *)
lfirst(l);
1337 if (curname[0] ==
'\0')
1367 tblSpcs[numSpcs++] = curoid;
1417 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1418 errmsg(
"tablespace \"%s\" does not exist",
1479 char *location = xlrec->
ts_path;
1516 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1517 errmsg(
"directories for tablespace %u could not be removed",
1519 errhint(
"You can remove the directories manually if necessary.")));
1523 elog(
PANIC,
"tblspc_redo: unknown op code %u", info);
HeapTuple heap_copytuple(HeapTuple tuple)
#define Anum_pg_tablespace_spcacl
Oid get_tablespace_oid(const char *tablespacename, bool missing_ok)
AclResult pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode)
Datum namein(PG_FUNCTION_ARGS)
int errhint(const char *fmt,...)
MemoryContext TopTransactionContext
void heap_endscan(HeapScanDesc scan)
#define InvokeObjectPostCreateHook(classId, objectId, subId)
#define RelationGetDescr(relation)
char ts_path[FLEXIBLE_ARRAY_MEMBER]
#define ObjectIdAttributeNumber
#define GUC_check_errdetail
bool path_is_prefix_of_path(const char *path1, const char *path2)
char * pstrdup(const char *in)
char * psprintf(const char *fmt,...)
#define InvokeObjectDropHook(classId, objectId, subId)
#define GLOBALTABLESPACE_OID
bytea * tablespace_reloptions(Datum reloptions, bool validate)
void ForceSyncCommit(void)
void canonicalize_path(char *path)
int errcode(int sqlerrcode)
#define MemSet(start, val, len)
bool directory_is_empty(const char *path)
Oid get_rolespec_oid(const Node *node, bool missing_ok)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
#define DirectFunctionCall1(func, arg1)
Oid CreateTableSpace(CreateTableSpaceStmt *stmt)
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
void heap_freetuple(HeapTuple htup)
void remove_tablespace_symlink(const char *linkloc)
bool IsReservedName(const char *name)
int namestrcpy(Name name, const char *str)
#define OidIsValid(objectId)
Oid GetDefaultTablespace(char relpersistence)
void LWLockRelease(LWLock *lock)
void assign_temp_tablespaces(const char *newval, void *extra)
bool TempTablespacesAreSet(void)
void pfree(void *pointer)
#define XLogRecGetData(decoder)
#define ObjectIdGetDatum(X)
void PrepareTempTablespaces(void)
Oid GetNextTempTableSpace(void)
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
void aclcheck_error(AclResult aclerr, AclObjectKind objectkind, const char *objectname)
#define DEFAULTTABLESPACE_OID
int errdetail(const char *fmt,...)
int errcode_for_file_access(void)
#define is_absolute_path(filename)
#define CStringGetDatum(X)
void get_parent_directory(char *path)
FormData_pg_tablespace * Form_pg_tablespace
bool pg_tablespace_ownercheck(Oid spc_oid, Oid roleid)
DIR * AllocateDir(const char *dirname)
#define Anum_pg_tablespace_spcowner
HeapScanDesc heap_beginscan_catalog(Relation relation, int nkeys, ScanKey key)
void DropTableSpace(DropTableSpaceStmt *stmt)
int unlink(const char *filename)
#define ereport(elevel, rest)
#define InvokeObjectPostAlterHook(classId, objectId, subId)
void SetTempTablespaces(Oid *tableSpaces, int numSpaces)
#define XLogRecGetInfo(decoder)
char * GetDatabasePath(Oid dbNode, Oid spcNode)
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
#define heap_getattr(tup, attnum, tupleDesc, isnull)
bool rmtree(const char *path, bool rmtopdir)
void XLogRegisterData(char *data, int len)
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
static void create_tablespace_directories(const char *location, const Oid tablespaceoid)
Oid simple_heap_insert(Relation relation, HeapTuple tup)
HeapTuple heap_getnext(HeapScanDesc scan, ScanDirection direction)
Relation heap_open(Oid relationId, LOCKMODE lockmode)
Datum transformRelOptions(Datum oldOptions, List *defList, char *namspace, char *validnsps[], bool ignoreOids, bool isReset)
bool allowSystemTableMods
void ResolveRecoveryConflictWithTablespace(Oid tsid)
#define HeapTupleIsValid(tuple)
#define Assert(condition)
static bool destroy_tablespace_directories(Oid tablespaceoid, bool redo)
struct dirent * ReadDir(DIR *dir, const char *dirname)
void CatalogUpdateIndexes(Relation heapRel, HeapTuple heapTuple)
void TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo)
#define XLOG_TBLSPC_CREATE
static int list_length(const List *l)
void simple_heap_delete(Relation relation, ItemPointer tid)
void simple_heap_update(Relation relation, ItemPointer otid, HeapTuple tup)
bool check_default_tablespace(char **newval, void **extra, GucSource source)
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
bool IsTransactionState(void)
void tblspc_redo(XLogReaderState *record)
#define TABLESPACE_VERSION_DIRECTORY
#define Anum_pg_tablespace_spcname
#define ObjectAddressSet(addr, class_id, object_id)
#define TableSpaceRelationId
void DeleteSharedSecurityLabel(Oid objectId, Oid classId)
static Datum values[MAXATTR]
ObjectAddress RenameTableSpace(const char *oldname, const char *newname)
int errmsg(const char *fmt,...)
void * MemoryContextAlloc(MemoryContext context, Size size)
char * get_tablespace_name(Oid spc_oid)
void list_free(List *list)
#define CHECKPOINT_IMMEDIATE
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
#define Anum_pg_tablespace_spcoptions
#define XLogRecHasAnyBlockRefs(decoder)
#define HeapTupleGetOid(tuple)
char * default_tablespace
#define RELPERSISTENCE_TEMP
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
void XLogBeginInsert(void)
#define ERRCODE_DUPLICATE_OBJECT
bool check_temp_tablespaces(char **newval, void **extra, GucSource source)
#define BTEqualStrategyNumber
#define offsetof(type, field)
void RequestCheckpoint(int flags)
#define Natts_pg_tablespace
Oid AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt)