aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2012-08-15 11:27:06 -0400
committerTom Lane <tgl@sss.pgh.pa.us>2012-08-15 11:27:06 -0400
commit9e035184b0fc807297dee5e2d0a219fee21fd08a (patch)
tree522c50fd78925ccbd00a986d613bf96fa72ac1e1
parent04e96bc69d541dd7b5f4d3b3daf49d291c7fcbb4 (diff)
downloadpostgresql-9e035184b0fc807297dee5e2d0a219fee21fd08a.tar.gz
postgresql-9e035184b0fc807297dee5e2d0a219fee21fd08a.zip
Disallow extensions from owning the schema they are assigned to.
This situation creates a dependency loop that confuses pg_dump and probably other things. Moreover, since the mental model is that the extension "contains" schemas it owns, but "is contained in" its extschema (even though neither is strictly true), having both true at once is confusing for people too. So prevent the situation from being set up. Reported and patched by Thom Brown. Back-patch to 9.1 where extensions were added.
-rw-r--r--src/backend/commands/extension.c30
1 files changed, 27 insertions, 3 deletions
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 2e587381784..9bac9a3efe7 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -2290,6 +2290,17 @@ AlterExtensionNamespace(List *names, const char *newschema)
if (aclresult != ACLCHECK_OK)
aclcheck_error(aclresult, ACL_KIND_NAMESPACE, newschema);
+ /*
+ * If the schema is currently a member of the extension, disallow moving
+ * the extension into the schema. That would create a dependency loop.
+ */
+ if (getExtensionOfObject(NamespaceRelationId, nspOid) == extensionOid)
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("cannot move extension \"%s\" into schema \"%s\" "
+ "because the extension contains the schema",
+ extensionName, newschema)));
+
/* Locate the pg_extension tuple */
extRel = heap_open(ExtensionRelationId, RowExclusiveLock);
@@ -2755,6 +2766,19 @@ ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt)
get_extension_name(oldExtension))));
/*
+ * Prevent a schema from being added to an extension if the schema
+ * contains the extension. That would create a dependency loop.
+ */
+ if (object.classId == NamespaceRelationId &&
+ object.objectId == get_extension_schema(extension.objectId))
+ ereport(ERROR,
+ (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+ errmsg("cannot add schema \"%s\" to extension \"%s\" "
+ "because the schema contains the extension",
+ get_namespace_name(object.objectId),
+ stmt->extname)));
+
+ /*
* OK, add the dependency.
*/
recordDependencyOn(&object, &extension, DEPENDENCY_EXTENSION);
@@ -2807,8 +2831,8 @@ AlterExtensionOwner_internal(Relation rel, Oid extensionOid, Oid newOwnerId)
{
Form_pg_extension extForm;
HeapTuple tup;
- SysScanDesc scandesc;
- ScanKeyData entry[1];
+ SysScanDesc scandesc;
+ ScanKeyData entry[1];
Assert(RelationGetRelid(rel) == ExtensionRelationId);
@@ -2876,7 +2900,7 @@ AlterExtensionOwner_oid(Oid extensionOid, Oid newOwnerId)
Relation rel;
rel = heap_open(ExtensionRelationId, RowExclusiveLock);
-
+
AlterExtensionOwner_internal(rel, extensionOid, newOwnerId);
heap_close(rel, NoLock);