Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend')
-rw-r--r--src/backend/catalog/heap.c9
-rw-r--r--src/backend/catalog/pg_shdepend.c68
-rw-r--r--src/backend/commands/tablecmds.c4
-rw-r--r--src/backend/commands/tablespace.c12
4 files changed, 84 insertions, 9 deletions
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 21f2240ade8..9abc4a1f556 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -440,6 +440,15 @@ heap_create(const char *relname,
}
}
+ /*
+ * If a tablespace is specified, removal of that tablespace is normally
+ * protected by the existence of a physical file; but for relations with
+ * no files, add a pg_shdepend entry to account for that.
+ */
+ if (!create_storage && reltablespace != InvalidOid)
+ recordDependencyOnTablespace(RelationRelationId, relid,
+ reltablespace);
+
return rel;
}
diff --git a/src/backend/catalog/pg_shdepend.c b/src/backend/catalog/pg_shdepend.c
index 86c3be107ff..90b7a5de299 100644
--- a/src/backend/catalog/pg_shdepend.c
+++ b/src/backend/catalog/pg_shdepend.c
@@ -59,6 +59,7 @@
#include "commands/schemacmds.h"
#include "commands/subscriptioncmds.h"
#include "commands/tablecmds.h"
+#include "commands/tablespace.h"
#include "commands/typecmds.h"
#include "miscadmin.h"
#include "storage/lmgr.h"
@@ -186,11 +187,14 @@ recordDependencyOnOwner(Oid classId, Oid objectId, Oid owner)
*
* 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.
@@ -345,6 +349,58 @@ changeDependencyOnOwner(Oid classId, Oid objectId, Oid newOwnerId)
}
/*
+ * 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.
*
@@ -1121,13 +1177,6 @@ shdepLockAndCheckObject(Oid classId, Oid objectId)
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: */
@@ -1141,7 +1190,6 @@ shdepLockAndCheckObject(Oid classId, Oid objectId)
pfree(tablespace);
break;
}
-#endif
case DatabaseRelationId:
{
@@ -1201,6 +1249,8 @@ storeObjectDescription(StringInfo descs,
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);
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 993da56d437..fd55bf4ac7d 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -13340,6 +13340,10 @@ ATExecSetTableSpaceNoStorage(Relation rel, Oid newTableSpace)
rd_rel->reltablespace = (newTableSpace == MyDatabaseTableSpace) ? InvalidOid : newTableSpace;
CatalogTupleUpdate(pg_class, &tuple->t_self, tuple);
+ /* Record dependency on tablespace */
+ changeDependencyOnTablespace(RelationRelationId,
+ reloid, rd_rel->reltablespace);
+
InvokeObjectPostAlterHook(RelationRelationId, reloid, 0);
heap_freetuple(tuple);
diff --git a/src/backend/commands/tablespace.c b/src/backend/commands/tablespace.c
index a9a2db28345..69ea155d502 100644
--- a/src/backend/commands/tablespace.c
+++ b/src/backend/commands/tablespace.c
@@ -420,6 +420,8 @@ DropTableSpace(DropTableSpaceStmt *stmt)
Form_pg_tablespace spcform;
ScanKeyData entry[1];
Oid tablespaceoid;
+ char *detail;
+ char *detail_log;
/*
* Find the target tuple
@@ -468,6 +470,16 @@ DropTableSpace(DropTableSpaceStmt *stmt)
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);