Commits

Alvaro Herrera  committed 994c36e

refactor ALTER some-obj SET OWNER implementation

Remove duplicate implementation of catalog munging and miscellaneous
privilege and consistency checks. Instead rely on already existing data
in objectaddress.c to do the work.

Author: KaiGai Kohei
Tweaked by me
Reviewed by Robert Haas

  • Participants
  • Parent commits 1f91c8c

Comments (0)

Files changed (24)

File src/backend/catalog/pg_largeobject.c

 }
 
 /*
- * LargeObjectAlterOwner
- *
- * Implementation of ALTER LARGE OBJECT statement
- */
-void
-LargeObjectAlterOwner(Oid loid, Oid newOwnerId)
-{
-	Form_pg_largeobject_metadata form_lo_meta;
-	Relation	pg_lo_meta;
-	ScanKeyData skey[1];
-	SysScanDesc scan;
-	HeapTuple	oldtup;
-	HeapTuple	newtup;
-
-	pg_lo_meta = heap_open(LargeObjectMetadataRelationId,
-						   RowExclusiveLock);
-
-	ScanKeyInit(&skey[0],
-				ObjectIdAttributeNumber,
-				BTEqualStrategyNumber, F_OIDEQ,
-				ObjectIdGetDatum(loid));
-
-	scan = systable_beginscan(pg_lo_meta,
-							  LargeObjectMetadataOidIndexId, true,
-							  SnapshotNow, 1, skey);
-
-	oldtup = systable_getnext(scan);
-	if (!HeapTupleIsValid(oldtup))
-		ereport(ERROR,
-				(errcode(ERRCODE_UNDEFINED_OBJECT),
-				 errmsg("large object %u does not exist", loid)));
-
-	form_lo_meta = (Form_pg_largeobject_metadata) GETSTRUCT(oldtup);
-	if (form_lo_meta->lomowner != newOwnerId)
-	{
-		Datum		values[Natts_pg_largeobject_metadata];
-		bool		nulls[Natts_pg_largeobject_metadata];
-		bool		replaces[Natts_pg_largeobject_metadata];
-		Acl		   *newAcl;
-		Datum		aclDatum;
-		bool		isnull;
-
-		/* Superusers can always do it */
-		if (!superuser())
-		{
-			/*
-			 * lo_compat_privileges is not checked here, because ALTER LARGE
-			 * OBJECT ... OWNER did not exist at all prior to PostgreSQL 9.0.
-			 *
-			 * We must be the owner of the existing object.
-			 */
-			if (!pg_largeobject_ownercheck(loid, GetUserId()))
-				ereport(ERROR,
-						(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
-						 errmsg("must be owner of large object %u", loid)));
-
-			/* Must be able to become new owner */
-			check_is_member_of_role(GetUserId(), newOwnerId);
-		}
-
-		memset(values, 0, sizeof(values));
-		memset(nulls, false, sizeof(nulls));
-		memset(replaces, false, sizeof(nulls));
-
-		values[Anum_pg_largeobject_metadata_lomowner - 1]
-			= ObjectIdGetDatum(newOwnerId);
-		replaces[Anum_pg_largeobject_metadata_lomowner - 1] = true;
-
-		/*
-		 * Determine the modified ACL for the new owner. This is only
-		 * necessary when the ACL is non-null.
-		 */
-		aclDatum = heap_getattr(oldtup,
-								Anum_pg_largeobject_metadata_lomacl,
-								RelationGetDescr(pg_lo_meta), &isnull);
-		if (!isnull)
-		{
-			newAcl = aclnewowner(DatumGetAclP(aclDatum),
-								 form_lo_meta->lomowner, newOwnerId);
-			values[Anum_pg_largeobject_metadata_lomacl - 1]
-				= PointerGetDatum(newAcl);
-			replaces[Anum_pg_largeobject_metadata_lomacl - 1] = true;
-		}
-
-		newtup = heap_modify_tuple(oldtup, RelationGetDescr(pg_lo_meta),
-								   values, nulls, replaces);
-
-		simple_heap_update(pg_lo_meta, &newtup->t_self, newtup);
-		CatalogUpdateIndexes(pg_lo_meta, newtup);
-
-		heap_freetuple(newtup);
-
-		/* Update owner dependency reference */
-		changeDependencyOnOwner(LargeObjectRelationId,
-								loid, newOwnerId);
-	}
-	systable_endscan(scan);
-
-	heap_close(pg_lo_meta, RowExclusiveLock);
-}
-
-/*
  * LargeObjectExists
  *
  * We don't use the system cache for large object metadata, for fear of

File src/backend/catalog/pg_shdepend.c

 #include "catalog/pg_foreign_server.h"
 #include "catalog/pg_language.h"
 #include "catalog/pg_largeobject.h"
+#include "catalog/pg_largeobject_metadata.h"
 #include "catalog/pg_namespace.h"
 #include "catalog/pg_operator.h"
 #include "catalog/pg_opclass.h"
 #include "catalog/pg_shdepend.h"
 #include "catalog/pg_tablespace.h"
 #include "catalog/pg_type.h"
+#include "commands/alter.h"
 #include "commands/dbcommands.h"
 #include "commands/collationcmds.h"
 #include "commands/conversioncmds.h"
 			/* Issue the appropriate ALTER OWNER call */
 			switch (sdepForm->classid)
 			{
-				case CollationRelationId:
-					AlterCollationOwner_oid(sdepForm->objid, newrole);
-					break;
-
-				case ConversionRelationId:
-					AlterConversionOwner_oid(sdepForm->objid, newrole);
-					break;
-
 				case TypeRelationId:
 					AlterTypeOwnerInternal(sdepForm->objid, newrole, true);
 					break;
 
-				case OperatorRelationId:
-					AlterOperatorOwner_oid(sdepForm->objid, newrole);
-					break;
-
 				case NamespaceRelationId:
 					AlterSchemaOwner_oid(sdepForm->objid, newrole);
 					break;
 					ATExecChangeOwner(sdepForm->objid, newrole, true, AccessExclusiveLock);
 					break;
 
-				case ProcedureRelationId:
-					AlterFunctionOwner_oid(sdepForm->objid, newrole);
-					break;
-
-				case LanguageRelationId:
-					AlterLanguageOwner_oid(sdepForm->objid, newrole);
-					break;
-
-				case LargeObjectRelationId:
-					LargeObjectAlterOwner(sdepForm->objid, newrole);
-					break;
-
 				case DefaultAclRelationId:
 
 					/*
 					 */
 					break;
 
-				case OperatorClassRelationId:
-					AlterOpClassOwner_oid(sdepForm->objid, newrole);
-					break;
-
-				case OperatorFamilyRelationId:
-					AlterOpFamilyOwner_oid(sdepForm->objid, newrole);
-					break;
-
 				case ForeignServerRelationId:
 					AlterForeignServerOwner_oid(sdepForm->objid, newrole);
 					break;
 					AlterForeignDataWrapperOwner_oid(sdepForm->objid, newrole);
 					break;
 
-				case ExtensionRelationId:
-					AlterExtensionOwner_oid(sdepForm->objid, newrole);
-					break;
-
 				case EventTriggerRelationId:
 					AlterEventTriggerOwner_oid(sdepForm->objid, newrole);
 					break;
 
+				/* Generic alter owner cases */
+				case CollationRelationId:
+				case ConversionRelationId:
+				case OperatorRelationId:
+				case ProcedureRelationId:
+				case LanguageRelationId:
+				case LargeObjectRelationId:
+				case OperatorFamilyRelationId:
+				case OperatorClassRelationId:
+				case ExtensionRelationId:
+					{
+						Oid			classId = sdepForm->classid;
+						Relation	catalog;
+
+						if (classId == LargeObjectRelationId)
+							classId = LargeObjectMetadataRelationId;
+
+						catalog = heap_open(classId, RowExclusiveLock);
+
+						AlterObjectOwner_internal(catalog, sdepForm->objid,
+												  newrole);
+
+						heap_close(catalog, NoLock);
+					}
+					break;
+
 				default:
 					elog(ERROR, "unexpected classid %u", sdepForm->classid);
 					break;

File src/backend/commands/aggregatecmds.c

 	heap_close(rel, NoLock);
 	heap_freetuple(tup);
 }
