76#include "utils/fmgroids.h"
90 const Oid tablespaceoid);
121 if (spcOid == GLOBALTABLESPACE_OID)
129 if (
stat(dir, &st) < 0)
154 if (errno != ENOENT || !isRedo)
157 errmsg(
"could not create directory \"%s\": %m",
173 errmsg(
"could not create directory \"%s\": %m",
184 errmsg(
"could not stat directory \"%s\": %m", dir)));
192 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
193 errmsg(
"\"%s\" exists but is not a directory",
212 bool nulls[Natts_pg_tablespace] = {0};
223 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
224 errmsg(
"permission denied to create tablespace \"%s\"",
225 stmt->tablespacename),
226 errhint(
"Must be superuser to create a tablespace.")));
239 if (strchr(location,
'\''))
241 (
errcode(ERRCODE_INVALID_NAME),
242 errmsg(
"tablespace location cannot contain single quotes")));
254 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
255 errmsg(
"tablespace location must be an absolute path")));
266 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
267 errmsg(
"tablespace location \"%s\" is too long",
273 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
274 errmsg(
"tablespace location should not be inside the data directory")));
282 (
errcode(ERRCODE_RESERVED_NAME),
283 errmsg(
"unacceptable tablespace name \"%s\"",
284 stmt->tablespacename),
285 errdetail(
"The prefix \"pg_\" is reserved for system tablespaces.")));
291#ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
292 if (strncmp(
stmt->tablespacename,
"regress_", 8) != 0)
293 elog(
WARNING,
"tablespaces created by regression test cases should have names starting with \"regress_\"");
304 errmsg(
"tablespace \"%s\" already exists",
305 stmt->tablespacename)));
319 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
320 errmsg(
"pg_tablespace OID value not set when in binary upgrade mode")));
327 Anum_pg_tablespace_oid);
329 values[Anum_pg_tablespace_spcname - 1] =
331 values[Anum_pg_tablespace_spcowner - 1] =
333 nulls[Anum_pg_tablespace_spcacl - 1] =
true;
338 NULL, NULL,
false,
false);
340 if (newOptions != (
Datum) 0)
341 values[Anum_pg_tablespace_spcoptions - 1] = newOptions;
343 nulls[Anum_pg_tablespace_spcoptions - 1] =
true;
363 xlrec.
ts_id = tablespaceoid;
386 return tablespaceoid;
397 char *tablespacename =
stmt->tablespacename;
413 Anum_pg_tablespace_spcname,
421 if (!
stmt->missing_ok)
424 (
errcode(ERRCODE_UNDEFINED_OBJECT),
425 errmsg(
"tablespace \"%s\" does not exist",
431 (
errmsg(
"tablespace \"%s\" does not exist, skipping",
440 tablespaceoid = spcform->oid;
454 &detail, &detail_log))
456 (
errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
457 errmsg(
"tablespace \"%s\" cannot be dropped because some objects depend on it",
523 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
524 errmsg(
"tablespace \"%s\" is not empty",
533 xlrec.
ts_id = tablespaceoid;
575 char *location_with_version_dir;
586 in_place = strlen(location) == 0;
593 errmsg(
"could not create directory \"%s\": %m",
597 location_with_version_dir =
psprintf(
"%s/%s", in_place ? linkloc : location,
610 (
errcode(ERRCODE_UNDEFINED_FILE),
611 errmsg(
"directory \"%s\" does not exist", location),
613 "restarting the server.") : 0));
617 errmsg(
"could not set permissions on directory \"%s\": %m",
628 if (
stat(location_with_version_dir, &st) < 0)
633 errmsg(
"could not stat directory \"%s\": %m",
634 location_with_version_dir)));
638 errmsg(
"could not create directory \"%s\": %m",
639 location_with_version_dir)));
643 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
644 errmsg(
"\"%s\" exists but is not a directory",
645 location_with_version_dir)));
648 (
errcode(ERRCODE_OBJECT_IN_USE),
649 errmsg(
"directory \"%s\" already in use as a tablespace",
650 location_with_version_dir)));
661 if (!in_place &&
symlink(location, linkloc) < 0)
664 errmsg(
"could not create symbolic link \"%s\": %m",
668 pfree(location_with_version_dir);
689 char *linkloc_with_version_dir;
728 errmsg(
"could not open directory \"%s\": %m",
729 linkloc_with_version_dir)));
738 errmsg(
"could not open directory \"%s\": %m",
739 linkloc_with_version_dir)));
740 pfree(linkloc_with_version_dir);
746 while ((de =
ReadDir(dirdesc, linkloc_with_version_dir)) != NULL)
748 if (strcmp(de->
d_name,
".") == 0 ||
749 strcmp(de->
d_name,
"..") == 0)
752 subfile =
psprintf(
"%s/%s", linkloc_with_version_dir, de->
d_name);
759 pfree(linkloc_with_version_dir);
764 if (rmdir(subfile) < 0)
767 errmsg(
"could not remove directory \"%s\": %m",
776 if (rmdir(linkloc_with_version_dir) < 0)
780 errmsg(
"could not remove directory \"%s\": %m",
781 linkloc_with_version_dir)));
782 pfree(linkloc_with_version_dir);
796 linkloc =
pstrdup(linkloc_with_version_dir);
798 if (
lstat(linkloc, &st) < 0)
800 int saved_errno = errno;
804 errmsg(
"could not stat file \"%s\": %m",
809 if (rmdir(linkloc) < 0)
811 int saved_errno = errno;
815 errmsg(
"could not remove directory \"%s\": %m",
821 if (unlink(linkloc) < 0)
823 int saved_errno = errno;
827 errmsg(
"could not remove symbolic link \"%s\": %m",
835 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
836 errmsg(
"\"%s\" is not a directory or symbolic link",
840 pfree(linkloc_with_version_dir);
860 while ((de =
ReadDir(dirdesc, path)) != NULL)
862 if (strcmp(de->
d_name,
".") == 0 ||
863 strcmp(de->
d_name,
"..") == 0)
887 if (
lstat(linkloc, &st) < 0)
893 errmsg(
"could not stat file \"%s\": %m", linkloc)));
902 if (rmdir(linkloc) < 0 && errno != ENOENT)
905 errmsg(
"could not remove directory \"%s\": %m",
910 if (unlink(linkloc) < 0 && errno != ENOENT)
913 errmsg(
"could not remove symbolic link \"%s\": %m",
920 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
921 errmsg(
"\"%s\" is not a directory or symbolic link",
945 Anum_pg_tablespace_spcname,
952 (
errcode(ERRCODE_UNDEFINED_OBJECT),
953 errmsg(
"tablespace \"%s\" does not exist",
958 tspId = newform->oid;
969 (
errcode(ERRCODE_RESERVED_NAME),
970 errmsg(
"unacceptable tablespace name \"%s\"", newname),
971 errdetail(
"The prefix \"pg_\" is reserved for system tablespaces.")));
977#ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
978 if (strncmp(newname,
"regress_", 8) != 0)
979 elog(
WARNING,
"tablespaces created by regression test cases should have names starting with \"regress_\"");
984 Anum_pg_tablespace_spcname,
992 errmsg(
"tablespace \"%s\" already exists",
1024 Datum repl_val[Natts_pg_tablespace];
1026 bool repl_null[Natts_pg_tablespace];
1027 bool repl_repl[Natts_pg_tablespace];
1034 Anum_pg_tablespace_spcname,
1041 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1042 errmsg(
"tablespace \"%s\" does not exist",
1043 stmt->tablespacename)));
1050 stmt->tablespacename);
1053 datum =
heap_getattr(tup, Anum_pg_tablespace_spcoptions,
1056 stmt->options, NULL, NULL,
false,
1061 memset(repl_null,
false,
sizeof(repl_null));
1062 memset(repl_repl,
false,
sizeof(repl_repl));
1063 if (newOptions != (
Datum) 0)
1064 repl_val[Anum_pg_tablespace_spcoptions - 1] = newOptions;
1066 repl_null[Anum_pg_tablespace_spcoptions - 1] =
true;
1067 repl_repl[Anum_pg_tablespace_spcoptions - 1] =
true;
1069 repl_null, repl_repl);
1082 return tablespaceoid;
1110 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1111 errmsg(
"tablespace \"%s\" does not exist",
1148 if (relpersistence == RELPERSISTENCE_TEMP)
1177 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1178 errmsg(
"cannot specify default tablespace for partitioned relations")));
1232 foreach(l, namelist)
1234 char *curname = (
char *)
lfirst(l);
1239 if (curname[0] ==
'\0')
1256 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1257 errmsg(
"tablespace \"%s\" does not exist",
1283 tblSpcs[numSpcs++] = curoid;
1288 numSpcs *
sizeof(
Oid));
1292 memcpy(myextra->
tblSpcs, tblSpcs, numSpcs *
sizeof(
Oid));
1370 foreach(l, namelist)
1372 char *curname = (
char *)
lfirst(l);
1377 if (curname[0] ==
'\0')
1409 tblSpcs[numSpcs++] = curoid;
1442 Anum_pg_tablespace_spcname,
1459 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1460 errmsg(
"tablespace \"%s\" does not exist",
1488 Anum_pg_tablespace_oid,
1521 char *location = xlrec->
ts_path;
1561 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1562 errmsg(
"directories for tablespace %u could not be removed",
1564 errhint(
"You can remove the directories manually if necessary.")));
1568 elog(
PANIC,
"tblspc_redo: unknown op code %u", info);
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
AclResult object_aclcheck(Oid classid, Oid objectid, Oid roleid, AclMode mode)
bool object_ownercheck(Oid classid, Oid objectid, Oid roleid)
Oid AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt)
Oid binary_upgrade_next_pg_tablespace_oid
bool directory_is_empty(const char *path)
void remove_tablespace_symlink(const char *linkloc)
static bool destroy_tablespace_directories(Oid tablespaceoid, bool redo)
bool check_default_tablespace(char **newval, void **extra, GucSource source)
char * get_tablespace_name(Oid spc_oid)
void DropTableSpace(DropTableSpaceStmt *stmt)
void PrepareTempTablespaces(void)
Oid get_tablespace_oid(const char *tablespacename, bool missing_ok)
ObjectAddress RenameTableSpace(const char *oldname, const char *newname)
void assign_temp_tablespaces(const char *newval, void *extra)
Oid GetDefaultTablespace(char relpersistence, bool partitioned)
void TablespaceCreateDbspace(Oid spcOid, Oid dbOid, bool isRedo)
bool check_temp_tablespaces(char **newval, void **extra, GucSource source)
Oid CreateTableSpace(CreateTableSpaceStmt *stmt)
char * default_tablespace
static void create_tablespace_directories(const char *location, const Oid tablespaceoid)
void tblspc_redo(XLogReaderState *record)
bool allow_in_place_tablespaces
static Datum values[MAXATTR]
#define Assert(condition)
#define FLEXIBLE_ARRAY_MEMBER
#define OidIsValid(objectId)
Oid GetNewOidWithIndex(Relation relation, Oid indexId, AttrNumber oidcolumn)
bool IsPinnedObject(Oid classId, Oid objectId)
bool IsReservedName(const char *name)
void RequestCheckpoint(int flags)
int errdetail_internal(const char *fmt,...)
int errcode_for_file_access(void)
int errdetail(const char *fmt,...)
int errhint(const char *fmt,...)
int errcode(int sqlerrcode)
int errmsg(const char *fmt,...)
int errdetail_log(const char *fmt,...)
#define ereport(elevel,...)
int MakePGDirectory(const char *directoryName)
bool TempTablespacesAreSet(void)
Oid GetNextTempTableSpace(void)
DIR * AllocateDir(const char *dirname)
struct dirent * ReadDir(DIR *dir, const char *dirname)
void SetTempTablespaces(Oid *tableSpaces, int numSpaces)
#define DirectFunctionCall1(func, arg1)
bool allowSystemTableMods
void * guc_malloc(int elevel, size_t size)
#define GUC_check_errdetail
HeapTuple heap_getnext(TableScanDesc sscan, ScanDirection direction)
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, const Datum *replValues, const bool *replIsnull, const bool *doReplace)
HeapTuple heap_copytuple(HeapTuple tuple)
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
void heap_freetuple(HeapTuple htup)
#define HeapTupleIsValid(tuple)
static Datum heap_getattr(HeapTuple tup, int attnum, TupleDesc tupleDesc, bool *isnull)
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
void list_free(List *list)
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
void LWLockRelease(LWLock *lock)
void * MemoryContextAlloc(MemoryContext context, Size size)
MemoryContext TopTransactionContext
char * pstrdup(const char *in)
void pfree(void *pointer)
void namestrcpy(Name name, const char *str)
Datum namein(PG_FUNCTION_ARGS)
#define InvokeObjectPostCreateHook(classId, objectId, subId)
#define InvokeObjectPostAlterHook(classId, objectId, subId)
#define InvokeObjectDropHook(classId, objectId, subId)
#define ObjectAddressSet(addr, class_id, object_id)
static int list_length(const List *l)
static rewind_source * source
void deleteSharedDependencyRecordsFor(Oid classId, Oid objectId, int32 objectSubId)
void recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
bool checkSharedDependencies(Oid classId, Oid objectId, char **detail_msg, char **detail_log_msg)
FormData_pg_tablespace * Form_pg_tablespace
int pg_mkdir_p(char *path, int omode)
#define is_absolute_path(filename)
bool path_is_prefix_of_path(const char *path1, const char *path2)
void canonicalize_path(char *path)
void get_parent_directory(char *path)
static Datum ObjectIdGetDatum(Oid X)
static Datum CStringGetDatum(const char *X)
void WaitForProcSignalBarrier(uint64 generation)
uint64 EmitProcSignalBarrier(ProcSignalBarrierType type)
@ PROCSIGNAL_BARRIER_SMGRRELEASE
char * psprintf(const char *fmt,...)
#define RelationGetDescr(relation)
bytea * tablespace_reloptions(Datum reloptions, bool validate)
Datum transformRelOptions(Datum oldOptions, List *defList, const char *namspace, const char *const validnsps[], bool acceptOidsOff, bool isReset)
char * GetDatabasePath(Oid dbOid, Oid spcOid)
#define TABLESPACE_VERSION_DIRECTORY
void ScanKeyInit(ScanKey entry, AttrNumber attributeNumber, StrategyNumber strategy, RegProcedure procedure, Datum argument)
void DeleteSharedSecurityLabel(Oid objectId, Oid classId)
void ResolveRecoveryConflictWithTablespace(Oid tsid)
#define BTEqualStrategyNumber
#define ERRCODE_DUPLICATE_OBJECT
char ts_path[FLEXIBLE_ARRAY_MEMBER]
void table_close(Relation relation, LOCKMODE lockmode)
Relation table_open(Oid relationId, LOCKMODE lockmode)
TableScanDesc table_beginscan_catalog(Relation relation, int nkeys, struct ScanKeyData *key)
static void table_endscan(TableScanDesc scan)
#define XLOG_TBLSPC_CREATE
bool SplitIdentifierString(char *rawstring, char separator, List **namelist)
#define symlink(oldpath, newpath)
bool IsTransactionState(void)
void ForceSyncCommit(void)
#define CHECKPOINT_IMMEDIATE
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
void XLogRegisterData(const char *data, uint32 len)
void XLogBeginInsert(void)
#define XLogRecGetInfo(decoder)
#define XLogRecGetData(decoder)
#define XLogRecHasAnyBlockRefs(decoder)