aboutsummaryrefslogtreecommitdiff
path: root/src/backend/commands/typecmds.c
diff options
context:
space:
mode:
authorAlvaro Herrera <alvherre@alvh.no-ip.org>2015-12-21 19:49:15 -0300
committerAlvaro Herrera <alvherre@alvh.no-ip.org>2015-12-21 19:49:15 -0300
commit7e29e7f5544d41cdf3cc2ed209ecabfa0242af04 (patch)
tree23a6a1600cc65f109fa2eee4494530f526ce45a2 /src/backend/commands/typecmds.c
parentab14c1383836301f00461b2a5593aebd340dd801 (diff)
downloadpostgresql-7e29e7f5544d41cdf3cc2ed209ecabfa0242af04.tar.gz
postgresql-7e29e7f5544d41cdf3cc2ed209ecabfa0242af04.zip
Rework internals of changing a type's ownership
This is necessary so that REASSIGN OWNED does the right thing with composite types, to wit, that it also alters ownership of the type's pg_class entry -- previously, the pg_class entry remained owned by the original user, which caused later other failures such as the new owner's inability to use ALTER TYPE to rename an attribute of the affected composite. Also, if the original owner is later dropped, the pg_class entry becomes owned by a non-existant user which is bogus. To fix, create a new routine AlterTypeOwner_oid which knows whether to pass the request to ATExecChangeOwner or deal with it directly, and use that in shdepReassignOwner rather than calling AlterTypeOwnerInternal directly. AlterTypeOwnerInternal is now simpler in that it only modifies the pg_type entry and recurses to handle a possible array type; higher-level tasks are handled by either AlterTypeOwner directly or AlterTypeOwner_oid. I took the opportunity to add a few more objects to the test rig for REASSIGN OWNED, so that more cases are exercised. Additional ones could be added for superuser-only-ownable objects (such as FDWs and event triggers) but I didn't want to push my luck by adding a new superuser to the tests on a backpatchable bug fix. Per bug #13666 reported by Chris Pacejo. This is a backpatch of commit 756e7b4c9db1 to branches 9.1 -- 9.4.
Diffstat (limited to 'src/backend/commands/typecmds.c')
-rw-r--r--src/backend/commands/typecmds.c87
1 files changed, 47 insertions, 40 deletions
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index 9a717d01211..01e014d6e1c 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -2717,53 +2717,64 @@ AlterTypeOwner(List *names, Oid newOwnerId)
get_namespace_name(typTup->typnamespace));
}
- /*
- * If it's a composite type, invoke ATExecChangeOwner so that we fix
- * up the pg_class entry properly. That will call back to
- * AlterTypeOwnerInternal to take care of the pg_type entry(s).
- */
- if (typTup->typtype == TYPTYPE_COMPOSITE)
- ATExecChangeOwner(typTup->typrelid, newOwnerId, true, AccessExclusiveLock);
- else
- {
- /*
- * We can just apply the modification directly.
- *
- * okay to scribble on typTup because it's a copy
- */
- typTup->typowner = newOwnerId;
+ AlterTypeOwner_oid(typeOid, newOwnerId, true);
+ }
+
+ /* Clean up */
+ heap_close(rel, RowExclusiveLock);
+}
+
+/*
+ * AlterTypeOwner_oid - change type owner unconditionally
+ *
+ * This function recurses to handle a pg_class entry, if necessary. It
+ * invokes any necessary access object hooks. If hasDependEntry is TRUE, this
+ * function modifies the pg_shdepend entry appropriately (this should be
+ * passed as FALSE only for table rowtypes and array types).
+ *
+ * This is used by ALTER TABLE/TYPE OWNER commands, as well as by REASSIGN
+ * OWNED BY. It assumes the caller has done all needed check.
+ */
+void
+AlterTypeOwner_oid(Oid typeOid, Oid newOwnerId, bool hasDependEntry)
+{
+ Relation rel;
+ HeapTuple tup;
+ Form_pg_type typTup;
- simple_heap_update(rel, &tup->t_self, tup);
+ rel = heap_open(TypeRelationId, RowExclusiveLock);
- CatalogUpdateIndexes(rel, tup);
+ tup = SearchSysCache1(TYPEOID, ObjectIdGetDatum(typeOid));
+ if (!HeapTupleIsValid(tup))
+ elog(ERROR, "cache lookup failed for type %u", typeOid);
+ typTup = (Form_pg_type) GETSTRUCT(tup);
- /* Update owner dependency reference */
- changeDependencyOnOwner(TypeRelationId, typeOid, newOwnerId);
+ /*
+ * If it's a composite type, invoke ATExecChangeOwner so that we fix up the
+ * pg_class entry properly. That will call back to AlterTypeOwnerInternal
+ * to take care of the pg_type entry(s).
+ */
+ if (typTup->typtype == TYPTYPE_COMPOSITE)
+ ATExecChangeOwner(typTup->typrelid, newOwnerId, true, AccessExclusiveLock);
+ else
+ AlterTypeOwnerInternal(typeOid, newOwnerId);
- /* If it has an array type, update that too */
- if (OidIsValid(typTup->typarray))
- AlterTypeOwnerInternal(typTup->typarray, newOwnerId, false);
- }
- }
+ /* Update owner dependency reference */
+ if (hasDependEntry)
+ changeDependencyOnOwner(TypeRelationId, typeOid, newOwnerId);
- /* Clean up */
+ ReleaseSysCache(tup);
heap_close(rel, RowExclusiveLock);
}
/*
- * AlterTypeOwnerInternal - change type owner unconditionally
- *
- * This is currently only used to propagate ALTER TABLE/TYPE OWNER to a
- * table's rowtype or an array type, and to implement REASSIGN OWNED BY.
- * It assumes the caller has done all needed checks. The function will
- * automatically recurse to an array type if the type has one.
+ * AlterTypeOwnerInternal - bare-bones type owner change.
*
- * hasDependEntry should be TRUE if type is expected to have a pg_shdepend
- * entry (ie, it's not a table rowtype nor an array type).
+ * This routine simply modifies the owner of a pg_type entry, and recurses
+ * to handle a possible array type.
*/
void
-AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId,
- bool hasDependEntry)
+AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId)
{
Relation rel;
HeapTuple tup;
@@ -2785,13 +2796,9 @@ AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId,
CatalogUpdateIndexes(rel, tup);
- /* Update owner dependency reference, if it has one */
- if (hasDependEntry)
- changeDependencyOnOwner(TypeRelationId, typeOid, newOwnerId);
-
/* If it has an array type, update that too */
if (OidIsValid(typTup->typarray))
- AlterTypeOwnerInternal(typTup->typarray, newOwnerId, false);
+ AlterTypeOwnerInternal(typTup->typarray, newOwnerId);
/* Clean up */
heap_close(rel, RowExclusiveLock);