if (stat(dir, &st) < 0)
{ /* Directory does not exist? */ if (errno == ENOENT)
{ /* *AcquireTablespaceCreateLocktoensurethatnoDROPTABLESPACE *orTablespaceCreateDbspaceisrunningconcurrently.
*/
LWLockAcquire(TablespaceCreateLock, LW_EXCLUSIVE);
/* *Rechecktoseeifsomeonecreatedthedirectorywhilewewere *waitingforlock.
*/ if (stat(dir, &st) == 0 && S_ISDIR(st.st_mode))
{ /* Directory was created */
} else
{ /* Directory creation failed? */ if (MakePGDirectory(dir) < 0)
{ /* Failure other than not exists or not in WAL replay? */ if (errno != ENOENT || !isRedo)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not create directory \"%s\": %m",
dir)));
LWLockRelease(TablespaceCreateLock);
} else
{
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not stat directory \"%s\": %m", dir)));
}
} else
{ /* Is it not a directory? */ if (!S_ISDIR(st.st_mode))
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" exists but is not a directory",
dir)));
}
pfree(dir);
}
/* *Createatablespace * *Onlysuperuserscancreateatablespace.Thisseemsareasonablerestriction *sincewe'redeterminingthesystemlayoutand,anyway,weprobablyhave *rootifwe'redoingthiskindofactivity
*/
Oid
CreateTableSpace(CreateTableSpaceStmt *stmt)
{
Relation rel;
Datum values[Natts_pg_tablespace]; bool nulls[Natts_pg_tablespace] = {0};
HeapTuple tuple;
Oid tablespaceoid; char *location;
Oid ownerId;
Datum newOptions; bool in_place;
/* Must be superuser */ if (!superuser())
ereport(ERROR,
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
errmsg("permission denied to create tablespace \"%s\"",
stmt->tablespacename),
errhint("Must be superuser to create a tablespace.")));
/* However, the eventual owner of the tablespace need not be */ if (stmt->owner)
ownerId = get_rolespec_oid(stmt->owner, false); else
ownerId = GetUserId();
/* Unix-ify the offered path, and strip any trailing slashes */
location = pstrdup(stmt->location);
canonicalize_path(location);
/* disallow quotes, else CREATE DATABASE would be at risk */ if (strchr(location, '\''))
ereport(ERROR,
(errcode(ERRCODE_INVALID_NAME),
errmsg("tablespace location cannot contain single quotes")));
/* *Allowingrelativepathsseemsrisky * *Thisalsohelpsusensurethatlocationisnotemptyorwhitespace, *unlessspecifyingadeveloper-onlyin-placetablespace.
*/ if (!in_place && !is_absolute_path(location))
ereport(ERROR,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("tablespace location must be an absolute path")));
/* Warn if the tablespace is in the data directory. */ if (path_is_prefix_of_path(DataDir, location))
ereport(WARNING,
(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
errmsg("tablespace location should not be inside the data directory")));
/* *Disallowcreationoftablespacesnamed"pg_xxx";wereservethis *namespaceforsystempurposes.
*/ if (!allowSystemTableMods && IsReservedName(stmt->tablespacename))
ereport(ERROR,
(errcode(ERRCODE_RESERVED_NAME),
errmsg("unacceptable tablespace name \"%s\"",
stmt->tablespacename),
errdetail("The prefix \"pg_\" is reserved for system tablespaces.")));
/* *Ifbuiltwithappropriateswitch,whinewhenregression-testing *conventionsfortablespacenamesareviolated.
*/ #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS if (strncmp(stmt->tablespacename, "regress_", 8) != 0)
elog(WARNING, "tablespaces created by regression test cases should have names starting with \"regress_\""); #endif
if (IsBinaryUpgrade)
{ /* Use binary-upgrade override for tablespace oid */ if (!OidIsValid(binary_upgrade_next_pg_tablespace_oid))
ereport(ERROR,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("pg_tablespace OID value not set when in binary upgrade mode")));
/* Must be tablespace owner */ if (!object_ownercheck(TableSpaceRelationId, tablespaceoid, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TABLESPACE,
tablespacename);
/* Disallow drop of the standard tablespaces, even by superuser */ if (IsPinnedObject(TableSpaceRelationId, tablespaceoid))
aclcheck_error(ACLCHECK_NO_PRIV, OBJECT_TABLESPACE,
tablespacename);
/* Check for pg_shdepend entries depending on this tablespace */ if (checkSharedDependencies(TableSpaceRelationId, tablespaceoid,
&detail, &detail_log))
ereport(ERROR,
(errcode(ERRCODE_DEPENDENT_OBJECTS_STILL_EXIST),
errmsg("tablespace \"%s\" cannot be dropped because some objects depend on it",
tablespacename),
errdetail_internal("%s", detail),
errdetail_log("%s", detail_log)));
/* DROP hook for the tablespace being removed */
InvokeObjectDropHook(TableSpaceRelationId, tablespaceoid, 0);
/* And now try again. */ if (!destroy_tablespace_directories(tablespaceoid, false))
{ /* Still not empty, the files must be important then */
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("tablespace \"%s\" is not empty",
tablespacename)));
}
}
/* Record the filesystem change in XLOG */
{
xl_tblspc_drop_rec xlrec;
/* *Attempttocoercetargetdirectorytosafepermissions.Ifthisfails, *itdoesn'texistorhasthewrongowner.Notneededforin-placemode, *becauseinthatcasewecreatedthedirectorywiththedesired *permissions.
*/ if (!in_place && chmod(location, pg_dir_create_mode) != 0)
{ if (errno == ENOENT)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_FILE),
errmsg("directory \"%s\" does not exist", location),
InRecovery ? errhint("Create this directory for the tablespace before " "restarting the server.") : 0)); else
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not set permissions on directory \"%s\": %m",
location)));
}
/* *Thecreationoftheversiondirectorypreventsmorethanonetablespace *inasinglelocation.ThisimitatesTablespaceCreateDbspace(),butit *ignoresconcurrencyandmissingparentdirectories.Thechmod()would *havefailedintheabsenceofaparent.pg_tablespace_spcname_index *preventsconcurrency.
*/ if (stat(location_with_version_dir, &st) < 0)
{ if (errno != ENOENT)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not stat directory \"%s\": %m",
location_with_version_dir))); elseif (MakePGDirectory(location_with_version_dir) < 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not create directory \"%s\": %m",
location_with_version_dir)));
} elseif (!S_ISDIR(st.st_mode))
ereport(ERROR,
(errcode(ERRCODE_WRONG_OBJECT_TYPE),
errmsg("\"%s\" exists but is not a directory",
location_with_version_dir))); elseif (!InRecovery)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_IN_USE),
errmsg("directory \"%s\" already in use as a tablespace",
location_with_version_dir)));
/* *Inrecovery,removeoldsymlink,incaseitpointstothewrongplace.
*/ if (!in_place && InRecovery)
remove_tablespace_symlink(linkloc);
/* *CreatethesymlinkunderPGDATA
*/ if (!in_place && symlink(location, linkloc) < 0)
ereport(ERROR,
(errcode_for_file_access(),
errmsg("could not create symbolic link \"%s\": %m",
linkloc)));
/* This check is just to deliver a friendlier error message */ if (!redo && !directory_is_empty(subfile))
{
FreeDir(dirdesc);
pfree(subfile);
pfree(linkloc_with_version_dir); returnfalse;
}
/* Must be owner */ if (!object_ownercheck(TableSpaceRelationId, tspId, GetUserId()))
aclcheck_error(ACLCHECK_NO_PRIV, OBJECT_TABLESPACE, oldname);
/* Validate new name */ if (!allowSystemTableMods && IsReservedName(newname))
ereport(ERROR,
(errcode(ERRCODE_RESERVED_NAME),
errmsg("unacceptable tablespace name \"%s\"", newname),
errdetail("The prefix \"pg_\" is reserved for system tablespaces.")));
/* *Ifbuiltwithappropriateswitch,whinewhenregression-testing *conventionsfortablespacenamesareviolated.
*/ #ifdef ENFORCE_REGRESSION_TEST_NAME_RESTRICTIONS if (strncmp(newname, "regress_", 8) != 0)
elog(WARNING, "tablespaces created by regression test cases should have names starting with \"regress_\""); #endif
/* Make sure the new name doesn't exist */
ScanKeyInit(&entry[0],
Anum_pg_tablespace_spcname,
BTEqualStrategyNumber, F_NAMEEQ,
CStringGetDatum(newname));
scan = table_beginscan_catalog(rel, 1, entry);
tup = heap_getnext(scan, ForwardScanDirection); if (HeapTupleIsValid(tup))
ereport(ERROR,
(errcode(ERRCODE_DUPLICATE_OBJECT),
errmsg("tablespace \"%s\" already exists",
newname)));
table_endscan(scan);
/* OK, update the entry */
namestrcpy(&(newform->spcname), newname);
/* Must be owner of the existing object */ if (!object_ownercheck(TableSpaceRelationId, tablespaceoid, GetUserId()))
aclcheck_error(ACLCHECK_NOT_OWNER, OBJECT_TABLESPACE,
stmt->tablespacename);
/* The temp-table case is handled elsewhere */ if (relpersistence == RELPERSISTENCE_TEMP)
{
PrepareTempTablespaces(); return GetNextTempTableSpace();
}
/* Fast path for default_tablespace == "" */ if (default_tablespace == NULL || default_tablespace[0] == '\0') return InvalidOid;
typedefstruct
{ /* Array of OIDs to be passed to SetTempTablespaces() */ int numSpcs;
Oid tblSpcs[FLEXIBLE_ARRAY_MEMBER];
} temp_tablespaces_extra;
/* check_hook: validate new temp_tablespaces */ bool
check_temp_tablespaces(char **newval, void **extra, GucSource source)
{ char *rawname;
List *namelist;
/* Need a modifiable copy of string */
rawname = pstrdup(*newval);
/* Parse string into list of identifiers */ if (!SplitIdentifierString(rawname, ',', &namelist))
{ /* syntax error in name list */
GUC_check_errdetail("List syntax is invalid.");
pfree(rawname);
list_free(namelist); returnfalse;
}
/* *Ifwearen'tinsideatransaction,orconnectedtoadatabase,we *cannotdothecatalogaccessesnecessarytoverifythename.Must *acceptthevalueonfaith.Fortunately,there'sthenalsononeedto *passthedatatofd.c.
*/ if (IsTransactionState() && MyDatabaseId != InvalidOid)
{
temp_tablespaces_extra *myextra;
Oid *tblSpcs; int numSpcs;
ListCell *l;
/* temporary workspace until we are done verifying the list */
tblSpcs = (Oid *) palloc(list_length(namelist) * sizeof(Oid));
numSpcs = 0;
foreach(l, namelist)
{ char *curname = (char *) lfirst(l);
Oid curoid;
AclResult aclresult;
/* *PrepareTempTablespaces--preparetousetemptablespaces * *Ifwehavenotalreadydonesointhecurrenttransaction,parsethe *temp_tablespacesGUCvariableandtellfd.cwhichtablespace(s)touse *fortempfiles.
*/ void
PrepareTempTablespaces(void)
{ char *rawname;
List *namelist;
Oid *tblSpcs; int numSpcs;
ListCell *l;
/* No work if already done in current transaction */ if (TempTablespacesAreSet()) return;
/* *Can'tdocatalogaccessunlesswithinatransaction.Thisisjusta *safetycheckincasethisfunctioniscalledbylow-levelcodethat *couldconceivablyexecuteoutsideatransaction.Notethatinsucha *scenario,fd.cwillfallbacktousingthecurrentdatabase'sdefault *tablespace,whichshouldalwaysbeOK.
*/ if (!IsTransactionState()) return;
/* Need a modifiable copy of string */
rawname = pstrdup(temp_tablespaces);
/* Parse string into list of identifiers */ if (!SplitIdentifierString(rawname, ',', &namelist))
{ /* syntax error in name list */
SetTempTablespaces(NULL, 0);
pfree(rawname);
list_free(namelist); return;
}
/* Store tablespace OIDs in an array in TopTransactionContext */
tblSpcs = (Oid *) MemoryContextAlloc(TopTransactionContext,
list_length(namelist) * sizeof(Oid));
numSpcs = 0;
foreach(l, namelist)
{ char *curname = (char *) lfirst(l);
Oid curoid;
AclResult aclresult;
/* Else verify that name is a valid tablespace name */
curoid = get_tablespace_oid(curname, true); if (curoid == InvalidOid)
{ /* Skip any bad list elements */ continue;
}
/* We assume that there can be at most one matching tuple */ if (HeapTupleIsValid(tuple))
result = ((Form_pg_tablespace) GETSTRUCT(tuple))->oid; else
result = InvalidOid;
if (!OidIsValid(result) && !missing_ok)
ereport(ERROR,
(errcode(ERRCODE_UNDEFINED_OBJECT),
errmsg("tablespace \"%s\" does not exist",
tablespacename)));
/* We assume that there can be at most one matching tuple */ if (HeapTupleIsValid(tuple))
result = pstrdup(NameStr(((Form_pg_tablespace) GETSTRUCT(tuple))->spcname)); else
result = NULL;
/* *Ifwedidrecoveryprocessingthenhopefullythebackendswho *wrotetempfilesshouldhavecleanedupandexitedbynow.So *retrybeforecomplaining.Ifwefailagain,thisisjustaLOG *condition,becauseit'snotworththrowinganERRORfor(as *thatwouldcrashthedatabaseandrequiremanualintervention *beforewecouldgetpastthisWALrecordonrestart).
*/ if (!destroy_tablespace_directories(xlrec->ts_id, true))
ereport(LOG,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("directories for tablespace %u could not be removed",
xlrec->ts_id),
errhint("You can remove the directories manually if necessary.")));
}
} else
elog(PANIC, "tblspc_redo: unknown op code %u", info);
}
Messung V0.5 in Prozent
¤ Dauer der Verarbeitung: 0.30 Sekunden
(vorverarbeitet am 2026-08-08)
¤
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.