#include "commands/schemacmds.h"
#include "commands/subscriptioncmds.h"
#include "commands/tablecmds.h"
+#include "commands/tablespace.h"
#include "commands/typecmds.h"
#include "storage/lmgr.h"
#include "miscadmin.h"
*
* There must be no more than one existing entry for the given dependent
* object and dependency type! So in practice this can only be used for
- * updating SHARED_DEPENDENCY_OWNER entries, which should have that property.
+ * updating SHARED_DEPENDENCY_OWNER and SHARED_DEPENDENCY_TABLESPACE
+ * entries, which should have that property.
*
* If there is no previous entry, we assume it was referencing a PINned
* object, so we create a new entry. If the new referenced object is
* PINned, we don't create an entry (and drop the old one, if any).
+ * (For tablespaces, we don't record dependencies in certain cases, so
+ * there are other possible reasons for entries to be missing.)
*
* sdepRel must be the pg_shdepend relation, already opened and suitably
* locked.
table_close(sdepRel, RowExclusiveLock);
}
+/*
+ * recordDependencyOnTablespace
+ *
+ * A convenient wrapper of recordSharedDependencyOn -- register the specified
+ * tablespace as default for the given object.
+ *
+ * Note: it's the caller's responsibility to ensure that there isn't a
+ * tablespace entry for the object already.
+ */
+void
+recordDependencyOnTablespace(Oid classId, Oid objectId, Oid tablespace)
+{
+ ObjectAddress myself,
+ referenced;
+
+ ObjectAddressSet(myself, classId, objectId);
+ ObjectAddressSet(referenced, TableSpaceRelationId, tablespace);
+
+ recordSharedDependencyOn(&myself, &referenced,
+ SHARED_DEPENDENCY_TABLESPACE);
+}
+
+/*
+ * changeDependencyOnTablespace
+ *
+ * Update the shared dependencies to account for the new tablespace.
+ *
+ * Note: we don't need an objsubid argument because only whole objects
+ * have tablespaces.
+ */
+void
+changeDependencyOnTablespace(Oid classId, Oid objectId, Oid newTablespaceId)
+{
+ Relation sdepRel;
+
+ sdepRel = table_open(SharedDependRelationId, RowExclusiveLock);
+
+ if (newTablespaceId != DEFAULTTABLESPACE_OID &&
+ newTablespaceId != InvalidOid)
+ shdepChangeDep(sdepRel,
+ classId, objectId, 0,
+ TableSpaceRelationId, newTablespaceId,
+ SHARED_DEPENDENCY_TABLESPACE);
+ else
+ shdepDropDependency(sdepRel,
+ classId, objectId, 0, true,
+ InvalidOid, InvalidOid,
+ SHARED_DEPENDENCY_INVALID);
+
+ table_close(sdepRel, RowExclusiveLock);
+}
+
/*
* getOidListDiff
* Helper for updateAclDependencies.
objectId)));
break;
- /*
- * Currently, this routine need not support any other shared
- * object types besides roles. If we wanted to record explicit
- * dependencies on databases or tablespaces, we'd need code along
- * these lines:
- */
-#ifdef NOT_USED
case TableSpaceRelationId:
{
/* For lack of a syscache on pg_tablespace, do this: */
pfree(tablespace);
break;
}
-#endif
case DatabaseRelationId:
{
appendStringInfo(descs, _("privileges for %s"), objdesc);
else if (deptype == SHARED_DEPENDENCY_POLICY)
appendStringInfo(descs, _("target of %s"), objdesc);
+ else if (deptype == SHARED_DEPENDENCY_TABLESPACE)
+ appendStringInfo(descs, _("tablespace for %s"), objdesc);
else
elog(ERROR, "unrecognized dependency type: %d",
(int) deptype);
Form_pg_tablespace spcform;
ScanKeyData entry[1];
Oid tablespaceoid;
+ char *detail;
+ char *detail_log;
/*
* Find the target tuple
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);
* a role mentioned in a policy object. The referenced object must be a
* pg_authid entry.
*
+ * (e) a SHARED_DEPENDENCY_TABLESPACE entry means that the referenced
+ * object is a tablespace mentioned in a relation without storage. The
+ * referenced object must be a pg_tablespace entry. (Relations that have
+ * storage don't need this: they are protected by the existence of a physical
+ * file in the tablespace.)
+ *
* SHARED_DEPENDENCY_INVALID is a value used as a parameter in internal
* routines, and is not valid in the catalog itself.
*/
SHARED_DEPENDENCY_OWNER = 'o',
SHARED_DEPENDENCY_ACL = 'a',
SHARED_DEPENDENCY_POLICY = 'r',
+ SHARED_DEPENDENCY_TABLESPACE = 't',
SHARED_DEPENDENCY_INVALID = 0
} SharedDependencyType;
extern void changeDependencyOnOwner(Oid classId, Oid objectId,
Oid newOwnerId);
+extern void recordDependencyOnTablespace(Oid classId, Oid objectId,
+ Oid tablespace);
+
+extern void changeDependencyOnTablespace(Oid classId, Oid objectId,
+ Oid newTablespaceId);
+
extern void updateAclDependencies(Oid classId, Oid objectId, int32 objectSubId,
Oid ownerId,
int noldmembers, Oid *oldmembers,