-
-/*
- * Change aggregate owner
- */
-void
-AlterAggregateOwner(List *name, List *args, Oid newOwnerId)
-{
-	Oid			procOid;
-
-	/* Look up function and make sure it's an aggregate */
-	procOid = LookupAggNameTypeNames(name, args, false);
-
-	/* The rest is just like a function */
-	AlterFunctionOwner_oid(procOid, newOwnerId);
-}

File src/backend/commands/alter.c

 #include "postgres.h"
 
 #include "access/htup_details.h"
+#include "access/sysattr.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
 #include "catalog/pg_largeobject.h"
+#include "catalog/pg_largeobject_metadata.h"
 #include "catalog/pg_namespace.h"
 #include "commands/alter.h"
 #include "commands/collationcmds.h"
 #include "miscadmin.h"
 #include "tcop/utility.h"
 #include "utils/builtins.h"
+#include "utils/fmgroids.h"
 #include "utils/lsyscache.h"
 #include "utils/rel.h"
 #include "utils/syscache.h"
+#include "utils/tqual.h"
 
 
 /*
 
 	switch (stmt->objectType)
 	{
-		case OBJECT_AGGREGATE:
-			AlterAggregateOwner(stmt->object, stmt->objarg, newowner);
-			break;
-
-		case OBJECT_COLLATION:
-			AlterCollationOwner(stmt->object, newowner);
-			break;
-
-		case OBJECT_CONVERSION:
-			AlterConversionOwner(stmt->object, newowner);
-			break;
-
 		case OBJECT_DATABASE:
 			AlterDatabaseOwner(strVal(linitial(stmt->object)), newowner);
 			break;
 
-		case OBJECT_FUNCTION:
-			AlterFunctionOwner(stmt->object, stmt->objarg, newowner);
-			break;
-
-		case OBJECT_LANGUAGE:
-			AlterLanguageOwner(strVal(linitial(stmt->object)), newowner);
-			break;
-
-		case OBJECT_LARGEOBJECT:
-			LargeObjectAlterOwner(oidparse(linitial(stmt->object)), newowner);
-			break;
-
-		case OBJECT_OPERATOR:
-			Assert(list_length(stmt->objarg) == 2);
-			AlterOperatorOwner(stmt->object,
-							   (TypeName *) linitial(stmt->objarg),
-							   (TypeName *) lsecond(stmt->objarg),
-							   newowner);
-			break;
-
-		case OBJECT_OPCLASS:
-			AlterOpClassOwner(stmt->object, stmt->addname, newowner);
-			break;
-
-		case OBJECT_OPFAMILY:
-			AlterOpFamilyOwner(stmt->object, stmt->addname, newowner);
-			break;
-
 		case OBJECT_SCHEMA:
 			AlterSchemaOwner(strVal(linitial(stmt->object)), newowner);
 			break;
 
-		case OBJECT_TABLESPACE:
-			AlterTableSpaceOwner(strVal(linitial(stmt->object)), newowner);
-			break;
-
 		case OBJECT_TYPE:
 		case OBJECT_DOMAIN:		/* same as TYPE */
 			AlterTypeOwner(stmt->object, newowner, stmt->objectType);
 			break;
 
-		case OBJECT_TSDICTIONARY:
-			AlterTSDictionaryOwner(stmt->object, newowner);
-			break;
-
-		case OBJECT_TSCONFIGURATION:
-			AlterTSConfigurationOwner(stmt->object, newowner);
-			break;
-
 		case OBJECT_FDW:
 			AlterForeignDataWrapperOwner(strVal(linitial(stmt->object)),
 										 newowner);
 			AlterEventTriggerOwner(strVal(linitial(stmt->object)), newowner);
 			break;
 
+		/* Generic cases */
+		case OBJECT_AGGREGATE:
+		case OBJECT_COLLATION:
+		case OBJECT_CONVERSION:
+		case OBJECT_FUNCTION:
+		case OBJECT_LANGUAGE:
+		case OBJECT_LARGEOBJECT:
+		case OBJECT_OPERATOR:
+		case OBJECT_OPCLASS:
+		case OBJECT_OPFAMILY:
+		case OBJECT_TABLESPACE:
+		case OBJECT_TSDICTIONARY:
+		case OBJECT_TSCONFIGURATION:
+			{
+				Relation	catalog;
+				Relation	relation;
+				Oid			classId;
+				ObjectAddress	address;
+
+				address = get_object_address(stmt->objectType,
+											 stmt->object,
+											 stmt->objarg,
+											 &relation,
+											 AccessExclusiveLock,
+											 false);
+				Assert(relation == NULL);
+				classId = address.classId;
+
+				/*
+				 * XXX - get_object_address returns Oid of pg_largeobject
+				 * catalog for OBJECT_LARGEOBJECT because of historical
+				 * reasons.  Fix up it here.
+				 */
+				if (classId == LargeObjectRelationId)
+					classId = LargeObjectMetadataRelationId;
+
+				catalog = heap_open(classId, RowExclusiveLock);
+
+				AlterObjectOwner_internal(catalog, address.objectId, newowner);
+				heap_close(catalog, RowExclusiveLock);
+			}
+			break;
+
 		default:
 			elog(ERROR, "unrecognized AlterOwnerStmt type: %d",
 				 (int) stmt->objectType);
 	}
 }
