81 #include "utils/fmgroids.h"
96 const Oid tablespaceoid);
127 if (spcNode == GLOBALTABLESPACE_OID)
135 if (
stat(dir, &st) < 0)
162 if (errno != ENOENT || !isRedo)
165 errmsg(
"could not create directory \"%s\": %m",
182 errmsg(
"could not create directory \"%s\": %m",
193 errmsg(
"could not create directory \"%s\": %m",
201 errmsg(
"could not create directory \"%s\": %m",
212 errmsg(
"could not stat directory \"%s\": %m", dir)));
220 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
221 errmsg(
"\"%s\" exists but is not a directory",
241 bool nulls[Natts_pg_tablespace];
252 (
errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
253 errmsg(
"permission denied to create tablespace \"%s\"",
255 errhint(
"Must be superuser to create a tablespace.")));
268 if (strchr(location,
'\''))
270 (
errcode(ERRCODE_INVALID_NAME),
271 errmsg(
"tablespace location cannot contain single quotes")));
283 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
284 errmsg(
"tablespace location must be an absolute path")));
295 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
296 errmsg(
"tablespace location \"%s\" is too long",
302 (
errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
303 errmsg(
"tablespace location should not be inside the data directory")));
311 (
errcode(ERRCODE_RESERVED_NAME),
312 errmsg(
"unacceptable tablespace name \"%s\"",
314 errdetail(
"The prefix \"pg_\" is reserved for system tablespaces.")));
320 #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
322 elog(
WARNING,
"tablespaces created by regression test cases should have names starting with \"regress_\"");
333 errmsg(
"tablespace \"%s\" already exists",
343 MemSet(nulls,
false,
sizeof(nulls));
350 (
errcode(ERRCODE_INVALID_PARAMETER_VALUE),
351 errmsg(
"pg_tablespace OID value not set when in binary upgrade mode")));
358 Anum_pg_tablespace_oid);
360 values[Anum_pg_tablespace_spcname - 1] =
362 values[Anum_pg_tablespace_spcowner - 1] =
364 nulls[Anum_pg_tablespace_spcacl - 1] =
true;
369 NULL, NULL,
false,
false);
371 if (newOptions != (
Datum) 0)
372 values[Anum_pg_tablespace_spcoptions - 1] = newOptions;
374 nulls[Anum_pg_tablespace_spcoptions - 1] =
true;
394 xlrec.
ts_id = tablespaceoid;
417 return tablespaceoid;
420 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
421 errmsg(
"tablespaces are not supported on this platform")));
451 Anum_pg_tablespace_spcname,
462 (
errcode(ERRCODE_UNDEFINED_OBJECT),
463 errmsg(
"tablespace \"%s\" does not exist",
469 (
errmsg(
"tablespace \"%s\" does not exist, skipping",
478 tablespaceoid = spcform->oid;
492 &detail, &detail_log))
494 (
errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
495 errmsg(
"tablespace \"%s\" cannot be dropped because some objects depend on it",
561 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
562 errmsg(
"tablespace \"%s\" is not empty",
571 xlrec.
ts_id = tablespaceoid;
602 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
603 errmsg(
"tablespaces are not supported on this platform")));
618 char *location_with_version_dir;
622 linkloc =
psprintf(
"pg_tblspc/%u", tablespaceoid);
629 in_place = strlen(location) == 0;
636 errmsg(
"could not create directory \"%s\": %m",
640 location_with_version_dir =
psprintf(
"%s/%s", in_place ? linkloc : location,
653 (
errcode(ERRCODE_UNDEFINED_FILE),
654 errmsg(
"directory \"%s\" does not exist", location),
656 "restarting the server.") : 0));
660 errmsg(
"could not set permissions on directory \"%s\": %m",
671 if (
stat(location_with_version_dir, &st) < 0)
676 errmsg(
"could not stat directory \"%s\": %m",
677 location_with_version_dir)));
681 errmsg(
"could not create directory \"%s\": %m",
682 location_with_version_dir)));
686 (
errcode(ERRCODE_WRONG_OBJECT_TYPE),
687 errmsg(
"\"%s\" exists but is not a directory",
688 location_with_version_dir)));
691 (
errcode(ERRCODE_OBJECT_IN_USE),
692 errmsg(
"directory \"%s\" already in use as a tablespace",
693 location_with_version_dir)));
704 if (!in_place &&
symlink(location, linkloc) < 0)
707 errmsg(
"could not create symbolic link \"%s\": %m",
711 pfree(location_with_version_dir);
732 char *linkloc_with_version_dir;
738 linkloc_with_version_dir =
psprintf(
"pg_tblspc/%u/%s", tablespaceoid,
771 errmsg(
"could not open directory \"%s\": %m",
772 linkloc_with_version_dir)));
781 errmsg(
"could not open directory \"%s\": %m",
782 linkloc_with_version_dir)));
783 pfree(linkloc_with_version_dir);
789 while ((de =
ReadDir(dirdesc, linkloc_with_version_dir)) != NULL)
791 if (strcmp(de->
d_name,
".") == 0 ||
792 strcmp(de->
d_name,
"..") == 0)
795 subfile =
psprintf(
"%s/%s", linkloc_with_version_dir, de->
d_name);
802 pfree(linkloc_with_version_dir);
807 if (rmdir(subfile) < 0)
810 errmsg(
"could not remove directory \"%s\": %m",
819 if (rmdir(linkloc_with_version_dir) < 0)
823 errmsg(
"could not remove directory \"%s\": %m",
824 linkloc_with_version_dir)));
825 pfree(linkloc_with_version_dir);
840 linkloc =
pstrdup(linkloc_with_version_dir);
842 if (
lstat(linkloc, &st) < 0)
844 int saved_errno = errno;
848 errmsg(
"could not stat file \"%s\": %m",
853 if (rmdir(linkloc) < 0)
855 int saved_errno = errno;
859 errmsg(
"could not remove directory \"%s\": %m",
866 if (unlink(linkloc) < 0)
868 int saved_errno = errno;
872 errmsg(
"could not remove symbolic link \"%s\": %m",
881 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
882 errmsg(
"\"%s\" is not a directory or symbolic link",
886 pfree(linkloc_with_version_dir);
906 while ((de =
ReadDir(dirdesc, path)) != NULL)
908 if (strcmp(de->
d_name,
".") == 0 ||
909 strcmp(de->
d_name,
"..") == 0)
933 if (
lstat(linkloc, &st) < 0)
939 errmsg(
"could not stat file \"%s\": %m", linkloc)));
948 if (rmdir(linkloc) < 0 && errno != ENOENT)
951 errmsg(
"could not remove directory \"%s\": %m",
957 if (unlink(linkloc) < 0 && errno != ENOENT)
960 errmsg(
"could not remove symbolic link \"%s\": %m",
968 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
969 errmsg(
"\"%s\" is not a directory or symbolic link",
993 Anum_pg_tablespace_spcname,
1000 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1001 errmsg(
"tablespace \"%s\" does not exist",
1006 tspId = newform->oid;
1017 (
errcode(ERRCODE_RESERVED_NAME),
1018 errmsg(
"unacceptable tablespace name \"%s\"", newname),
1019 errdetail(
"The prefix \"pg_\" is reserved for system tablespaces.")));
1025 #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS
1026 if (strncmp(newname,
"regress_", 8) != 0)
1027 elog(
WARNING,
"tablespaces created by regression test cases should have names starting with \"regress_\"");
1032 Anum_pg_tablespace_spcname,
1040 errmsg(
"tablespace \"%s\" already exists",
1072 Datum repl_val[Natts_pg_tablespace];
1074 bool repl_null[Natts_pg_tablespace];
1075 bool repl_repl[Natts_pg_tablespace];
1082 Anum_pg_tablespace_spcname,
1089 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1090 errmsg(
"tablespace \"%s\" does not exist",
1101 datum =
heap_getattr(tup, Anum_pg_tablespace_spcoptions,
1104 stmt->
options, NULL, NULL,
false,
1109 memset(repl_null,
false,
sizeof(repl_null));
1110 memset(repl_repl,
false,
sizeof(repl_repl));
1111 if (newOptions != (
Datum) 0)
1112 repl_val[Anum_pg_tablespace_spcoptions - 1] = newOptions;
1114 repl_null[Anum_pg_tablespace_spcoptions - 1] =
true;
1115 repl_repl[Anum_pg_tablespace_spcoptions - 1] =
true;
1117 repl_null, repl_repl);
1130 return tablespaceoid;
1158 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1159 errmsg(
"tablespace \"%s\" does not exist",
1196 if (relpersistence == RELPERSISTENCE_TEMP)
1225 (
errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1226 errmsg(
"cannot specify default tablespace for partitioned relations")));
1280 foreach(l, namelist)
1282 char *curname = (
char *)
lfirst(l);
1287 if (curname[0] ==
'\0')
1304 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1305 errmsg(
"tablespace \"%s\" does not exist",
1331 tblSpcs[numSpcs++] = curoid;
1336 numSpcs *
sizeof(
Oid));
1340 memcpy(myextra->
tblSpcs, tblSpcs, numSpcs *
sizeof(
Oid));
1341 *extra = (
void *) myextra;
1418 foreach(l, namelist)
1420 char *curname = (
char *)
lfirst(l);
1425 if (curname[0] ==
'\0')
1457 tblSpcs[numSpcs++] = curoid;
1490 Anum_pg_tablespace_spcname,
1507 (
errcode(ERRCODE_UNDEFINED_OBJECT),
1508 errmsg(
"tablespace \"%s\" does not exist",
1536 Anum_pg_tablespace_oid,
1569 char *location = xlrec->
ts_path;
1609 (
errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1610 errmsg(
"directories for tablespace %u could not be removed",
1612 errhint(
"You can remove the directories manually if necessary.")));
1616 elog(
PANIC,
"tblspc_redo: unknown op code %u", info);
Oid get_rolespec_oid(const RoleSpec *role, bool missing_ok)
AclResult pg_tablespace_aclcheck(Oid spc_oid, Oid roleid, AclMode mode)
bool pg_tablespace_ownercheck(Oid spc_oid, Oid roleid)
void aclcheck_error(AclResult aclerr, ObjectType objtype, const char *objectname)
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 spcNode, Oid dbNode, 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 offsetof(type, field)
#define FLEXIBLE_ARRAY_MEMBER
#define MemSet(start, val, len)
#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,...)
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
#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
#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)
#define CStringGetDatum(X)
#define ObjectIdGetDatum(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 dbNode, Oid spcNode)
#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 XLogBeginInsert(void)
void XLogRegisterData(char *data, int len)
#define XLogRecGetInfo(decoder)
#define XLogRecGetData(decoder)
#define XLogRecHasAnyBlockRefs(decoder)