aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/backend/catalog/pg_shdepend.c5
-rw-r--r--src/backend/commands/extension.c92
-rw-r--r--src/include/commands/extension.h2
3 files changed, 99 insertions, 0 deletions
diff --git a/src/backend/catalog/pg_shdepend.c b/src/backend/catalog/pg_shdepend.c
index b3696325c9d..5fdf1649d85 100644
--- a/src/backend/catalog/pg_shdepend.c
+++ b/src/backend/catalog/pg_shdepend.c
@@ -25,6 +25,7 @@
#include "catalog/pg_conversion.h"
#include "catalog/pg_database.h"
#include "catalog/pg_default_acl.h"
+#include "catalog/pg_extension.h"
#include "catalog/pg_foreign_data_wrapper.h"
#include "catalog/pg_foreign_server.h"
#include "catalog/pg_language.h"
@@ -1392,6 +1393,10 @@ shdepReassignOwned(List *roleids, Oid newrole)
AlterForeignDataWrapperOwner_oid(sdepForm->objid, newrole);
break;
+ case ExtensionRelationId:
+ AlterExtensionOwner_oid(sdepForm->objid, newrole);
+ break;
+
default:
elog(ERROR, "unexpected classid %u", sdepForm->classid);
break;
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 63b3ffa4ef0..2e587381784 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -2789,3 +2789,95 @@ ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt)
if (relation != NULL)
relation_close(relation, NoLock);
}
+
+/*
+ * AlterExtensionOwner_internal
+ *
+ * Internal routine for changing the owner of an extension. rel must be
+ * pg_extension, already open and suitably locked; it will not be closed.
+ *
+ * Note that this only changes ownership of the extension itself; it doesn't
+ * change the ownership of objects it contains. Since this function is
+ * currently only called from REASSIGN OWNED, this restriction is okay because
+ * said objects would also be affected by our caller. But it's not enough for
+ * a full-fledged ALTER OWNER implementation, so beware.
+ */
+static void
+AlterExtensionOwner_internal(Relation rel, Oid extensionOid, Oid newOwnerId)
+{
+ Form_pg_extension extForm;
+ HeapTuple tup;
+ SysScanDesc scandesc;
+ ScanKeyData entry[1];
+
+ Assert(RelationGetRelid(rel) == ExtensionRelationId);
+
+ ScanKeyInit(&entry[0],
+ ObjectIdAttributeNumber,
+ BTEqualStrategyNumber, F_OIDEQ,
+ ObjectIdGetDatum(extensionOid));
+
+ scandesc = systable_beginscan(rel, ExtensionOidIndexId, true,
+ SnapshotNow, 1, entry);
+
+ /* We assume that there can be at most one matching tuple */
+ tup = systable_getnext(scandesc);
+ if (!HeapTupleIsValid(tup)) /* should not happen */
+ elog(ERROR, "cache lookup failed for extension %u", extensionOid);
+
+ tup = heap_copytuple(tup);
+ systable_endscan(scandesc);
+
+ extForm = (Form_pg_extension) GETSTRUCT(tup);
+
+ /*
+ * If the new owner is the same as the existing owner, consider the
+ * command to have succeeded. This is for dump restoration purposes.
+ */
+ if (extForm->extowner != newOwnerId)
+ {
+ /* Superusers can always do it */
+ if (!superuser())
+ {
+ /* Otherwise, must be owner of the existing object */
+ if (!pg_extension_ownercheck(HeapTupleGetOid(tup), GetUserId()))
+ aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EXTENSION,
+ NameStr(extForm->extname));
+
+ /* Must be able to become new owner */
+ check_is_member_of_role(GetUserId(), newOwnerId);
+
+ /* no privilege checks on namespace are required */
+ }
+
+ /*
+ * Modify the owner --- okay to scribble on tup because it's a copy
+ */
+ extForm->extowner = newOwnerId;
+
+ simple_heap_update(rel, &tup->t_self, tup);
+
+ CatalogUpdateIndexes(rel, tup);
+
+ /* Update owner dependency reference */
+ changeDependencyOnOwner(ExtensionRelationId, extensionOid,
+ newOwnerId);
+ }
+
+ heap_freetuple(tup);
+}
+
+/*
+ * Change extension owner, by OID
+ */
+void
+AlterExtensionOwner_oid(Oid extensionOid, Oid newOwnerId)
+{
+ Relation rel;
+
+ rel = heap_open(ExtensionRelationId, RowExclusiveLock);
+
+ AlterExtensionOwner_internal(rel, extensionOid, newOwnerId);
+
+ heap_close(rel, NoLock);
+}
diff --git a/src/include/commands/extension.h b/src/include/commands/extension.h
index 2792c6dd49f..7b95f6d784b 100644
--- a/src/include/commands/extension.h
+++ b/src/include/commands/extension.h
@@ -46,4 +46,6 @@ extern char *get_extension_name(Oid ext_oid);
extern void AlterExtensionNamespace(List *names, const char *newschema);
+extern void AlterExtensionOwner_oid(Oid extensionOid, Oid newOwnerId);
+
#endif /* EXTENSION_H */