+
+/*
+ * Return a copy of the tuple for the object with the given object OID, from
+ * the given catalog (which must have been opened by the caller and suitably
+ * locked).  NULL is returned if the OID is not found.
+ *
+ * We try a syscache first, if available.
+ *
+ * XXX this function seems general in possible usage.  Given sufficient callers
+ * elsewhere, we should consider moving it to a more appropriate place.
+ */
+static HeapTuple
+get_catalog_object_by_oid(Relation catalog, Oid objectId)
+{
+	HeapTuple	tuple;
+	Oid			classId = RelationGetRelid(catalog);
+	int			oidCacheId = get_object_catcache_oid(classId);
+
+	if (oidCacheId > 0)
+	{
+		tuple = SearchSysCacheCopy1(oidCacheId, ObjectIdGetDatum(objectId));
+		if (!HeapTupleIsValid(tuple))  /* should not happen */
+			return NULL;
+	}
+	else
+	{
+		Oid			oidIndexId = get_object_oid_index(classId);
+		SysScanDesc	scan;
+		ScanKeyData	skey;
+
+		Assert(OidIsValid(oidIndexId));
+
+		ScanKeyInit(&skey,
+					ObjectIdAttributeNumber,
+					BTEqualStrategyNumber, F_OIDEQ,
+					ObjectIdGetDatum(objectId));
+
+		scan = systable_beginscan(catalog, oidIndexId, true,
+								  SnapshotNow, 1, &skey);
+		tuple = systable_getnext(scan);
+		if (!HeapTupleIsValid(tuple))
+		{
+			systable_endscan(scan);
+			return NULL;
+		}
+		tuple = heap_copytuple(tuple);
+
+		systable_endscan(scan);
+	}
+
+	return tuple;
+}
+
+/*
+ * Generic function to change the ownership of a given object, for simple
+ * cases (won't work for tables, nor other cases where we need to do more than
+ * change the ownership column of a single catalog entry).
+ *
+ * rel: catalog relation containing object (RowExclusiveLock'd by caller)
+ * objectId: OID of object to change the ownership of
+ * new_ownerId: OID of new object owner
+ */
+void
+AlterObjectOwner_internal(Relation rel, Oid objectId, Oid new_ownerId)
+{
+	Oid			classId = RelationGetRelid(rel);
+	AttrNumber	Anum_owner = get_object_attnum_owner(classId);
+	AttrNumber	Anum_namespace = get_object_attnum_namespace(classId);
+	AttrNumber	Anum_acl = get_object_attnum_acl(classId);
+	AttrNumber	Anum_name = get_object_attnum_name(classId);
+	HeapTuple	oldtup;
+	Datum		datum;
+	bool		isnull;
+	Oid			old_ownerId;
+	Oid			namespaceId = InvalidOid;
+
+	oldtup = get_catalog_object_by_oid(rel, objectId);
+	if (oldtup == NULL)
+		elog(ERROR, "cache lookup failed for object %u of catalog \"%s\"",
+			 objectId, RelationGetRelationName(rel));
+
+	datum = heap_getattr(oldtup, Anum_owner,
+						 RelationGetDescr(rel), &isnull);
+	Assert(!isnull);
+	old_ownerId = DatumGetObjectId(datum);
+
+	if (Anum_namespace != InvalidAttrNumber)
+	{
+		datum = heap_getattr(oldtup, Anum_namespace,
+							 RelationGetDescr(rel), &isnull);
+		Assert(!isnull);
+		namespaceId = DatumGetObjectId(datum);
+	}
+
+	if (old_ownerId != new_ownerId)
+	{
+		AttrNumber	nattrs;
+		HeapTuple	newtup;
+		Datum	   *values;
+		bool	   *nulls;
+		bool	   *replaces;
+
+		/* Superusers can bypass permission checks */
+		if (!superuser())
+		{
+			AclObjectKind	aclkind = get_object_aclkind(classId);
+
+			/* must be owner */
+			if (!has_privs_of_role(GetUserId(), old_ownerId))
+			{
+				char   *objname;
+				char	namebuf[NAMEDATALEN];
+
+				if (Anum_name != InvalidAttrNumber)
+				{
+					datum = heap_getattr(oldtup, Anum_name,
+										 RelationGetDescr(rel), &isnull);
+					Assert(!isnull);
+					objname = NameStr(*DatumGetName(datum));
+				}
+				else
+				{
+					snprintf(namebuf, sizeof(namebuf), "%u",
+							 HeapTupleGetOid(oldtup));
+					objname = namebuf;
+				}
+				aclcheck_error(ACLCHECK_NOT_OWNER, aclkind, objname);
+			}
+			/* Must be able to become new owner */
+			check_is_member_of_role(GetUserId(), new_ownerId);
+
+			/* New owner must have CREATE privilege on namespace */
+			if (OidIsValid(namespaceId))
+			{
+				AclResult   aclresult;
+
+				aclresult = pg_namespace_aclcheck(namespaceId, new_ownerId,
+												  ACL_CREATE);
+				if (aclresult != ACLCHECK_OK)
+					aclcheck_error(aclresult, aclkind,
+								   get_namespace_name(namespaceId));
+			}
+		}
+
+		/* Build a modified tuple */
+		nattrs = RelationGetNumberOfAttributes(rel);
+		values = palloc0(nattrs * sizeof(Datum));
+		nulls = palloc0(nattrs * sizeof(bool));
+		replaces = palloc0(nattrs * sizeof(bool));
+		values[Anum_owner - 1] = ObjectIdGetDatum(new_ownerId);
+		replaces[Anum_owner - 1] = true;
+
+		/*
+		 * Determine the modified ACL for the new owner.  This is only
+		 * necessary when the ACL is non-null.
+		 */
+		if (Anum_acl != InvalidAttrNumber)
+		{
+			datum = heap_getattr(oldtup,
+								 Anum_acl, RelationGetDescr(rel), &isnull);
+			if (!isnull)
+			{
+				Acl    *newAcl;
+
+				newAcl = aclnewowner(DatumGetAclP(datum),
+									 old_ownerId, new_ownerId);
+				values[Anum_acl - 1] = PointerGetDatum(newAcl);
+				replaces[Anum_acl - 1] = true;
+			}
+		}
+
+		newtup = heap_modify_tuple(oldtup, RelationGetDescr(rel),
+								   values, nulls, replaces);
+
+		/* Perform actual update */
+		simple_heap_update(rel, &newtup->t_self, newtup);
+		CatalogUpdateIndexes(rel, newtup);
+
+		/* Update owner dependency reference */
+		if (classId == LargeObjectMetadataRelationId)
+			classId = LargeObjectRelationId;
+		changeDependencyOnOwner(classId, HeapTupleGetOid(newtup), new_ownerId);
+
+		/* Release memory */
+		pfree(values);
+		pfree(nulls);
+		pfree(replaces);
+	}
+}

File src/backend/commands/collationcmds.c

 #include "utils/rel.h"
 #include "utils/syscache.h"
 
-static void AlterCollationOwner_internal(Relation rel, Oid collationOid,
-							 Oid newOwnerId);
-
 /*
  * CREATE COLLATION
  */
 }
 
 /*
- * Change collation owner, by name
- */
-void
-AlterCollationOwner(List *name, Oid newOwnerId)
-{
-	Oid			collationOid;
-	Relation	rel;
-
-	rel = heap_open(CollationRelationId, RowExclusiveLock);
-
-	collationOid = get_collation_oid(name, false);
-
-	AlterCollationOwner_internal(rel, collationOid, newOwnerId);
-
-	heap_close(rel, RowExclusiveLock);
-}
-
-/*
- * Change collation owner, by oid
- */
-void
-AlterCollationOwner_oid(Oid collationOid, Oid newOwnerId)
-{
-	Relation	rel;
-
-	rel = heap_open(CollationRelationId, RowExclusiveLock);
-
-	AlterCollationOwner_internal(rel, collationOid, newOwnerId);
-
-	heap_close(rel, RowExclusiveLock);
-}
-
-/*
- * AlterCollationOwner_internal
- *
- * Internal routine for changing the owner.  rel must be pg_collation, already
- * open and suitably locked; it will not be closed.
- */
-static void
-AlterCollationOwner_internal(Relation rel, Oid collationOid, Oid newOwnerId)
-{
-	Form_pg_collation collForm;
-	HeapTuple	tup;
-
-	Assert(RelationGetRelid(rel) == CollationRelationId);
-
-	tup = SearchSysCacheCopy1(COLLOID, ObjectIdGetDatum(collationOid));
-	if (!HeapTupleIsValid(tup)) /* should not happen */
-		elog(ERROR, "cache lookup failed for collation %u", collationOid);
-
-	collForm = (Form_pg_collation) 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 (collForm->collowner != newOwnerId)
-	{
-		AclResult	aclresult;
-
-		/* Superusers can always do it */
-		if (!superuser())
-		{
-			/* Otherwise, must be owner of the existing object */
-			if (!pg_collation_ownercheck(HeapTupleGetOid(tup), GetUserId()))
-				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_COLLATION,
-							   NameStr(collForm->collname));
-
-			/* Must be able to become new owner */
-			check_is_member_of_role(GetUserId(), newOwnerId);
-
-			/* New owner must have CREATE privilege on namespace */
-			aclresult = pg_namespace_aclcheck(collForm->collnamespace,
-											  newOwnerId,
-											  ACL_CREATE);
-			if (aclresult != ACLCHECK_OK)
-				aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
-							   get_namespace_name(collForm->collnamespace));
-		}
-
-		/*
-		 * Modify the owner --- okay to scribble on tup because it's a copy
-		 */
-		collForm->collowner = newOwnerId;
-
-		simple_heap_update(rel, &tup->t_self, tup);
-
-		CatalogUpdateIndexes(rel, tup);
-
-		/* Update owner dependency reference */
-		changeDependencyOnOwner(CollationRelationId, collationOid,
-								newOwnerId);
-	}
-
-	heap_freetuple(tup);
-}
-
-/*
  * Execute ALTER COLLATION SET SCHEMA
  */
 void

File src/backend/commands/conversioncmds.c

 #include "utils/rel.h"
 #include "utils/syscache.h"
 
-static void AlterConversionOwner_internal(Relation rel, Oid conversionOid,
-							  Oid newOwnerId);
-
 /*
  * CREATE CONVERSION
  */
 	heap_close(rel, NoLock);
 	heap_freetuple(tup);
 }
