81 #include "utils/fmgroids.h"
96 const Oid tablespaceoid);
127 if (spcOid == GLOBALTABLESPACE_OID)
135 if (
stat(dir, &st) < 0)
160 if (errno != ENOENT || !isRedo)
163 errmsg(
"could not create directory \"%s\": %m",
179 errmsg(
"could not create directory \"%s\": %m",
190 errmsg(
"could not stat directory \"%s\": %m", dir)));
198 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
199 errmsg(
"\"%s\" exists but is not a directory",
218 bool nulls[Natts_pg_tablespace] = {0};
229 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
230 errmsg(
"permission denied to create tablespace \"%s\"",
231 stmt->tablespacename),
232 errhint(
"Must be superuser to create a tablespace.")));
245 if (strchr(location,
'\''))
247 (
errcode(ERRCODE_INVALID_NAME),
248 errmsg(
"tablespace location cannot contain single quotes")));
260 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
261 errmsg(
"tablespace location must be an absolute path")));
272 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
273 errmsg(
"tablespace location \"%s\" is too long",
279 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
280 errmsg(
"tablespace location should not be inside the data directory")));
288 (
errcode(ERRCODE_RESERVED_NAME),
289 errmsg(
"unacceptable tablespace name \"%s\"",
290 stmt->tablespacename),
291 errdetail(
"The prefix \"pg_\" is reserved for system tablespaces.")));
297 #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
298 if (strncmp(
stmt->tablespacename,
"regress_", 8) != 0)
299 elog(
WARNING,
"tablespaces created by regression test cases should have names starting with \"regress_\"");
310 errmsg(
"tablespace \"%s\" already exists",
311 stmt->tablespacename)));
325 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
326 errmsg(
"pg_tablespace OID value not set when in binary upgrade mode")));
333 Anum_pg_tablespace_oid);
335 values[Anum_pg_tablespace_spcname - 1] =
337 values[Anum_pg_tablespace_spcowner - 1] =
339 nulls[Anum_pg_tablespace_spcacl - 1] =
true;
344 NULL, NULL,
false,
false);
346 if (newOptions != (
Datum) 0)
347 values[Anum_pg_tablespace_spcoptions - 1] = newOptions;
349 nulls[Anum_pg_tablespace_spcoptions - 1] =
true;
369 xlrec.
ts_id = tablespaceoid;
392 return tablespaceoid;
403 char *tablespacename =
stmt->tablespacename;
419 Anum_pg_tablespace_spcname,
427 if (!
stmt->missing_ok)
430 (
errcode(ERRCODE_UNDEFINED_OBJECT),
431 errmsg(
"tablespace \"%s\" does not exist",
437 (
errmsg(
"tablespace \"%s\" does not exist, skipping",
446 tablespaceoid = spcform->oid;
460 &detail, &detail_log))
462 (
errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
463 errmsg(
"tablespace \"%s\" cannot be dropped because some objects depend on it",
529 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
530 errmsg(
"tablespace \"%s\" is not empty",
539 xlrec.
ts_id = tablespaceoid;
581 char *location_with_version_dir;
585 linkloc =
psprintf(
"pg_tblspc/%u", tablespaceoid);
592 in_place = strlen(location) == 0;
599 errmsg(
"could not create directory \"%s\": %m",
603 location_with_version_dir =
psprintf(
"%s/%s", in_place ? linkloc : location,
616 (
errcode(ERRCODE_UNDEFINED_FILE),
617 errmsg(
"directory \"%s\" does not exist", location),
619 "restarting the server.") : 0));
623 errmsg(
"could not set permissions on directory \"%s\": %m",
634 if (
stat(location_with_version_dir, &st) < 0)
639 errmsg(
"could not stat directory \"%s\": %m",
640 location_with_version_dir)));
644 errmsg(
"could not create directory \"%s\": %m",
645 location_with_version_dir)));
649 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
650 errmsg(
"\"%s\" exists but is not a directory",
651 location_with_version_dir)));
654 (
errcode(ERRCODE_OBJECT_IN_USE),
655 errmsg(
"directory \"%s\" already in use as a tablespace",
656 location_with_version_dir)));
667 if (!in_place &&
symlink(location, linkloc) < 0)
670 errmsg(
"could not create symbolic link \"%s\": %m",
674 pfree(location_with_version_dir);
695 char *linkloc_with_version_dir;
701 linkloc_with_version_dir =
psprintf(
"pg_tblspc/%u/%s", tablespaceoid,
734 errmsg(
"could not open directory \"%s\": %m",
735 linkloc_with_version_dir)));
744 errmsg(
"could not open directory \"%s\": %m",
745 linkloc_with_version_dir)));
746 pfree(linkloc_with_version_dir);
752 while ((de =
ReadDir(dirdesc, linkloc_with_version_dir)) != NULL)
754 if (strcmp(de->
d_name,
".") == 0 ||
755 strcmp(de->
d_name,
"..") == 0)
758 subfile =
psprintf(
"%s/%s", linkloc_with_version_dir, de->
d_name);
765 pfree(linkloc_with_version_dir);
770 if (rmdir(subfile) < 0)
773 errmsg(
"could not remove directory \"%s\": %m",
782 if (rmdir(linkloc_with_version_dir) < 0)
786 errmsg(
"could not remove directory \"%s\": %m",
787 linkloc_with_version_dir)));
788 pfree(linkloc_with_version_dir);
802 linkloc =
pstrdup(linkloc_with_version_dir);
804 if (
lstat(linkloc, &st) < 0)
806 int saved_errno = errno;
810 errmsg(
"could not stat file \"%s\": %m",
815 if (rmdir(linkloc) < 0)
817 int saved_errno = errno;
821 errmsg(
"could not remove directory \"%s\": %m",
827 if (unlink(linkloc) < 0)
829 int saved_errno = errno;
833 errmsg(
"could not remove symbolic link \"%s\": %m",
841 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
842 errmsg(
"\"%s\" is not a directory or symbolic link",
846 pfree(linkloc_with_version_dir);
866 while ((de =
ReadDir(dirdesc, path)) != NULL)
868 if (strcmp(de->
d_name,
".") == 0 ||
869 strcmp(de->
d_name,
"..") == 0)
893 if (
lstat(linkloc, &st) < 0)
899 errmsg(
"could not stat file \"%s\": %m", linkloc)));
908 if (rmdir(linkloc) < 0 && errno != ENOENT)
911 errmsg(
"could not remove directory \"%s\": %m",
916 if (unlink(linkloc) < 0 && errno != ENOENT)
919 errmsg(
"could not remove symbolic link \"%s\": %m",
926 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
927 errmsg(
"\"%s\" is not a directory or symbolic link",
951 Anum_pg_tablespace_spcname,
958 (
errcode(ERRCODE_UNDEFINED_OBJECT),
959 errmsg(
"tablespace \"%s\" does not exist",
964 tspId = newform->oid;
975 (
errcode(ERRCODE_RESERVED_NAME),
976 errmsg(
"unacceptable tablespace name \"%s\"", newname),
977 errdetail(
"The prefix \"pg_\" is reserved for system tablespaces.")));
983 #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
984 if (strncmp(newname,
"regress_", 8) != 0)
985 elog(
WARNING,
"tablespaces created by regression test cases should have names starting with \"regress_\"");
990 Anum_pg_tablespace_spcname,
998 errmsg(
"tablespace \"%s\" already exists",
1030 Datum repl_val[Natts_pg_tablespace];
1032 bool repl_null[Natts_pg_tablespace];
1033 bool repl_repl[Natts_pg_tablespace];
1040 Anum_pg_tablespace_spcname,
1047 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1048 errmsg(
"tablespace \"%s\" does not exist",
1049 stmt->tablespacename)));
1056 stmt->tablespacename);
1059 datum =
heap_getattr(tup, Anum_pg_tablespace_spcoptions,
1062 stmt->options, NULL, NULL,
false,
1067 memset(repl_null,
false,
sizeof(repl_null));
1068 memset(repl_repl,
false,
sizeof(repl_repl));
1069 if (newOptions != (
Datum) 0)
1070 repl_val[Anum_pg_tablespace_spcoptions - 1] = newOptions;
1072 repl_null[Anum_pg_tablespace_spcoptions - 1] =
true;
1073 repl_repl[Anum_pg_tablespace_spcoptions - 1] =
true;
1075 repl_null, repl_repl);
1088 return tablespaceoid;
1116 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1117 errmsg(
"tablespace \"%s\" does not exist",
1154 if (relpersistence == RELPERSISTENCE_TEMP)
1183 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1184 errmsg(
"cannot specify default tablespace for partitioned relations")));
1238 foreach(l, namelist)
1240 char *curname = (
char *)
lfirst(l);
1245 if (curname[0] ==
'\0')
1262 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1263 errmsg(
"tablespace \"%s\" does not exist",
1289 tblSpcs[numSpcs++] = curoid;
1294 numSpcs *
sizeof(
Oid));
1298 memcpy(myextra->
tblSpcs, tblSpcs, numSpcs *
sizeof(
Oid));
1299 *extra = (
void *) myextra;
1376 foreach(l, namelist)
1378 char *curname = (
char *)
lfirst(l);
1383 if (curname[0] ==
'\0')
1415 tblSpcs[numSpcs++] = curoid;
1448 Anum_pg_tablespace_spcname,
1465 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1466 errmsg(
"tablespace \"%s\" does not exist",
1494 Anum_pg_tablespace_oid,
1527 char *location = xlrec->
ts_path;
1567 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1568 errmsg(
"directories for tablespace %u could not be removed",
1570 errhint(
"You can remove the directories manually if necessary.")));
1574 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)
char * get_tablespace_name(Oid spc_oid)
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)
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 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)
elog(ERROR, "%s: %s", p2, msg)
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,...)
struct dirent * ReadDir(DIR *dir, const char *dirname)
int MakePGDirectory(const char *directoryName)
bool TempTablespacesAreSet(void)
Oid GetNextTempTableSpace(void)
void SetTempTablespaces(Oid *tableSpaces, int numSpaces)
DIR * AllocateDir(const char *dirname)
#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_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
HeapTuple heap_copytuple(HeapTuple tuple)
HeapTuple heap_modify_tuple(HeapTuple tuple, TupleDesc tupleDesc, Datum *replValues, bool *replIsnull, bool *doReplace)
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)
Assert(fmt[strlen(fmt) - 1] !='\n')
void list_free(List *list)
bool LWLockAcquire(LWLock *lock, LWLockMode mode)
void LWLockRelease(LWLock *lock)
MemoryContext TopTransactionContext
char * pstrdup(const char *in)
void pfree(void *pointer)
void * MemoryContextAlloc(MemoryContext context, Size size)
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, char *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
void XLogRegisterData(char *data, uint32 len)
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
void XLogBeginInsert(void)
#define XLogRecGetInfo(decoder)
#define XLogRecGetData(decoder)
#define XLogRecHasAnyBlockRefs(decoder)