-
-/*
- * Change conversion owner, by name
- */
-void
-AlterConversionOwner(List *name, Oid newOwnerId)
-{
-	Oid			conversionOid;
-	Relation	rel;
-
-	rel = heap_open(ConversionRelationId, RowExclusiveLock);
-
-	conversionOid = get_conversion_oid(name, false);
-
-	AlterConversionOwner_internal(rel, conversionOid, newOwnerId);
-
-	heap_close(rel, NoLock);
-}
-
-/*
- * Change conversion owner, by oid
- */
-void
-AlterConversionOwner_oid(Oid conversionOid, Oid newOwnerId)
-{
-	Relation	rel;
-
-	rel = heap_open(ConversionRelationId, RowExclusiveLock);
-
-	AlterConversionOwner_internal(rel, conversionOid, newOwnerId);
-
-	heap_close(rel, NoLock);
-}
-
-/*
- * AlterConversionOwner_internal
- *
- * Internal routine for changing the owner.  rel must be pg_conversion, already
- * open and suitably locked; it will not be closed.
- */
-static void
-AlterConversionOwner_internal(Relation rel, Oid conversionOid, Oid newOwnerId)
-{
-	Form_pg_conversion convForm;
-	HeapTuple	tup;
-
-	Assert(RelationGetRelid(rel) == ConversionRelationId);
-
-	tup = SearchSysCacheCopy1(CONVOID, ObjectIdGetDatum(conversionOid));
-	if (!HeapTupleIsValid(tup)) /* should not happen */
-		elog(ERROR, "cache lookup failed for conversion %u", conversionOid);
-
-	convForm = (Form_pg_conversion) 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 (convForm->conowner != newOwnerId)
-	{
-		AclResult	aclresult;
-
-		/* Superusers can always do it */
-		if (!superuser())
-		{
-			/* Otherwise, must be owner of the existing object */
-			if (!pg_conversion_ownercheck(HeapTupleGetOid(tup), GetUserId()))
-				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION,
-							   NameStr(convForm->conname));
-
-			/* Must be able to become new owner */
-			check_is_member_of_role(GetUserId(), newOwnerId);
-
-			/* New owner must have CREATE privilege on namespace */
-			aclresult = pg_namespace_aclcheck(convForm->connamespace,
-											  newOwnerId,
-											  ACL_CREATE);
-			if (aclresult != ACLCHECK_OK)
-				aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
-							   get_namespace_name(convForm->connamespace));
-		}
-
-		/*
-		 * Modify the owner --- okay to scribble on tup because it's a copy
-		 */
-		convForm->conowner = newOwnerId;
-
-		simple_heap_update(rel, &tup->t_self, tup);
-
-		CatalogUpdateIndexes(rel, tup);
-
-		/* Update owner dependency reference */
-		changeDependencyOnOwner(ConversionRelationId, conversionOid,
-								newOwnerId);
-	}
-
-	heap_freetuple(tup);
-}

File src/backend/commands/extension.c

 	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);
-}

File src/backend/commands/functioncmds.c

 #include "utils/syscache.h"
 #include "utils/tqual.h"
 
-
-static void AlterFunctionOwner_internal(Relation rel, HeapTuple tup,
-							Oid newOwnerId);
-
-
 /*
  *	 Examine the RETURNS clause of the CREATE FUNCTION statement
  *	 and return information about it as *prorettype_p and *returnsSet.
 }
 
 /*
- * Change function owner by name and args
- */
-void
-AlterFunctionOwner(List *name, List *argtypes, Oid newOwnerId)
-{
-	Relation	rel;
-	Oid			procOid;
-	HeapTuple	tup;
-
-	rel = heap_open(ProcedureRelationId, RowExclusiveLock);
-
-	procOid = LookupFuncNameTypeNames(name, argtypes, false);
-
-	tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(procOid));
-	if (!HeapTupleIsValid(tup)) /* should not happen */
-		elog(ERROR, "cache lookup failed for function %u", procOid);
-
-	if (((Form_pg_proc) GETSTRUCT(tup))->proisagg)
-		ereport(ERROR,
-				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
-				 errmsg("\"%s\" is an aggregate function",
-						NameListToString(name)),
-				 errhint("Use ALTER AGGREGATE to change owner of aggregate functions.")));
-
-	AlterFunctionOwner_internal(rel, tup, newOwnerId);
-
-	heap_close(rel, NoLock);
-}
-
-/*
- * Change function owner by Oid
- */
-void
-AlterFunctionOwner_oid(Oid procOid, Oid newOwnerId)
-{
-	Relation	rel;
-	HeapTuple	tup;
-
-	rel = heap_open(ProcedureRelationId, RowExclusiveLock);
-
-	tup = SearchSysCache1(PROCOID, ObjectIdGetDatum(procOid));
-	if (!HeapTupleIsValid(tup)) /* should not happen */
-		elog(ERROR, "cache lookup failed for function %u", procOid);
-	AlterFunctionOwner_internal(rel, tup, newOwnerId);
-
-	heap_close(rel, NoLock);
-}
-
-static void
-AlterFunctionOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
-{
-	Form_pg_proc procForm;
-	AclResult	aclresult;
-	Oid			procOid;
-
-	Assert(RelationGetRelid(rel) == ProcedureRelationId);
-	Assert(tup->t_tableOid == ProcedureRelationId);
-
-	procForm = (Form_pg_proc) GETSTRUCT(tup);
-	procOid = HeapTupleGetOid(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 (procForm->proowner != newOwnerId)
-	{
-		Datum		repl_val[Natts_pg_proc];
-		bool		repl_null[Natts_pg_proc];
-		bool		repl_repl[Natts_pg_proc];
-		Acl		   *newAcl;
-		Datum		aclDatum;
-		bool		isNull;
-		HeapTuple	newtuple;
-
-		/* Superusers can always do it */
-		if (!superuser())
-		{
-			/* Otherwise, must be owner of the existing object */
-			if (!pg_proc_ownercheck(procOid, GetUserId()))
-				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
-							   NameStr(procForm->proname));
-
-			/* Must be able to become new owner */
-			check_is_member_of_role(GetUserId(), newOwnerId);
-
-			/* New owner must have CREATE privilege on namespace */
-			aclresult = pg_namespace_aclcheck(procForm->pronamespace,
-											  newOwnerId,
-											  ACL_CREATE);
-			if (aclresult != ACLCHECK_OK)
-				aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
-							   get_namespace_name(procForm->pronamespace));
-		}
-
-		memset(repl_null, false, sizeof(repl_null));
-		memset(repl_repl, false, sizeof(repl_repl));
-
-		repl_repl[Anum_pg_proc_proowner - 1] = true;
-		repl_val[Anum_pg_proc_proowner - 1] = ObjectIdGetDatum(newOwnerId);
-
-		/*
-		 * Determine the modified ACL for the new owner.  This is only
-		 * necessary when the ACL is non-null.
-		 */
-		aclDatum = SysCacheGetAttr(PROCOID, tup,
-								   Anum_pg_proc_proacl,
-								   &isNull);
-		if (!isNull)
-		{
-			newAcl = aclnewowner(DatumGetAclP(aclDatum),
-								 procForm->proowner, newOwnerId);
-			repl_repl[Anum_pg_proc_proacl - 1] = true;
-			repl_val[Anum_pg_proc_proacl - 1] = PointerGetDatum(newAcl);
-		}
-
-		newtuple = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val,
-									 repl_null, repl_repl);
-
-		simple_heap_update(rel, &newtuple->t_self, newtuple);
-		CatalogUpdateIndexes(rel, newtuple);
-
-		heap_freetuple(newtuple);
-
-		/* Update owner dependency reference */
-		changeDependencyOnOwner(ProcedureRelationId, procOid, newOwnerId);
-	}
-
-	ReleaseSysCache(tup);
-}
-
-/*
  * Implements the ALTER FUNCTION utility command (except for the
  * RENAME and OWNER clauses, which are handled as part of the generic
  * ALTER framework).

File src/backend/commands/opclasscmds.c

 			  List *operators);
 static void dropProcedures(List *opfamilyname, Oid amoid, Oid opfamilyoid,
 			   List *procedures);
-static void AlterOpClassOwner_internal(Relation rel, HeapTuple tuple,
-						   Oid newOwnerId);
-static void AlterOpFamilyOwner_internal(Relation rel, HeapTuple tuple,
-							Oid newOwnerId);
-
 
 /*
  * OpFamilyCacheLookup
 }
 
 /*
- * Change opclass owner by name
- */
-void
-AlterOpClassOwner(List *name, const char *access_method, Oid newOwnerId)
-{
-	Oid			amOid;
-	Relation	rel;
-	HeapTuple	tup;
-	HeapTuple	origtup;
-
-	amOid = get_am_oid(access_method, false);
-
-	rel = heap_open(OperatorClassRelationId, RowExclusiveLock);
-
-	/* Look up the opclass. */
-	origtup = OpClassCacheLookup(amOid, name, false);
-	tup = heap_copytuple(origtup);
-	ReleaseSysCache(origtup);
-
-	AlterOpClassOwner_internal(rel, tup, newOwnerId);
-
-	heap_freetuple(tup);
-	heap_close(rel, NoLock);
-}
-
-/*
- * Change operator class owner, specified by OID
- */
-void
-AlterOpClassOwner_oid(Oid opclassOid, Oid newOwnerId)
-{
-	HeapTuple	tup;
-	Relation	rel;
-
-	rel = heap_open(OperatorClassRelationId, RowExclusiveLock);
-
-	tup = SearchSysCacheCopy1(CLAOID, ObjectIdGetDatum(opclassOid));
-	if (!HeapTupleIsValid(tup))
-		elog(ERROR, "cache lookup failed for opclass %u", opclassOid);
-
-	AlterOpClassOwner_internal(rel, tup, newOwnerId);
-
-	heap_freetuple(tup);
-	heap_close(rel, NoLock);
-}
-
-/*
- * The first parameter is pg_opclass, opened and suitably locked.  The second
- * parameter is a copy of the tuple from pg_opclass we want to modify.
- */
-static void
-AlterOpClassOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
-{
-	Oid			namespaceOid;
-	AclResult	aclresult;
-	Form_pg_opclass opcForm;
-
-	Assert(tup->t_tableOid == OperatorClassRelationId);
-	Assert(RelationGetRelid(rel) == OperatorClassRelationId);
-
-	opcForm = (Form_pg_opclass) GETSTRUCT(tup);
-
-	namespaceOid = opcForm->opcnamespace;
-
-	/*
-	 * If the new owner is the same as the existing owner, consider the
-	 * command to have succeeded.  This is for dump restoration purposes.
-	 */
-	if (opcForm->opcowner != newOwnerId)
-	{
-		/* Superusers can always do it */
-		if (!superuser())
-		{
-			/* Otherwise, must be owner of the existing object */
-			if (!pg_opclass_ownercheck(HeapTupleGetOid(tup), GetUserId()))
-				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPCLASS,
-							   NameStr(opcForm->opcname));
-
-			/* Must be able to become new owner */
-			check_is_member_of_role(GetUserId(), newOwnerId);
-
-			/* New owner must have CREATE privilege on namespace */
-			aclresult = pg_namespace_aclcheck(namespaceOid, newOwnerId,
-											  ACL_CREATE);
-			if (aclresult != ACLCHECK_OK)
-				aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
-							   get_namespace_name(namespaceOid));
-		}
-
-		/*
-		 * Modify the owner --- okay to scribble on tup because it's a copy
-		 */
-		opcForm->opcowner = newOwnerId;
-
-		simple_heap_update(rel, &tup->t_self, tup);
-
-		CatalogUpdateIndexes(rel, tup);
-
-		/* Update owner dependency reference */
-		changeDependencyOnOwner(OperatorClassRelationId, HeapTupleGetOid(tup),
-								newOwnerId);
-	}
-}
-
-/*
- * Change opfamily owner by name
- */
-void
-AlterOpFamilyOwner(List *name, const char *access_method, Oid newOwnerId)
-{
-	Oid			amOid;
-	Relation	rel;
-	HeapTuple	tup;
-	char	   *opfname;
-	char	   *schemaname;
-
-	amOid = get_am_oid(access_method, false);
-
-	rel = heap_open(OperatorFamilyRelationId, RowExclusiveLock);
-
-	/*
-	 * Look up the opfamily
-	 */
-	DeconstructQualifiedName(name, &schemaname, &opfname);
-
-	if (schemaname)
-	{
-		Oid			namespaceOid;
-
-		namespaceOid = LookupExplicitNamespace(schemaname);
-
-		tup = SearchSysCacheCopy3(OPFAMILYAMNAMENSP,
-								  ObjectIdGetDatum(amOid),
-								  PointerGetDatum(opfname),
-								  ObjectIdGetDatum(namespaceOid));
-		if (!HeapTupleIsValid(tup))
-			ereport(ERROR,
-					(errcode(ERRCODE_UNDEFINED_OBJECT),
-					 errmsg("operator family \"%s\" does not exist for access method \"%s\"",
-							opfname, access_method)));
-	}
-	else
-	{
-		Oid			opfOid;
-
-		opfOid = OpfamilynameGetOpfid(amOid, opfname);
-		if (!OidIsValid(opfOid))
-			ereport(ERROR,
-					(errcode(ERRCODE_UNDEFINED_OBJECT),
-					 errmsg("operator family \"%s\" does not exist for access method \"%s\"",
-							opfname, access_method)));
-
-		tup = SearchSysCacheCopy1(OPFAMILYOID, ObjectIdGetDatum(opfOid));
-		if (!HeapTupleIsValid(tup))		/* should not happen */
-			elog(ERROR, "cache lookup failed for opfamily %u", opfOid);
-	}
-
-	AlterOpFamilyOwner_internal(rel, tup, newOwnerId);
-
-	heap_freetuple(tup);
-	heap_close(rel, NoLock);
-}
-
-/*
- * Change operator family owner, specified by OID
- */
-void
-AlterOpFamilyOwner_oid(Oid opfamilyOid, Oid newOwnerId)
-{
-	HeapTuple	tup;
-	Relation	rel;
-
-	rel = heap_open(OperatorFamilyRelationId, RowExclusiveLock);
-
-	tup = SearchSysCacheCopy1(OPFAMILYOID, ObjectIdGetDatum(opfamilyOid));
-	if (!HeapTupleIsValid(tup))
-		elog(ERROR, "cache lookup failed for opfamily %u", opfamilyOid);
-
-	AlterOpFamilyOwner_internal(rel, tup, newOwnerId);
-
-	heap_freetuple(tup);
-	heap_close(rel, NoLock);
-}
-
-/*
- * The first parameter is pg_opfamily, opened and suitably locked.	The second
- * parameter is a copy of the tuple from pg_opfamily we want to modify.
- */
-static void
-AlterOpFamilyOwner_internal(Relation rel, HeapTuple tup, Oid newOwnerId)
-{
-	Oid			namespaceOid;
-	AclResult	aclresult;
-	Form_pg_opfamily opfForm;
-
-	Assert(tup->t_tableOid == OperatorFamilyRelationId);
-	Assert(RelationGetRelid(rel) == OperatorFamilyRelationId);
-
-	opfForm = (Form_pg_opfamily) GETSTRUCT(tup);
-
-	namespaceOid = opfForm->opfnamespace;
-
-	/*
-	 * If the new owner is the same as the existing owner, consider the
-	 * command to have succeeded.  This is for dump restoration purposes.
-	 */
-	if (opfForm->opfowner != newOwnerId)
-	{
-		/* Superusers can always do it */
-		if (!superuser())
-		{
-			/* Otherwise, must be owner of the existing object */
-			if (!pg_opfamily_ownercheck(HeapTupleGetOid(tup), GetUserId()))
-				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPFAMILY,
-							   NameStr(opfForm->opfname));
-
-			/* Must be able to become new owner */
-			check_is_member_of_role(GetUserId(), newOwnerId);
-
-			/* New owner must have CREATE privilege on namespace */
-			aclresult = pg_namespace_aclcheck(namespaceOid, newOwnerId,
-											  ACL_CREATE);
-			if (aclresult != ACLCHECK_OK)
-				aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
-							   get_namespace_name(namespaceOid));
-		}
-
-		/*
-		 * Modify the owner --- okay to scribble on tup because it's a copy
-		 */
-		opfForm->opfowner = newOwnerId;
-
-		simple_heap_update(rel, &tup->t_self, tup);
-
-		CatalogUpdateIndexes(rel, tup);
-
-		/* Update owner dependency reference */
-		changeDependencyOnOwner(OperatorFamilyRelationId, HeapTupleGetOid(tup),
-								newOwnerId);
-	}
-}
-
-/*
  * get_am_oid - given an access method name, look up the OID
  *
  * If missing_ok is false, throw an error if access method not found.  If

File src/backend/commands/operatorcmds.c

 #include "utils/rel.h"
 #include "utils/syscache.h"
 
-
-static void AlterOperatorOwner_internal(Relation rel, Oid operOid, Oid newOwnerId);
-
 /*
  * DefineOperator
  *		this function extracts all the information from the
 
 	heap_close(relation, RowExclusiveLock);
 }
-
-void
-AlterOperatorOwner_oid(Oid operOid, Oid newOwnerId)
-{
-	Relation	rel;
-
-	rel = heap_open(OperatorRelationId, RowExclusiveLock);
-
-	AlterOperatorOwner_internal(rel, operOid, newOwnerId);
-
-	heap_close(rel, NoLock);
-}
-
-/*
- * change operator owner
- */
-void
-AlterOperatorOwner(List *name, TypeName *typeName1, TypeName *typeName2,
-				   Oid newOwnerId)
-{
-	Oid			operOid;
-	Relation	rel;
-
-	rel = heap_open(OperatorRelationId, RowExclusiveLock);
-
-	operOid = LookupOperNameTypeNames(NULL, name,
-									  typeName1, typeName2,
-									  false, -1);
-
-	AlterOperatorOwner_internal(rel, operOid, newOwnerId);
-
-	heap_close(rel, NoLock);
-}
-
-static void
-AlterOperatorOwner_internal(Relation rel, Oid operOid, Oid newOwnerId)
-{
-	HeapTuple	tup;
-	AclResult	aclresult;
-	Form_pg_operator oprForm;
-
-	Assert(RelationGetRelid(rel) == OperatorRelationId);
-
-	tup = SearchSysCacheCopy1(OPEROID, ObjectIdGetDatum(operOid));
-	if (!HeapTupleIsValid(tup)) /* should not happen */
-		elog(ERROR, "cache lookup failed for operator %u", operOid);
-
-	oprForm = (Form_pg_operator) 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 (oprForm->oprowner != newOwnerId)
-	{
-		/* Superusers can always do it */
-		if (!superuser())
-		{
-			/* Otherwise, must be owner of the existing object */
-			if (!pg_oper_ownercheck(operOid, GetUserId()))
-				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPER,
-							   NameStr(oprForm->oprname));
-
-			/* Must be able to become new owner */
-			check_is_member_of_role(GetUserId(), newOwnerId);
-
-			/* New owner must have CREATE privilege on namespace */
-			aclresult = pg_namespace_aclcheck(oprForm->oprnamespace,
-											  newOwnerId,
-											  ACL_CREATE);
-			if (aclresult != ACLCHECK_OK)
-				aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
-							   get_namespace_name(oprForm->oprnamespace));
-		}
-
-		/*
-		 * Modify the owner --- okay to scribble on tup because it's a copy
-		 */
-		oprForm->oprowner = newOwnerId;
-
-		simple_heap_update(rel, &tup->t_self, tup);
-
-		CatalogUpdateIndexes(rel, tup);
-
-		/* Update owner dependency reference */
-		changeDependencyOnOwner(OperatorRelationId, operOid, newOwnerId);
-	}
-
-	heap_freetuple(tup);
-}

File src/backend/commands/proclang.c

 				 Oid languageOwner, Oid handlerOid, Oid inlineOid,
 				 Oid valOid, bool trusted);
 static PLTemplate *find_language_template(const char *languageName);
-static void AlterLanguageOwner_internal(HeapTuple tup, Relation rel,
-							Oid newOwnerId);
-
 
 /* ---------------------------------------------------------------------
  * CREATE PROCEDURAL LANGUAGE
 }
 
 /*
- * Change language owner
- */
-void
-AlterLanguageOwner(const char *name, Oid newOwnerId)
-{
-	HeapTuple	tup;
-	Relation	rel;
-
-	rel = heap_open(LanguageRelationId, RowExclusiveLock);
-
-	tup = SearchSysCache1(LANGNAME, CStringGetDatum(name));
-	if (!HeapTupleIsValid(tup))
-		ereport(ERROR,
-				(errcode(ERRCODE_UNDEFINED_OBJECT),
-				 errmsg("language \"%s\" does not exist", name)));
-
-	AlterLanguageOwner_internal(tup, rel, newOwnerId);
-
-	ReleaseSysCache(tup);
-
-	heap_close(rel, RowExclusiveLock);
-
-}
-
-/*
- * Change language owner, specified by OID
- */
-void
-AlterLanguageOwner_oid(Oid oid, Oid newOwnerId)
-{
-	HeapTuple	tup;
-	Relation	rel;
-
-	rel = heap_open(LanguageRelationId, RowExclusiveLock);
-
-	tup = SearchSysCache1(LANGOID, ObjectIdGetDatum(oid));
-	if (!HeapTupleIsValid(tup))
-		elog(ERROR, "cache lookup failed for language %u", oid);
-
-	AlterLanguageOwner_internal(tup, rel, newOwnerId);
-
-	ReleaseSysCache(tup);
-
-	heap_close(rel, RowExclusiveLock);
-}
-
-/*
- * Workhorse for AlterLanguageOwner variants
- */
-static void
-AlterLanguageOwner_internal(HeapTuple tup, Relation rel, Oid newOwnerId)
-{
-	Form_pg_language lanForm;
-
-	lanForm = (Form_pg_language) 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 (lanForm->lanowner != newOwnerId)
-	{
-		Datum		repl_val[Natts_pg_language];
-		bool		repl_null[Natts_pg_language];
-		bool		repl_repl[Natts_pg_language];
-		Acl		   *newAcl;
-		Datum		aclDatum;
-		bool		isNull;
-		HeapTuple	newtuple;
-
-		/* Otherwise, must be owner of the existing object */
-		if (!pg_language_ownercheck(HeapTupleGetOid(tup), GetUserId()))
-			aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_LANGUAGE,
-						   NameStr(lanForm->lanname));
-
-		/* Must be able to become new owner */
-		check_is_member_of_role(GetUserId(), newOwnerId);
-
-		memset(repl_null, false, sizeof(repl_null));
-		memset(repl_repl, false, sizeof(repl_repl));
-
-		repl_repl[Anum_pg_language_lanowner - 1] = true;
-		repl_val[Anum_pg_language_lanowner - 1] = ObjectIdGetDatum(newOwnerId);
-
-		/*
-		 * Determine the modified ACL for the new owner.  This is only
-		 * necessary when the ACL is non-null.
-		 */
-		aclDatum = SysCacheGetAttr(LANGNAME, tup,
-								   Anum_pg_language_lanacl,
-								   &isNull);
-		if (!isNull)
-		{
-			newAcl = aclnewowner(DatumGetAclP(aclDatum),
-								 lanForm->lanowner, newOwnerId);
-			repl_repl[Anum_pg_language_lanacl - 1] = true;
-			repl_val[Anum_pg_language_lanacl - 1] = PointerGetDatum(newAcl);
-		}
-
-		newtuple = heap_modify_tuple(tup, RelationGetDescr(rel),
-									 repl_val, repl_null, repl_repl);
-
-		simple_heap_update(rel, &newtuple->t_self, newtuple);
-		CatalogUpdateIndexes(rel, newtuple);
-
-		heap_freetuple(newtuple);
-
-		/* Update owner dependency reference */
-		changeDependencyOnOwner(LanguageRelationId, HeapTupleGetOid(tup),
-								newOwnerId);
-	}
-}
-
-/*
  * get_language_oid - given a language name, look up the OID
  *
  * If missing_ok is false, throw an error if language name not found.  If

File src/backend/commands/tablespace.c

 }
 
 /*
- * Change tablespace owner
- */
-void
-AlterTableSpaceOwner(const char *name, Oid newOwnerId)
-{
-	Relation	rel;
-	ScanKeyData entry[1];
-	HeapScanDesc scandesc;
-	Form_pg_tablespace spcForm;
-	HeapTuple	tup;
-
-	/* Search pg_tablespace */
-	rel = heap_open(TableSpaceRelationId, RowExclusiveLock);
-
-	ScanKeyInit(&entry[0],
-				Anum_pg_tablespace_spcname,
-				BTEqualStrategyNumber, F_NAMEEQ,
-				CStringGetDatum(name));
-	scandesc = heap_beginscan(rel, SnapshotNow, 1, entry);
-	tup = heap_getnext(scandesc, ForwardScanDirection);
-	if (!HeapTupleIsValid(tup))
-		ereport(ERROR,
-				(errcode(ERRCODE_UNDEFINED_OBJECT),
-				 errmsg("tablespace \"%s\" does not exist", name)));
-
-	spcForm = (Form_pg_tablespace) 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 (spcForm->spcowner != newOwnerId)
-	{
-		Datum		repl_val[Natts_pg_tablespace];
-		bool		repl_null[Natts_pg_tablespace];
-		bool		repl_repl[Natts_pg_tablespace];
-		Acl		   *newAcl;
-		Datum		aclDatum;
-		bool		isNull;
-		HeapTuple	newtuple;
-
-		/* Otherwise, must be owner of the existing object */
-		if (!pg_tablespace_ownercheck(HeapTupleGetOid(tup), GetUserId()))
-			aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TABLESPACE,
-						   name);
-
-		/* Must be able to become new owner */
-		check_is_member_of_role(GetUserId(), newOwnerId);
-
-		/*
-		 * Normally we would also check for create permissions here, but there
-		 * are none for tablespaces so we follow what rename tablespace does
-		 * and omit the create permissions check.
-		 *
-		 * NOTE: Only superusers may create tablespaces to begin with and so
-		 * initially only a superuser would be able to change its ownership
-		 * anyway.
-		 */
-
-		memset(repl_null, false, sizeof(repl_null));
-		memset(repl_repl, false, sizeof(repl_repl));
-
-		repl_repl[Anum_pg_tablespace_spcowner - 1] = true;
-		repl_val[Anum_pg_tablespace_spcowner - 1] = ObjectIdGetDatum(newOwnerId);
-
-		/*
-		 * Determine the modified ACL for the new owner.  This is only
-		 * necessary when the ACL is non-null.
-		 */
-		aclDatum = heap_getattr(tup,
-								Anum_pg_tablespace_spcacl,
-								RelationGetDescr(rel),
-								&isNull);
-		if (!isNull)
-		{
-			newAcl = aclnewowner(DatumGetAclP(aclDatum),
-								 spcForm->spcowner, newOwnerId);
-			repl_repl[Anum_pg_tablespace_spcacl - 1] = true;
-			repl_val[Anum_pg_tablespace_spcacl - 1] = PointerGetDatum(newAcl);
-		}
-
-		newtuple = heap_modify_tuple(tup, RelationGetDescr(rel), repl_val, repl_null, repl_repl);
-
-		simple_heap_update(rel, &newtuple->t_self, newtuple);
-		CatalogUpdateIndexes(rel, newtuple);
-
-		heap_freetuple(newtuple);
-
-		/* Update owner dependency reference */
-		changeDependencyOnOwner(TableSpaceRelationId, HeapTupleGetOid(tup),
-								newOwnerId);
-	}
-
-	heap_endscan(scandesc);
-	heap_close(rel, NoLock);
-}
-
-
-/*
  * Alter table space options
  */
 void

File src/backend/commands/tsearchcmds.c

 	heap_close(rel, RowExclusiveLock);
 }
 
-/*
- * ALTER TEXT SEARCH DICTIONARY OWNER
- */
-void
-AlterTSDictionaryOwner(List *name, Oid newOwnerId)
-{
-	HeapTuple	tup;
-	Relation	rel;
-	Oid			dictId;
-	Oid			namespaceOid;
-	AclResult	aclresult;
-	Form_pg_ts_dict form;
-
-	rel = heap_open(TSDictionaryRelationId, RowExclusiveLock);
-
-	dictId = get_ts_dict_oid(name, false);
-
-	tup = SearchSysCacheCopy1(TSDICTOID, ObjectIdGetDatum(dictId));
-
-	if (!HeapTupleIsValid(tup)) /* should not happen */
-		elog(ERROR, "cache lookup failed for text search dictionary %u",
-			 dictId);
-
-	form = (Form_pg_ts_dict) GETSTRUCT(tup);
-	namespaceOid = form->dictnamespace;
-
-	if (form->dictowner != newOwnerId)
-	{
-		/* Superusers can always do it */
-		if (!superuser())
-		{
-			/* must be owner */
-			if (!pg_ts_dict_ownercheck(dictId, GetUserId()))
-				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSDICTIONARY,
-							   NameListToString(name));
-
-			/* Must be able to become new owner */
-			check_is_member_of_role(GetUserId(), newOwnerId);
-
-			/* New owner must have CREATE privilege on namespace */
-			aclresult = pg_namespace_aclcheck(namespaceOid, newOwnerId, ACL_CREATE);
-			if (aclresult != ACLCHECK_OK)
-				aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
-							   get_namespace_name(namespaceOid));
-		}
-
-		form->dictowner = newOwnerId;
-
-		simple_heap_update(rel, &tup->t_self, tup);
-		CatalogUpdateIndexes(rel, tup);
-
-		/* Update owner dependency reference */
-		changeDependencyOnOwner(TSDictionaryRelationId, HeapTupleGetOid(tup),
-								newOwnerId);
-	}
-
-	heap_close(rel, NoLock);
-	heap_freetuple(tup);
-}
-
 /* ---------------------- TS Template commands -----------------------*/
 
 /*
 }
 
 /*
- * ALTER TEXT SEARCH CONFIGURATION OWNER
- */
-void
-AlterTSConfigurationOwner(List *name, Oid newOwnerId)
-{
-	HeapTuple	tup;
-	Relation	rel;
-	Oid			cfgId;
-	AclResult	aclresult;
-	Oid			namespaceOid;
-	Form_pg_ts_config form;
-
-	rel = heap_open(TSConfigRelationId, RowExclusiveLock);
-
-	cfgId = get_ts_config_oid(name, false);
-
-	tup = SearchSysCacheCopy1(TSCONFIGOID, ObjectIdGetDatum(cfgId));
-
-	if (!HeapTupleIsValid(tup)) /* should not happen */
-		elog(ERROR, "cache lookup failed for text search configuration %u",
-			 cfgId);
-
-	form = (Form_pg_ts_config) GETSTRUCT(tup);
-	namespaceOid = form->cfgnamespace;
-
-	if (form->cfgowner != newOwnerId)
-	{
-		/* Superusers can always do it */
-		if (!superuser())
-		{
-			/* must be owner */
-			if (!pg_ts_config_ownercheck(cfgId, GetUserId()))
-				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSCONFIGURATION,
-							   NameListToString(name));
-
-			/* Must be able to become new owner */
-			check_is_member_of_role(GetUserId(), newOwnerId);
-
-			/* New owner must have CREATE privilege on namespace */
-			aclresult = pg_namespace_aclcheck(namespaceOid, newOwnerId, ACL_CREATE);
-			if (aclresult != ACLCHECK_OK)
-				aclcheck_error(aclresult, ACL_KIND_NAMESPACE,
-							   get_namespace_name(namespaceOid));
-		}
-
-		form->cfgowner = newOwnerId;
-
-		simple_heap_update(rel, &tup->t_self, tup);
-		CatalogUpdateIndexes(rel, tup);
-
-		/* Update owner dependency reference */
-		changeDependencyOnOwner(TSConfigRelationId, HeapTupleGetOid(tup),
-								newOwnerId);
-	}
-
-	heap_close(rel, NoLock);
-	heap_freetuple(tup);
-}
-
-/*
  * ALTER TEXT SEARCH CONFIGURATION - main entry point
  */
 void

File src/backend/nodes/copyfuncs.c

 	COPY_NODE_FIELD(relation);
 	COPY_NODE_FIELD(object);
 	COPY_NODE_FIELD(objarg);
-	COPY_STRING_FIELD(addname);
 	COPY_STRING_FIELD(newowner);
 
 	return newnode;

File src/backend/nodes/equalfuncs.c

 	COMPARE_NODE_FIELD(relation);
 	COMPARE_NODE_FIELD(object);
 	COMPARE_NODE_FIELD(objarg);
-	COMPARE_STRING_FIELD(addname);
 	COMPARE_STRING_FIELD(newowner);
 
 	return true;

File src/backend/parser/gram.y

 					AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
 					n->objectType = OBJECT_OPCLASS;
 					n->object = $4;
-					n->addname = $6;
+					n->objarg = list_make1(makeString($6));
 					n->newowner = $9;
 					$$ = (Node *)n;
 				}
 					AlterOwnerStmt *n = makeNode(AlterOwnerStmt);
 					n->objectType = OBJECT_OPFAMILY;
 					n->object = $4;
-					n->addname = $6;
+					n->objarg = list_make1(makeString($6));
 					n->newowner = $9;
 					$$ = (Node *)n;
 				}

File src/include/catalog/pg_largeobject.h

 
 extern Oid	LargeObjectCreate(Oid loid);
 extern void LargeObjectDrop(Oid loid);
-extern void LargeObjectAlterOwner(Oid loid, Oid newOwnerId);
 extern bool LargeObjectExists(Oid loid);
 
 #endif   /* PG_LARGEOBJECT_H */

File src/include/commands/alter.h

 #include "utils/relcache.h"
 
 extern void ExecRenameStmt(RenameStmt *stmt);
+
 extern void ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt);
 extern Oid	AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid);
 extern Oid	AlterObjectNamespace_internal(Relation rel, Oid objid, Oid nspOid);
+
 extern void ExecAlterOwnerStmt(AlterOwnerStmt *stmt);
+extern void AlterObjectOwner_internal(Relation catalog, Oid objectId,
+						  Oid new_ownerId);
 
 #endif   /* ALTER_H */

File src/include/commands/collationcmds.h

 
 extern void DefineCollation(List *names, List *parameters);
 extern void RenameCollation(List *name, const char *newname);
-extern void AlterCollationOwner(List *name, Oid newOwnerId);
-extern void AlterCollationOwner_oid(Oid collationOid, Oid newOwnerId);
 extern void AlterCollationNamespace(List *name, const char *newschema);
 extern Oid	AlterCollationNamespace_oid(Oid collOid, Oid newNspOid);
 

File src/include/commands/conversioncmds.h

 
 extern void CreateConversionCommand(CreateConversionStmt *parsetree);
 extern void RenameConversion(List *name, const char *newname);
-extern void AlterConversionOwner(List *name, Oid newOwnerId);
-extern void AlterConversionOwner_oid(Oid conversionOid, Oid newOwnerId);
 
 #endif   /* CONVERSIONCMDS_H */

File src/include/commands/defrem.h

 extern void SetFunctionReturnType(Oid funcOid, Oid newRetType);
 extern void SetFunctionArgType(Oid funcOid, int argIndex, Oid newArgType);
 extern void RenameFunction(List *name, List *argtypes, const char *newname);
-extern void AlterFunctionOwner(List *name, List *argtypes, Oid newOwnerId);
-extern void AlterFunctionOwner_oid(Oid procOid, Oid newOwnerId);
 extern void AlterFunction(AlterFunctionStmt *stmt);
 extern void CreateCast(CreateCastStmt *stmt);
 extern void DropCastById(Oid castOid);
 /* commands/operatorcmds.c */
 extern void DefineOperator(List *names, List *parameters);
 extern void RemoveOperatorById(Oid operOid);
-extern void AlterOperatorOwner(List *name, TypeName *typeName1,
-				   TypeName *typename2, Oid newOwnerId);
-extern void AlterOperatorOwner_oid(Oid operOid, Oid newOwnerId);
 
 /* commands/aggregatecmds.c */
 extern void DefineAggregate(List *name, List *args, bool oldstyle,
 				List *parameters);
 extern void RenameAggregate(List *name, List *args, const char *newname);
-extern void AlterAggregateOwner(List *name, List *args, Oid newOwnerId);
 
 /* commands/opclasscmds.c */
 extern void DefineOpClass(CreateOpClassStmt *stmt);
 extern void RemoveAmProcEntryById(Oid entryOid);
 extern void RenameOpClass(List *name, const char *access_method, const char *newname);
 extern void RenameOpFamily(List *name, const char *access_method, const char *newname);
-extern void AlterOpClassOwner(List *name, const char *access_method, Oid newOwnerId);
-extern void AlterOpClassOwner_oid(Oid opclassOid, Oid newOwnerId);
-extern void AlterOpFamilyOwner(List *name, const char *access_method, Oid newOwnerId);
-extern void AlterOpFamilyOwner_oid(Oid opfamilyOid, Oid newOwnerId);
 extern Oid	get_am_oid(const char *amname, bool missing_ok);
 extern Oid	get_opclass_oid(Oid amID, List *opclassname, bool missing_ok);
 extern Oid	get_opfamily_oid(Oid amID, List *opfamilyname, bool missing_ok);
 extern void RenameTSDictionary(List *oldname, const char *newname);
 extern void RemoveTSDictionaryById(Oid dictId);
 extern void AlterTSDictionary(AlterTSDictionaryStmt *stmt);
-extern void AlterTSDictionaryOwner(List *name, Oid newOwnerId);
 
 extern void DefineTSTemplate(List *names, List *parameters);
 extern void RenameTSTemplate(List *oldname, const char *newname);
 extern void RenameTSConfiguration(List *oldname, const char *newname);
 extern void RemoveTSConfigurationById(Oid cfgId);
 extern void AlterTSConfiguration(AlterTSConfigurationStmt *stmt);
-extern void AlterTSConfigurationOwner(List *name, Oid newOwnerId);
 
 extern text *serialize_deflist(List *deflist);
 extern List *deserialize_deflist(Datum txt);

File src/include/commands/proclang.h

 extern void CreateProceduralLanguage(CreatePLangStmt *stmt);
 extern void DropProceduralLanguageById(Oid langOid);
 extern void RenameLanguage(const char *oldname, const char *newname);
-extern void AlterLanguageOwner(const char *name, Oid newOwnerId);
-extern void AlterLanguageOwner_oid(Oid oid, Oid newOwnerId);
 extern bool PLTemplateExists(const char *languageName);
 extern Oid	get_language_oid(const char *langname, bool missing_ok);
 

File src/include/commands/tablespace.h

 extern void CreateTableSpace(CreateTableSpaceStmt *stmt);
 extern void DropTableSpace(DropTableSpaceStmt *stmt);
 extern void RenameTableSpace(const char *oldname, const char *newname);
-extern void AlterTableSpaceOwner(const char *name, Oid newOwnerId);
 extern void AlterTableSpaceOptions(AlterTableSpaceOptionsStmt *stmt);
 
 extern void TablespaceCreateDbspace(Oid spcNode, Oid dbNode, bool isRedo);

File src/include/nodes/parsenodes.h

 	RangeVar   *relation;		/* in case it's a table */
 	List	   *object;			/* in case it's some other object */
 	List	   *objarg;			/* argument types, if applicable */
-	char	   *addname;		/* additional name if needed */
 	char	   *newowner;		/* the new owner */
 } AlterOwnerStmt;