pgsql-v9.2-ddl-refactoring-part-2.v1.groundworks.patch

application/octet-stream

Filename: pgsql-v9.2-ddl-refactoring-part-2.v1.groundworks.patch
Type: application/octet-stream
Part: 2
Message: Refactoring on DROP/ALTER SET SCHEMA/ALTER RENAME TO statement

Patch

Same data as JSON: GET /api/v1/attachments/:id/patch the parsed metadata as JSON — format, series position, per-file stats; never the diff bytes. API reference →
Format: unified
Series: patch v9
File+
src/backend/catalog/objectaddress.c 493 84
src/backend/commands/comment.c 1 2
src/backend/commands/dropcmds.c 1 2
src/backend/commands/extension.c 1 2
src/backend/commands/seclabel.c 1 2
src/include/catalog/objectaddress.h 9 2
src/test/regress/expected/alter_rename.out 282 0
src/test/regress/expected/privileges.out 1 1
src/test/regress/parallel_schedule 1 1
src/test/regress/serial_schedule 1 0
src/test/regress/sql/alter_rename.sql 240 0
 src/backend/catalog/objectaddress.c        |  577 ++++++++++++++++++++++++----
 src/backend/commands/comment.c             |    3 +-
 src/backend/commands/dropcmds.c            |    3 +-
 src/backend/commands/extension.c           |    3 +-
 src/backend/commands/seclabel.c            |    3 +-
 src/include/catalog/objectaddress.h        |   11 +-
 src/test/regress/expected/alter_rename.out |  282 ++++++++++++++
 src/test/regress/expected/privileges.out   |    2 +-
 src/test/regress/parallel_schedule         |    2 +-
 src/test/regress/serial_schedule           |    1 +
 src/test/regress/sql/alter_rename.sql      |  240 ++++++++++++
 11 files changed, 1031 insertions(+), 96 deletions(-)

diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index ec4c987..bcf5259 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -53,6 +53,7 @@
 #include "foreign/foreign.h"
 #include "libpq/be-fsstubs.h"
 #include "miscadmin.h"
+#include "mb/pg_wchar.h"
 #include "nodes/makefuncs.h"
 #include "parser/parse_func.h"
 #include "parser/parse_oper.h"
@@ -76,8 +77,11 @@ typedef struct
 {
 	Oid			class_oid;			/* oid of catalog */
 	Oid			oid_index_oid; 		/* oid of index on system oid column */
+	Oid			name_index_oid;		/* oid of index on name/schema column */
 	int			oid_catcache_id;	/* id of catcache on system oid column  */
+	int			name_catcache_id;	/* id of catcache on name/schema column */
 	AttrNumber	attnum_namespace;	/* attnum of namespace field */
+	AttrNumber	attnum_name;		/* attnum of name field */
 } ObjectPropertyType;
 
 static ObjectPropertyType ObjectProperty[] =
@@ -85,152 +89,227 @@ static ObjectPropertyType ObjectProperty[] =
 	{
 		CastRelationId,
 		CastOidIndexId,
+		InvalidOid,
 		-1,
-		InvalidAttrNumber
+		-1,
+		InvalidAttrNumber,
+		InvalidAttrNumber,
 	},
 	{
 		CollationRelationId,
 		CollationOidIndexId,
+		InvalidOid,	/* No suitable index on pg_collation */
 		COLLOID,
-		Anum_pg_collation_collnamespace
+		-1,			/* COLLNAMEENCNSP also takes oid of encoding */
+		Anum_pg_collation_collnamespace,
+		Anum_pg_collation_collname,
 	},
 	{
 		ConstraintRelationId,
 		ConstraintOidIndexId,
+		ConstraintNameNspIndexId,
 		CONSTROID,
-		Anum_pg_constraint_connamespace
+		-1,
+		Anum_pg_constraint_connamespace,
+		Anum_pg_constraint_conname,
 	},
 	{
 		ConversionRelationId,
 		ConversionOidIndexId,
+		ConversionNameNspIndexId,
 		CONVOID,
-		Anum_pg_conversion_connamespace
+		-1,
+		Anum_pg_conversion_connamespace,
+		Anum_pg_conversion_conname,
 	},
 	{
 		DatabaseRelationId,
 		DatabaseOidIndexId,
+		DatabaseNameIndexId,
 		DATABASEOID,
-		InvalidAttrNumber
+		-1,
+		InvalidAttrNumber,
+		Anum_pg_database_datname,
 	},
 	{
 		ExtensionRelationId,
 		ExtensionOidIndexId,
+		InvalidOid,
+		-1,
 		-1,
-		InvalidAttrNumber		/* extension doesn't belong to extnamespace */
+		InvalidAttrNumber,		/* extension doesn't belong to extnamespace */
+		InvalidAttrNumber,		/* extension name is unavailable to change */
 	},
 	{
 		ForeignDataWrapperRelationId,
 		ForeignDataWrapperOidIndexId,
+		ForeignDataWrapperNameIndexId,
 		FOREIGNDATAWRAPPEROID,
-		InvalidAttrNumber
+		FOREIGNDATAWRAPPERNAME,
+		InvalidAttrNumber,
+		Anum_pg_foreign_data_wrapper_fdwname,
 	},
 	{
 		ForeignServerRelationId,
 		ForeignServerOidIndexId,
+		ForeignServerNameIndexId,
 		FOREIGNSERVEROID,
-		InvalidAttrNumber
+		FOREIGNSERVERNAME,
+		InvalidAttrNumber,
+		Anum_pg_foreign_server_srvname,
 	},
 	{
 		ProcedureRelationId,
 		ProcedureOidIndexId,
+		InvalidOid,	/* No suitable index on pg_proc */
 		PROCOID,
-		Anum_pg_proc_pronamespace
+		-1,			/* PROCNAMEARGSNSP takes argument types too */
+		Anum_pg_proc_pronamespace,
+		Anum_pg_proc_proname,
 	},
 	{
 		LanguageRelationId,
 		LanguageOidIndexId,
+		LanguageNameIndexId,
 		LANGOID,
+		LANGNAME,
 		InvalidAttrNumber,
+		Anum_pg_language_lanname,
 	},
 	{
 		LargeObjectMetadataRelationId,
 		LargeObjectMetadataOidIndexId,
+		InvalidOid,
+		-1,
 		-1,
-		InvalidAttrNumber
+		InvalidAttrNumber,
+		InvalidAttrNumber,
 	},
 	{
 		OperatorClassRelationId,
 		OpclassOidIndexId,
+		InvalidOid,	/* No suitable index on pg_opclass */
 		CLAOID,
+		-1,			/* CLANAME takes oid of access method too */
 		Anum_pg_opclass_opcnamespace,
+		Anum_pg_opclass_opcname,
 	},
 	{
 		OperatorRelationId,
 		OperatorOidIndexId,
+		OperatorNameNspIndexId,
 		OPEROID,
-		Anum_pg_operator_oprnamespace
+		-1,			/* OPERNAMENSP takes oid of left/right types too */
+		Anum_pg_operator_oprnamespace,
+		Anum_pg_operator_oprname,
 	},
 	{
 		OperatorFamilyRelationId,
 		OpfamilyOidIndexId,
+		InvalidOid,	/* No suitable index on op_opfamily */
 		OPFAMILYOID,
-		Anum_pg_opfamily_opfnamespace
+		-1,			/* OPFAMILYAMNAMENSP takes oid of access method too */
+		Anum_pg_opfamily_opfnamespace,
+		Anum_pg_opfamily_opfname,
 	},
 	{
 		AuthIdRelationId,
 		AuthIdOidIndexId,
+		AuthIdRolnameIndexId,
 		AUTHOID,
-		InvalidAttrNumber
+		AUTHNAME,
+		InvalidAttrNumber,
+		AuthIdRelationId,
 	},
 	{
 		RewriteRelationId,
 		RewriteOidIndexId,
+		InvalidOid,	/* No suitable index on pg_rewrite */
 		-1,
-		InvalidAttrNumber
+		-1,			/* RULERELNAME takes oid of relation too */
+		InvalidAttrNumber,
+		Anum_pg_rewrite_rulename,
 	},
 	{
 		NamespaceRelationId,
 		NamespaceOidIndexId,
+		NamespaceNameIndexId,
 		NAMESPACEOID,
-		InvalidAttrNumber
+		NAMESPACENAME,
+		InvalidAttrNumber,
+		Anum_pg_namespace_nspname,
 	},
 	{
 		RelationRelationId,
 		ClassOidIndexId,
+		ClassNameNspIndexId,
 		RELOID,
-		Anum_pg_class_relnamespace
+		RELNAMENSP,
+		Anum_pg_class_relnamespace,
+		Anum_pg_class_relname,
 	},
 	{
 		TableSpaceRelationId,
 		TablespaceOidIndexId,
+		TablespaceNameIndexId,
 		TABLESPACEOID,
-		InvalidAttrNumber
+		-1,
+		InvalidAttrNumber,
+		Anum_pg_tablespace_spcname,
 	},
 	{
 		TriggerRelationId,
 		TriggerOidIndexId,
+		InvalidOid,		/* No suitable index on pg_trigegr */
+		-1,
 		-1,
-		InvalidAttrNumber
+		InvalidAttrNumber,
+		Anum_pg_trigger_tgname,
 	},
 	{
 		TSConfigRelationId,
 		TSConfigOidIndexId,
+		TSConfigNameNspIndexId,
 		TSCONFIGOID,
-		Anum_pg_ts_config_cfgnamespace
+		TSCONFIGNAMENSP,
+		Anum_pg_ts_config_cfgnamespace,
+		Anum_pg_ts_config_cfgname,
 	},
 	{
 		TSDictionaryRelationId,
 		TSDictionaryOidIndexId,
+		TSDictionaryNameNspIndexId,
 		TSDICTOID,
-		Anum_pg_ts_dict_dictnamespace
+		TSDICTNAMENSP,
+		Anum_pg_ts_dict_dictnamespace,
+		Anum_pg_ts_dict_dictname,
 	},
 	{
 		TSParserRelationId,
 		TSParserOidIndexId,
+		TSParserNameNspIndexId,
 		TSPARSEROID,
-		Anum_pg_ts_parser_prsnamespace
+		TSPARSERNAMENSP,
+		Anum_pg_ts_parser_prsnamespace,
+		Anum_pg_ts_parser_prsname,
 	},
 	{
 		TSTemplateRelationId,
 		TSTemplateOidIndexId,
+		TSTemplateNameNspIndexId,
 		TSTEMPLATEOID,
+		TSTEMPLATENAMENSP,
 		Anum_pg_ts_template_tmplnamespace,
+		Anum_pg_ts_template_tmplname,
 	},
 	{
 		TypeRelationId,
 		TypeOidIndexId,
+		TypeNameNspIndexId,
 		TYPEOID,
-		Anum_pg_type_typnamespace
+		TYPENAMENSP,
+		Anum_pg_type_typnamespace,
+		Anum_pg_type_typname,
 	}
 };
 
@@ -914,93 +993,129 @@ object_exists(ObjectAddress address)
  * Check ownership of an object previously identified by get_object_address.
  */
 void
-check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
-					   List *objname, List *objargs, Relation relation)
+check_object_ownership(Oid roleid, ObjectAddress address, Relation relation)
 {
-	switch (objtype)
+	switch (address.classId)
 	{
-		case OBJECT_INDEX:
-		case OBJECT_SEQUENCE:
-		case OBJECT_TABLE:
-		case OBJECT_VIEW:
-		case OBJECT_FOREIGN_TABLE:
-		case OBJECT_COLUMN:
-		case OBJECT_RULE:
-		case OBJECT_TRIGGER:
-		case OBJECT_CONSTRAINT:
+		case RelationRelationId:
+		case RewriteRelationId:
+		case TriggerRelationId:
+		case ConstraintRelationId:
 			if (!pg_class_ownercheck(RelationGetRelid(relation), roleid))
 				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CLASS,
 							   RelationGetRelationName(relation));
 			break;
-		case OBJECT_DATABASE:
+		case DatabaseRelationId:
 			if (!pg_database_ownercheck(address.objectId, roleid))
 				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_DATABASE,
-							   NameListToString(objname));
+							   get_database_name(address.objectId));
 			break;
-		case OBJECT_TYPE:
-		case OBJECT_DOMAIN:
-		case OBJECT_ATTRIBUTE:
+		case TypeRelationId:
 			if (!pg_type_ownercheck(address.objectId, roleid))
 				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TYPE,
 							   format_type_be(address.objectId));
 			break;
-		case OBJECT_AGGREGATE:
-		case OBJECT_FUNCTION:
+		case ProcedureRelationId:
 			if (!pg_proc_ownercheck(address.objectId, roleid))
 				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_PROC,
-							   NameListToString(objname));
+							   format_procedure(address.objectId));
 			break;
-		case OBJECT_OPERATOR:
+		case OperatorRelationId:
 			if (!pg_oper_ownercheck(address.objectId, roleid))
 				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPER,
-							   NameListToString(objname));
+							   format_operator(address.objectId));
 			break;
-		case OBJECT_SCHEMA:
+		case NamespaceRelationId:
 			if (!pg_namespace_ownercheck(address.objectId, roleid))
 				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_NAMESPACE,
-							   NameListToString(objname));
+							   get_namespace_name(address.objectId));
 			break;
-		case OBJECT_COLLATION:
+		case CollationRelationId:
 			if (!pg_collation_ownercheck(address.objectId, roleid))
 				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_COLLATION,
-							   NameListToString(objname));
+							   get_collation_name(address.objectId));
 			break;
-		case OBJECT_CONVERSION:
+		case ConversionRelationId:
 			if (!pg_conversion_ownercheck(address.objectId, roleid))
+			{
+				char	   *convname = NULL;
+				HeapTuple	tup = SearchSysCache1(CONVOID,
+									ObjectIdGetDatum(address.objectId));
+				if (HeapTupleIsValid(tup))
+				{
+					Form_pg_conversion conversion
+						= (Form_pg_conversion) GETSTRUCT(tup);
+					convname = pstrdup(NameStr(conversion->conname));
+					ReleaseSysCache(tup);
+				}
 				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_CONVERSION,
-							   NameListToString(objname));
+							   convname);
+			}
 			break;
-		case OBJECT_EXTENSION:
+		case ExtensionRelationId:
 			if (!pg_extension_ownercheck(address.objectId, roleid))
 				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_EXTENSION,
-							   NameListToString(objname));
+							   get_extension_name(address.objectId));
 			break;
-		case OBJECT_FDW:
+		case ForeignDataWrapperRelationId:
 			if (!pg_foreign_data_wrapper_ownercheck(address.objectId, roleid))
 				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FDW,
-							   NameListToString(objname));
+						GetForeignDataWrapper(address.objectId)->fdwname);
 			break;
-		case OBJECT_FOREIGN_SERVER:
+		case ForeignServerRelationId:
 			if (!pg_foreign_server_ownercheck(address.objectId, roleid))
 				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_FOREIGN_SERVER,
-							   NameListToString(objname));
+							   GetForeignServer(address.objectId)->servername);
 			break;
-		case OBJECT_LANGUAGE:
+		case LanguageRelationId:
 			if (!pg_language_ownercheck(address.objectId, roleid))
-				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_LANGUAGE,
-							   NameListToString(objname));
+			{
+				char	   *lanname = NULL;
+				HeapTuple	tup = SearchSysCache1(LANGOID,
+										ObjectIdGetDatum(address.objectId));
+				if (HeapTupleIsValid(tup))
+				{
+					Form_pg_language lang
+						= (Form_pg_language) GETSTRUCT(tup);
+					lanname = pstrdup(NameStr(lang->lanname));
+					ReleaseSysCache(tup);
+				}
+				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_LANGUAGE, lanname);
+			}
 			break;
-		case OBJECT_OPCLASS:
+		case OperatorClassRelationId:
 			if (!pg_opclass_ownercheck(address.objectId, roleid))
-				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPCLASS,
-							   NameListToString(objname));
+			{
+				char	   *opcname = NULL;
+				HeapTuple	tup = SearchSysCache1(CLAOID,
+										ObjectIdGetDatum(address.objectId));
+				if (HeapTupleIsValid(tup))
+				{
+					Form_pg_opclass opclass
+						= (Form_pg_opclass) GETSTRUCT(tup);
+					opcname = pstrdup(NameStr(opclass->opcname));
+					ReleaseSysCache(tup);
+				}
+				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPCLASS, opcname);
+			}
 			break;
-		case OBJECT_OPFAMILY:
+		case OperatorFamilyRelationId:
 			if (!pg_opfamily_ownercheck(address.objectId, roleid))
-				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPFAMILY,
-							   NameListToString(objname));
+			{
+				char	   *opfname = NULL;
+				HeapTuple	tup = SearchSysCache1(OPFAMILYOID,
+										ObjectIdGetDatum(address.objectId));
+				if (HeapTupleIsValid(tup))
+				{
+					Form_pg_opfamily opfamily
+						= (Form_pg_opfamily) GETSTRUCT(tup);
+					opfname = pstrdup(NameStr(opfamily->opfname));
+					ReleaseSysCache(tup);
+				}
+				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_OPFAMILY, opfname);
+			}
 			break;
-		case OBJECT_LARGEOBJECT:
+		case LargeObjectRelationId:
 			if (!lo_compat_privileges &&
 				!pg_largeobject_ownercheck(address.objectId, roleid))
 				ereport(ERROR,
@@ -1008,14 +1123,36 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
 						 errmsg("must be owner of large object %u",
 								address.objectId)));
 			break;
-		case OBJECT_CAST:
+		case CastRelationId:
 			{
-				/* We can only check permissions on the source/target types */
-				TypeName   *sourcetype = (TypeName *) linitial(objname);
-				TypeName   *targettype = (TypeName *) linitial(objargs);
-				Oid			sourcetypeid = typenameTypeId(NULL, sourcetype);
-				Oid			targettypeid = typenameTypeId(NULL, targettype);
+				Relation	catalog;
+				ScanKeyData	skey[1];
+				SysScanDesc	scan;
+				HeapTuple	tup;
+				Oid			sourcetypeid;
+				Oid			targettypeid;
+
+				catalog = heap_open(CastRelationId, AccessShareLock);
+
+				ScanKeyInit(&skey[0],
+							ObjectIdAttributeNumber,
+							BTEqualStrategyNumber, F_OIDEQ,
+							ObjectIdGetDatum(address.objectId));
+				
+				scan = systable_beginscan(catalog, CastOidIndexId, true,
+										  SnapshotNow, 1, skey);
+				tup = systable_getnext(scan);
+				if (!HeapTupleIsValid(tup))
+					elog(ERROR, "could not find tuple for cast %u",
+						 address.objectId);
+
+				sourcetypeid = ((Form_pg_cast) GETSTRUCT(tup))->castsource;
+				targettypeid = ((Form_pg_cast) GETSTRUCT(tup))->casttarget;
+
+				systable_endscan(scan);
+                heap_close(catalog, AccessShareLock);
 
+				/* We can only check permissions on the source/target types */
 				if (!pg_type_ownercheck(sourcetypeid, roleid)
 					&& !pg_type_ownercheck(targettypeid, roleid))
 					ereport(ERROR,
@@ -1025,23 +1162,46 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
 									format_type_be(targettypeid))));
 			}
 			break;
-		case OBJECT_TABLESPACE:
+		case TableSpaceRelationId:
 			if (!pg_tablespace_ownercheck(address.objectId, roleid))
 				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TABLESPACE,
-							   NameListToString(objname));
+							   get_tablespace_name(address.objectId));
 			break;
-		case OBJECT_TSDICTIONARY:
+		case TSDictionaryRelationId:
 			if (!pg_ts_dict_ownercheck(address.objectId, roleid))
+			{
+				char	   *dictname = NULL;
+				HeapTuple	tup = SearchSysCache1(TSDICTOID,
+									ObjectIdGetDatum(address.objectId));
+				if (HeapTupleIsValid(tup))
+				{
+					Form_pg_ts_dict tsdict
+						= (Form_pg_ts_dict) GETSTRUCT(tup);
+					dictname = pstrdup(NameStr(tsdict->dictname));
+					ReleaseSysCache(tup);
+				}
 				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSDICTIONARY,
-							   NameListToString(objname));
+							   dictname);
+			}
 			break;
-		case OBJECT_TSCONFIGURATION:
+		case TSConfigRelationId:
 			if (!pg_ts_config_ownercheck(address.objectId, roleid))
+			{
+				char	   *confname = NULL;
+				HeapTuple	tup = SearchSysCache1(TSCONFIGOID,
+									ObjectIdGetDatum(address.objectId));
+				if (HeapTupleIsValid(tup))
+				{
+					Form_pg_ts_config tsconf
+						= (Form_pg_ts_config) GETSTRUCT(tup);
+					confname = pstrdup(NameStr(tsconf->cfgname));
+					ReleaseSysCache(tup);
+				}
 				aclcheck_error(ACLCHECK_NOT_OWNER, ACL_KIND_TSCONFIGURATION,
-							   NameListToString(objname));
+							   confname);
+			}
 			break;
-		case OBJECT_ROLE:
-
+		case AuthIdRelationId:
 			/*
 			 * We treat roles as being "owned" by those with CREATEROLE priv,
 			 * except that superusers are only owned by superusers.
@@ -1061,8 +1221,8 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
 							 errmsg("must have CREATEROLE privilege")));
 			}
 			break;
-		case OBJECT_TSPARSER:
-		case OBJECT_TSTEMPLATE:
+		case TSParserRelationId:
+		case TSTemplateRelationId:
 			/* We treat these object types as being owned by superusers */
 			if (!superuser_arg(roleid))
 				ereport(ERROR,
@@ -1070,9 +1230,258 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
 						 errmsg("must be superuser")));
 			break;
 		default:
-			elog(ERROR, "unrecognized object type: %d",
-				 (int) objtype);
+			elog(ERROR, "unrecognized class-id of the object: %u",
+				 address.classId);
+	}
+}
+
+/*
+ * check_exists_namespace
+ *
+ * check name or/and namespace conflict of the supplied object, if and
+ * when its name or namespace would be switched to.
+ */
+bool
+object_exists_namespace(ObjectAddress address,
+						Oid new_namespace, const char *new_name)
+{
+	ObjectPropertyType *property;
+	HeapTuple	tuple;
+	Datum		datum;
+	bool		isnull;
+	bool		found = false;
+
+	/*
+	 * Right now, we have no code path to invoke this routine toward
+	 * pg_attribute, pg_trigger or pg_rewrite; that takes special
+	 * treatments.
+	 */
+	Assert(address.objectSubId == 0);
+	Assert(address.classId != TriggerRelationId);
+	Assert(address.classId != RewriteRelationId);
+
+	/*
+	 * Weird backward compatibility hack: ObjectAddress notation uses
+	 * LargeObjectRelationId for large objects, but since PostgreSQL
+	 * 9.0, the relevant catalog is actually LargeObjectMetadataRelationId.
+	 */
+	if (address.classId == LargeObjectRelationId)
+		address.classId = LargeObjectMetadataRelationId;
+
+	property = get_object_property_data(address.classId);
+
+	/* This routine must be called towards object classes with its name. */
+	Assert(property->attnum_name != InvalidAttrNumber);
+
+	/* We have catcache by oid for named object types */
+	Assert(property->oid_catcache_id != -1);
+
+	tuple = SearchSysCache1(property->oid_catcache_id,
+							ObjectIdGetDatum(address.objectId));
+	if (!HeapTupleIsValid(tuple))
+		elog(ERROR, "cache lookup failed for class %u object %u subobj %d",
+			 address.classId, address.objectId, address.objectSubId);
+
+	/*
+	 * if namespace is preserved, the current one shall be used as
+	 * a key to look up system catalog.
+	 */
+	if (!OidIsValid(new_namespace) &&
+		property->attnum_namespace != InvalidAttrNumber)
+	{
+		
+		datum = SysCacheGetAttr(property->oid_catcache_id,
+								tuple,
+								property->attnum_namespace,
+								&isnull);
+		Assert(!isnull);
+		new_namespace = DatumGetObjectId(datum);
+	}
+
+	/*
+	 * if name is preserved, the current one shall be used as
+	 * a key to look up system catalog.
+	 */
+	if (!new_name)
+	{
+		datum = SysCacheGetAttr(property->oid_catcache_id,
+								tuple,
+								property->attnum_name,
+								&isnull);
+		Assert(!isnull);
+		new_name = pstrdup(NameStr(*(DatumGetName(datum))));
+	}
+	Assert(new_name != NULL);
+
+	/* COLLNAMEENCNSP cache takes encoding type, so special treatment too */
+	if (address.classId == CollationRelationId)
+	{
+		if (SearchSysCacheExists3(COLLNAMEENCNSP,
+								  CStringGetDatum(new_name),
+								  Int32GetDatum(GetDatabaseEncoding()),
+								  ObjectIdGetDatum(new_namespace)))
+			found = true;
+		/* mustn't match an any-encoding entry, either */
+		if (SearchSysCacheExists3(COLLNAMEENCNSP,
+								  CStringGetDatum(new_name),
+								  Int32GetDatum(-1),
+								  ObjectIdGetDatum(new_namespace)))
+			found = true;
 	}
+	/* PROCNAMEARGSNSP cache takes argument types too */
+	else if (address.classId == ProcedureRelationId)
+	{
+		Form_pg_proc	procForm = (Form_pg_proc) GETSTRUCT(tuple);
+
+		if (SearchSysCacheExists3(PROCNAMEARGSNSP,
+								  CStringGetDatum(new_name),
+								  PointerGetDatum(&procForm->proargtypes),
+								  ObjectIdGetDatum(new_namespace)))
+			found = true;
+	}
+	/* OPERNAMENSP cache takes oid of left/right types too */
+	else if (address.classId == OperatorRelationId)
+	{
+		Oid		oprleft = ((Form_pg_operator) GETSTRUCT(tuple))->oprleft;
+		Oid		oprright = ((Form_pg_operator) GETSTRUCT(tuple))->oprright;
+
+		if (SearchSysCacheExists4(OPERNAMENSP,
+								  CStringGetDatum(new_name),
+								  ObjectIdGetDatum(oprleft),
+								  ObjectIdGetDatum(oprright),
+								  ObjectIdGetDatum(new_namespace)))
+			found = true;
+	}
+	/* CLAAMNAMENSP cache takes oid of access method too */
+	else if (address.classId == OperatorClassRelationId)
+	{
+		Oid		amoid = ((Form_pg_opclass) GETSTRUCT(tuple))->opcmethod;
+
+		if (SearchSysCacheExists3(CLAAMNAMENSP,
+								  ObjectIdGetDatum(amoid),
+								  CStringGetDatum(new_name),
+								  ObjectIdGetDatum(new_namespace)))
+			found = true;
+	}
+	/* OPFAMILYAMNAMENSP cache takes oid of access method too */
+	else if (address.classId == OperatorFamilyRelationId)
+	{
+		Oid		amoid = ((Form_pg_opfamily) GETSTRUCT(tuple))->opfmethod;
+
+		if (SearchSysCacheExists3(OPFAMILYAMNAMENSP,
+								  ObjectIdGetDatum(amoid),
+								  CStringGetDatum(new_name),
+								  ObjectIdGetDatum(new_namespace)))
+			found = true;
+	}
+	else if (property->name_catcache_id != -1)
+	{
+		found = SearchSysCacheExists2(property->name_catcache_id,
+									  CStringGetDatum(new_name),
+									  ObjectIdGetDatum(new_namespace));
+	}
+	else
+	{
+		Relation	rel;
+		ScanKeyData skey[2];
+		SysScanDesc scan;
+		int			nkeys;
+
+		/* No syscache, so examine the table directly. */
+		Assert(OidIsValid(property->name_index_oid));
+
+		ScanKeyInit(&skey[0],
+					property->attnum_name,
+					BTEqualStrategyNumber, F_NAMEEQ,
+					CStringGetDatum(new_name));
+		if (property->attnum_namespace == InvalidAttrNumber)
+			nkeys = 1;
+		else
+		{
+			ScanKeyInit(&skey[1],
+						property->attnum_namespace,
+						BTEqualStrategyNumber, F_OIDEQ,
+						ObjectIdGetDatum(new_namespace));
+			nkeys = 2;
+		}
+
+		rel = heap_open(address.classId, AccessShareLock);
+		scan = systable_beginscan(rel, property->name_index_oid, true,
+								  SnapshotNow, nkeys, skey);
+		found = HeapTupleIsValid(systable_getnext(scan));
+		systable_endscan(scan);
+		heap_close(rel, AccessShareLock);
+	}
+	ReleaseSysCache(tuple);
+
+	return found;
+}
+
+/*
+ * get_object_tuple
+ *
+ * It returns a copy of heaptuple data within system catalog.
+ */
+HeapTuple
+get_object_tuple(ObjectAddress address)
+{
+	int			cache = -1;
+	Oid			indexoid = InvalidOid;
+	Relation	rel;
+	ScanKeyData skey[1];
+	SysScanDesc sd;
+	HeapTuple	tuple = NULL;
+	ObjectPropertyType	   *property;
+
+	/* Sub-objects require special treatment. */
+	if (address.objectSubId != 0)
+	{
+		/* Currently, attributes are the only sub-objects. */
+		Assert(address.classId == RelationRelationId);
+		tuple = SearchSysCacheCopy2(ATTNUM,
+									ObjectIdGetDatum(address.objectId),
+									Int16GetDatum(address.objectSubId));
+		if (((Form_pg_attribute) GETSTRUCT(tuple))->attisdropped)
+		{
+			heap_freetuple(tuple);
+			return NULL;
+		}
+		return tuple;
+	}
+
+	/*
+	 * Weird backward compatibility hack: ObjectAddress notation uses
+	 * LargeObjectRelationId for large objects, but since PostgreSQL
+	 * 9.0, the relevant catalog is actually LargeObjectMetadataRelationId.
+	 */
+	if (address.classId == LargeObjectRelationId)
+		address.classId = LargeObjectMetadataRelationId;
+
+	/*
+	 * For object types that have a relevant syscache, we use it; for
+	 * everything else, we'll have to do an index-scan.
+	 */
+	property = get_object_property_data(address.classId);
+	cache = property->oid_catcache_id;
+	indexoid = property->oid_index_oid;
+
+	/* Found a syscache? */
+	if (cache != -1)
+		return SearchSysCacheCopy1(cache, ObjectIdGetDatum(address.objectId));
+
+	/* No syscache, so examine the table directly. */
+	Assert(OidIsValid(indexoid));
+	ScanKeyInit(&skey[0],
+				ObjectIdAttributeNumber,
+				BTEqualStrategyNumber, F_OIDEQ,
+				ObjectIdGetDatum(address.objectId));
+	rel = heap_open(address.classId, AccessShareLock);
+	sd = systable_beginscan(rel, indexoid, true, SnapshotNow, 1, skey);
+	tuple = heap_copytuple(systable_getnext(sd));
+	systable_endscan(sd);
+	heap_close(rel, AccessShareLock);
+
+	return tuple;
 }
 
 /*
diff --git a/src/backend/commands/comment.c b/src/backend/commands/comment.c
index 200b6a2..34705e5 100644
--- a/src/backend/commands/comment.c
+++ b/src/backend/commands/comment.c
@@ -73,8 +73,7 @@ CommentObject(CommentStmt *stmt)
 								 &relation, ShareUpdateExclusiveLock, false);
 
 	/* Require ownership of the target object. */
-	check_object_ownership(GetUserId(), stmt->objtype, address,
-						   stmt->objname, stmt->objargs, relation);
+	check_object_ownership(GetUserId(), address, relation);
 
 	/* Perform other integrity checks as needed. */
 	switch (stmt->objtype)
diff --git a/src/backend/commands/dropcmds.c b/src/backend/commands/dropcmds.c
index ef70168..2cd8232 100644
--- a/src/backend/commands/dropcmds.c
+++ b/src/backend/commands/dropcmds.c
@@ -98,8 +98,7 @@ RemoveObjects(DropStmt *stmt)
 			namespaceId = get_object_namespace(&address);
 			if (!OidIsValid(namespaceId) ||
 				!pg_namespace_ownercheck(namespaceId, GetUserId()))
-				check_object_ownership(GetUserId(), stmt->removeType, address,
-									   objname, objargs, relation);
+				check_object_ownership(GetUserId(), address, relation);
 		}
 
 		/* Release any relcache reference count, but keep lock until commit. */
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index c334ca9..5a2cc09 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -2652,8 +2652,7 @@ ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *stmt)
 								&relation, ShareUpdateExclusiveLock, false);
 
 	/* Permission check: must own target object, too */
-	check_object_ownership(GetUserId(), stmt->objtype, object,
-						   stmt->objname, stmt->objargs, relation);
+	check_object_ownership(GetUserId(), object, relation);
 
 	/*
 	 * Check existing extension membership.
diff --git a/src/backend/commands/seclabel.c b/src/backend/commands/seclabel.c
index e0fd7ac..118f467 100644
--- a/src/backend/commands/seclabel.c
+++ b/src/backend/commands/seclabel.c
@@ -90,8 +90,7 @@ ExecSecLabelStmt(SecLabelStmt *stmt)
 								 &relation, ShareUpdateExclusiveLock, false);
 
 	/* Require ownership of the target object. */
-	check_object_ownership(GetUserId(), stmt->objtype, address,
-						   stmt->objname, stmt->objargs, relation);
+	check_object_ownership(GetUserId(), address, relation);
 
 	/* Perform other integrity checks as needed. */
 	switch (stmt->objtype)
diff --git a/src/include/catalog/objectaddress.h b/src/include/catalog/objectaddress.h
index eddccb8..ff7b957 100644
--- a/src/include/catalog/objectaddress.h
+++ b/src/include/catalog/objectaddress.h
@@ -13,6 +13,7 @@
 #ifndef OBJECTADDRESS_H
 #define OBJECTADDRESS_H
 
+#include "access/htup.h"
 #include "nodes/parsenodes.h"
 #include "storage/lock.h"
 #include "utils/relcache.h"
@@ -32,8 +33,14 @@ extern ObjectAddress get_object_address(ObjectType objtype, List *objname,
 										LOCKMODE lockmode, bool missing_ok);
 
 extern void check_object_ownership(Oid roleid,
-					   ObjectType objtype, ObjectAddress address,
-					   List *objname, List *objargs, Relation relation);
+								   ObjectAddress address,
+								   Relation relation);
+
+extern bool object_exists_namespace(ObjectAddress address,
+									Oid new_namespace,
+									const char *new_name);
+
+extern HeapTuple get_object_tuple(ObjectAddress address);
 
 extern Oid	get_object_namespace(const ObjectAddress *address);
 
diff --git a/src/test/regress/expected/alter_rename.out b/src/test/regress/expected/alter_rename.out
new file mode 100644
index 0000000..6688d50
--- /dev/null
+++ b/src/test/regress/expected/alter_rename.out
@@ -0,0 +1,282 @@
+--
+-- ALTER xxx RENAME TO/SET SCHEMA statement
+--
+CREATE SCHEMA testschema_1;
+CREATE SCHEMA testschema_2;
+SET search_path = testschema_1, public;
+--
+-- ROLE
+--
+CREATE ROLE testrole_1;
+CREATE ROLE testrole_2;
+ALTER ROLE testrole_1 RENAME TO testrole_2;		-- fail
+ERROR:  role "testrole_2" already exists
+ALTER ROLE testrole_1 RENAME TO testrole_3;		-- OK
+DROP ROLE testrole_2, testrole_3;
+--
+-- LANGUAGE
+--
+CREATE LANGUAGE testlang_1 HANDLER plpgsql_call_handler;
+CREATE LANGUAGE testlang_2 HANDLER plpgsql_call_handler;
+ALTER LANGUAGE testlang_1 RENAME TO testlang_2;	-- fail
+ERROR:  language "testlang_2" already exists
+ALTER LANGUAGE testlang_1 RENAME TO testlang_3;	-- OK
+DROP LANGUAGE testlang_2;
+DROP LANGUAGE testlang_3;
+--
+-- TABLE
+--
+CREATE TABLE testtable_a(a int, b int);
+CREATE TABLE testtable_b(x int, y int);
+ALTER TABLE testtable_a RENAME TO testtable_b;		-- fail
+ERROR:  relation "testtable_b" already exists
+ALTER TABLE testtable_b SET SCHEMA testschema_2;	-- OK
+ALTER TABLE testtable_a RENAME TO testtable_b;		-- OK
+ALTER TABLE testtable_b SET SCHEMA testschema_2;	-- fail
+ERROR:  relation "testtable_b" already exists in schema "testschema_2"
+--
+-- VIEW
+--
+CREATE VIEW testview_a AS SELECT * FROM pg_class WHERE relname like 'pg_%';
+CREATE VIEW testview_b AS SELECT * FROM pg_class WHERE relname like 'pg_%';
+ALTER VIEW testview_a RENAME TO testview_b;		-- fail
+ERROR:  relation "testview_b" already exists
+ALTER VIEW testview_b SET SCHEMA testschema_2;	-- OK
+ALTER VIEW testview_a RENAME TO testview_b;		-- OK
+ALTER VIEW testview_b SET SCHEMA testschema_2;	-- fail
+ERROR:  relation "testview_b" already exists in schema "testschema_2"
+ALTER VIEW testtable_b SET SCHEMA public;		-- fail
+ERROR:  "testtable_b" is not a view
+ALTER VIEW testtable_b RENAME TO testtable_c;	-- fail
+ERROR:  "testtable_b" is not a view
+--
+-- SEQUENCE
+--
+CREATE SEQUENCE testseq_a;
+CREATE SEQUENCE testseq_b;
+ALTER SEQUENCE testseq_a RENAME TO testseq_b;		-- fail
+ERROR:  relation "testseq_b" already exists
+ALTER SEQUENCE testseq_b SET SCHEMA testschema_2;	-- OK
+ALTER SEQUENCE testseq_a RENAME TO testseq_b;		-- OK
+ALTER SEQUENCE testseq_b SET SCHEMA testschema_2;	-- fail
+ERROR:  relation "testseq_b" already exists in schema "testschema_2"
+ALTER SEQUENCE testview_b SET SCHEMA public;		-- fail
+ERROR:  "testview_b" is not a sequence
+ALTER SEQUENCE testview_b RENAME TO testview_c;		-- fail
+ERROR:  "testview_b" is not a sequence
+--
+-- COMPOSITE TYPE
+--
+CREATE TYPE testcomptype_a AS (a int, b int);
+CREATE TYPE testcomptype_b AS (a int, b int);
+ALTER TYPE testcomptype_a RENAME TO testcomptype_b;	-- fail
+ERROR:  relation "testcomptype_b" already exists
+ALTER TYPE testcomptype_b SET SCHEMA testschema_2;	-- OK
+ALTER TYPE testcomptype_a RENAME TO testcomptype_b;	-- OK
+ALTER TYPE testcomptype_b SET SCHEMA testschema_2;	-- fail
+ERROR:  type "testcomptype_b" already exists in schema "testschema_2"
+ALTER TYPE testseq_b SET SCHEMA public;				-- fail
+ERROR:  testseq_b is a table's row type
+HINT:  Use ALTER TABLE instead.
+ALTER TYPE testseq_b RENAME TO testseq_c;			-- fail
+ERROR:  testseq_b is a table's row type
+HINT:  Use ALTER TABLE instead.
+--
+-- INDEX
+--
+CREATE INDEX testindex_a ON testtable_b (a);
+CREATE INDEX testindex_b ON testtable_b (b);
+ALTER INDEX testindex_a RENAME TO testindex_b;		-- fail
+ERROR:  relation "testindex_b" already exists
+ALTER INDEX testindex_a RENAME TO testindex_c;		-- OK
+--
+-- COLUMN
+--
+ALTER TABLE testtable_b RENAME a TO b;		-- fail
+ERROR:  column "b" of relation "testtable_b" already exists
+ALTER TABLE testtable_b RENAME a TO x;		-- OK
+CREATE TABLE testtable_c (z int) INHERITS (testtable_b);
+ALTER TABLE ONLY testtable_b RENAME b TO y;	-- fail
+ERROR:  inherited column "b" must be renamed in child tables too
+ALTER TABLE testtable_b RENAME b TO y;		-- OK
+ALTER TABLE testtable_c RENAME z TO zz;		-- OK
+ALTER TABLE testtable_c RENAME x TO xx;		-- fail
+ERROR:  cannot rename inherited column "x"
+--
+-- TRIGGER
+--
+CREATE TRIGGER testtrigger_a
+    BEFORE UPDATE ON testtable_b
+    FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger();
+CREATE TRIGGER testtrigger_b
+    BEFORE UPDATE ON testtable_b
+    FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger();
+ALTER TRIGGER testtrigger_a ON testtable_b RENAME TO testtrigger_b;	-- fail
+ERROR:  trigger "testtrigger_b" for relation "testtable_b" already exists
+ALTER TRIGGER testtrigger_a ON testtable_b RENAME TO testtrigger_c;	-- OK
+--
+-- FUNCTION, AGGREGATE
+--
+CREATE FUNCTION testfunc_a(int)
+	   RETURNS int LANGUAGE sql
+	   AS 'SELECT $1 + $1';
+CREATE FUNCTION testfunc_b(int)
+	   RETURNS int LANGUAGE sql
+	   AS 'SELECT $1 + $1';
+ALTER FUNCTION testfunc_a(int) RENAME TO testfunc_b;	-- fail
+ERROR:  function testfunc_b(integer) already exists in schema "testschema_1"
+ALTER FUNCTION testfunc_b(int) SET SCHEMA testschema_2;	-- OK
+ALTER FUNCTION testfunc_a(int) RENAME TO testfunc_b;	-- OK
+ALTER FUNCTION testfunc_b(int) SET SCHEMA testschema_2;	-- fail
+ERROR:  function "testfunc_b" already exists in schema "testschema_2"
+CREATE AGGREGATE testagg_a(
+	   sfunc1 = int4pl, basetype = int4, stype1 = int4,
+	   initcond1 = '0'
+);
+CREATE AGGREGATE testagg_b(
+	   sfunc1 = int4pl, basetype = int4, stype1 = int4,
+	   initcond1 = '0'
+);
+ALTER AGGREGATE testagg_a(int) RENAME TO testagg_b;		-- fail
+ERROR:  function testagg_b(integer) already exists in schema "testschema_1"
+ALTER AGGREGATE testagg_b(int) SET SCHEMA testschema_2;	-- OK
+ALTER AGGREGATE testagg_a(int) RENAME TO testagg_b;		-- OK
+ALTER AGGREGATE testagg_b(int) SET SCHEMA testschema_2;	-- fail
+ERROR:  function "testagg_b" already exists in schema "testschema_2"
+--
+-- TYPE
+--
+CREATE TYPE testtype_a;
+CREATE TYPE testtype_b;
+CREATE FUNCTION testtype_a_in (cstring) RETURNS testtype_a LANGUAGE 'internal' AS 'int4in';
+NOTICE:  return type testtype_a is only a shell
+CREATE FUNCTION testtype_b_in (cstring) RETURNS testtype_b LANGUAGE 'internal' AS 'int4in';
+NOTICE:  return type testtype_b is only a shell
+CREATE FUNCTION testtype_a_out (testtype_a) RETURNS cstring LANGUAGE 'internal' AS 'int4out';
+NOTICE:  argument type testtype_a is only a shell
+CREATE FUNCTION testtype_b_out (testtype_b) RETURNS cstring LANGUAGE 'internal' AS 'int4out';
+NOTICE:  argument type testtype_b is only a shell
+CREATE TYPE testtype_a (internallength = 4, input = testtype_a_in, output = testtype_a_out);
+CREATE TYPE testtype_b (internallength = 4, input = testtype_b_in, output = testtype_b_out);
+ALTER TYPE testtype_a RENAME TO testtype_b;		-- fail
+ERROR:  type "testtype_b" already exists
+ALTER TYPE testtype_b SET SCHEMA testschema_2;	-- OK
+ALTER TYPE testtype_a RENAME TO testtype_b;		-- OK
+ALTER TYPE testtype_b SET SCHEMA testschema_2;	-- fail
+ERROR:  type "testtype_b" already exists in schema "testschema_2"
+--
+-- OPERATOR, OPERATOR FAMILY and OPERATOR CLASS
+--
+CREATE OPERATOR @#@
+	   (leftarg = int8, rightarg = int8, procedure = int8xor);
+ALTER OPERATOR @#@(int8,int8) SET SCHEMA testschema_2;	-- OK
+CREATE OPERATOR @#@
+	   (leftarg = int8, rightarg = int8, procedure = int8xor);
+-- XXX - comment out due to error message with oid determinded at runtime
+-- ALTER OPERATOR @#@(int8,int8) SET SCHEMA testschema_2;	-- fail
+CREATE OPERATOR FAMILY testopfamily_a USING btree;
+CREATE OPERATOR FAMILY testopfamily_b USING btree;
+ALTER OPERATOR FAMILY testopfamily_a USING btree RENAME TO testopfamily_b;	-- fail
+ERROR:  operator family "testopfamily_b" for access method "btree" already exists in schema "testschema_1"
+ALTER OPERATOR FAMILY testopfamily_b USING btree SET SCHEMA testschema_2;	-- OK
+ALTER OPERATOR FAMILY testopfamily_a USING btree RENAME TO testopfamily_b;	-- OK
+-- XXX - comment out due to error message with oid determinded at runtime
+-- ALTER OPERATOR FAMILY testopfamily_b USING btree SET SCHEMA testschema_2;	-- fail
+CREATE OPERATOR CLASS testopclass_a
+	   FOR TYPE box USING btree FAMILY testopfamily_b AS OPERATOR 1 =;
+CREATE OPERATOR CLASS testopclass_b
+	   FOR TYPE circle USING btree FAMILY testopfamily_b AS OPERATOR 1 =;
+ALTER OPERATOR CLASS testopclass_a USING btree RENAME TO testopclass_b;		-- fail
+ERROR:  operator class "testopclass_b" for access method "btree" already exists in schema "testschema_1"
+ALTER OPERATOR CLASS testopclass_b USING btree SET SCHEMA testschema_2;		-- OK
+ALTER OPERATOR CLASS testopclass_a USING btree RENAME TO testopclass_b;		-- OK
+-- XXX - comment out due to error message with oid determinded at runtime
+-- ALTER OPERATOR CLASS testopclass_b USING btree SET SCHEMA testschema_2;		-- fail
+--
+-- TEXT SEARCH
+--
+CREATE TEXT SEARCH DICTIONARY testtsdict_a (
+        Template=ispell,
+        DictFile=ispell_sample,
+        AffFile=ispell_sample
+);
+CREATE TEXT SEARCH DICTIONARY testtsdict_b (
+        Template=ispell,
+        DictFile=ispell_sample,
+        AffFile=ispell_sample
+);
+ALTER TEXT SEARCH DICTIONARY testtsdict_a RENAME TO testtsdict_b;	-- fail
+ERROR:  text search dictionary "testtsdict_b" already exists
+ALTER TEXT SEARCH DICTIONARY testtsdict_b SET SCHEMA testschema_2;	-- OK
+ALTER TEXT SEARCH DICTIONARY testtsdict_a RENAME TO testtsdict_b;	-- OK
+ALTER TEXT SEARCH DICTIONARY testtsdict_b SET SCHEMA testschema_2;	-- fail
+ERROR:  text search dictionary testtsdict_b already exists in schema "testschema_2"
+CREATE TEXT SEARCH CONFIGURATION testtsconf_a (COPY=english);
+CREATE TEXT SEARCH CONFIGURATION testtsconf_b (COPY=english);
+ALTER TEXT SEARCH CONFIGURATION testtsconf_a RENAME TO testtsconf_b;	-- fail
+ERROR:  text search configuration "testtsconf_b" already exists
+ALTER TEXT SEARCH CONFIGURATION testtsconf_b SET SCHEMA testschema_2;	-- OK
+ALTER TEXT SEARCH CONFIGURATION testtsconf_a RENAME TO testtsconf_b;	-- OK
+ALTER TEXT SEARCH CONFIGURATION testtsconf_b SET SCHEMA testschema_2;	-- fail
+ERROR:  text search configuration testtsconf_b already exists in schema "testschema_2"
+--
+-- COLLATION
+--
+CREATE COLLATION testcollation_a FROM "C";
+CREATE COLLATION testcollation_b FROM "C";
+ALTER COLLATION testcollation_a RENAME TO testcollation_b;	-- fail
+ERROR:  collation "testcollation_b" for encoding "UTF8" already exists in schema "testschema_1"
+ALTER COLLATION testcollation_b SET SCHEMA testschema_2;	-- OK
+ALTER COLLATION testcollation_a RENAME TO testcollation_b;	-- OK
+ALTER COLLATION testcollation_b SET SCHEMA testschema_2;	-- fail
+ERROR:  collation "testcollation_b" for encoding "UTF8" already exists in schema "testschema_2"
+--
+-- CONVERSION
+--
+CREATE CONVERSION testconv_a FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8;
+CREATE CONVERSION testconv_b FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8;
+ALTER CONVERSION testconv_a RENAME TO testconv_b;		-- fail
+ERROR:  conversion "testconv_b" already exists in schema "testschema_1"
+ALTER CONVERSION testconv_b SET SCHEMA testschema_2;	-- OK
+ALTER CONVERSION testconv_a RENAME TO testconv_b;		-- OK
+ALTER CONVERSION testconv_b SET SCHEMA testschema_2;	-- fail
+ERROR:  conversion testconv_b already exists in schema "testschema_2"
+--
+-- SCHEMA
+--
+ALTER SCHEMA testschema_1 RENAME TO testschema_2;	-- fail
+ERROR:  schema "testschema_2" already exists
+ALTER SCHEMA testschema_1 RENAME TO testschema_3;	-- OK
+DROP SCHEMA testschema_2, testschema_3 CASCADE;
+NOTICE:  drop cascades to 31 other objects
+DETAIL:  drop cascades to table testschema_3.testtable_b
+drop cascades to view testschema_3.testview_b
+drop cascades to sequence testschema_3.testseq_b
+drop cascades to type testschema_3.testcomptype_b
+drop cascades to table testschema_3.testtable_c
+drop cascades to function testschema_3.testfunc_b(integer)
+drop cascades to function testschema_3.testagg_b(integer)
+drop cascades to type testschema_3.testtype_b
+drop cascades to function testschema_3.testtype_a_in(cstring)
+drop cascades to function testschema_3.testtype_a_out(testschema_3.testtype_b)
+drop cascades to operator testschema_3.@#@(bigint,bigint)
+drop cascades to operator family testschema_3.testopfamily_b for access method btree
+drop cascades to text search dictionary testtsdict_b
+drop cascades to text search configuration testtsconf_b
+drop cascades to collation testcollation_b
+drop cascades to conversion testconv_b
+drop cascades to table testschema_2.testtable_b
+drop cascades to view testschema_2.testview_b
+drop cascades to sequence testschema_2.testseq_b
+drop cascades to type testschema_2.testcomptype_b
+drop cascades to function testschema_2.testfunc_b(integer)
+drop cascades to function testschema_2.testagg_b(integer)
+drop cascades to type testschema_2.testtype_b
+drop cascades to function testschema_3.testtype_b_in(cstring)
+drop cascades to function testschema_3.testtype_b_out(testschema_2.testtype_b)
+drop cascades to operator testschema_2.@#@(bigint,bigint)
+drop cascades to operator family testschema_2.testopfamily_b for access method btree
+drop cascades to text search dictionary testtsdict_b
+drop cascades to text search configuration testtsconf_b
+drop cascades to collation testcollation_b
+drop cascades to conversion testconv_b
diff --git a/src/test/regress/expected/privileges.out b/src/test/regress/expected/privileges.out
index 5cda230..8aec0a4 100644
--- a/src/test/regress/expected/privileges.out
+++ b/src/test/regress/expected/privileges.out
@@ -504,7 +504,7 @@ SELECT testfunc1(5); -- ok
 (1 row)
 
 DROP FUNCTION testfunc1(int); -- fail
-ERROR:  must be owner of function testfunc1
+ERROR:  must be owner of function testfunc1(integer)
 \c -
 DROP FUNCTION testfunc1(int); -- ok
 -- restore to sanity
diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule
index b47b08b..7f590fc 100644
--- a/src/test/regress/parallel_schedule
+++ b/src/test/regress/parallel_schedule
@@ -99,7 +99,7 @@ test: select_views portals_p2 foreign_key cluster dependency guc bitmapops combo
 # NB: temp.sql does a reconnect which transiently uses 2 connections,
 # so keep this parallel group to at most 19 tests
 # ----------
-test: plancache limit plpgsql copy2 temp domain rangefuncs prepare without_oid conversion truncate alter_table sequence polymorphism rowtypes returning largeobject with xml
+test: plancache limit plpgsql copy2 temp domain rangefuncs prepare without_oid conversion truncate alter_rename alter_table sequence polymorphism rowtypes returning largeobject with xml
 
 # run stats by itself because its delay may be insufficient under heavy load
 test: stats
diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule
index 57806b5..78f63e3 100644
--- a/src/test/regress/serial_schedule
+++ b/src/test/regress/serial_schedule
@@ -119,6 +119,7 @@ test: prepare
 test: without_oid
 test: conversion
 test: truncate
+test: alter_rename
 test: alter_table
 test: sequence
 test: polymorphism
diff --git a/src/test/regress/sql/alter_rename.sql b/src/test/regress/sql/alter_rename.sql
new file mode 100644
index 0000000..9b2bdf1
--- /dev/null
+++ b/src/test/regress/sql/alter_rename.sql
@@ -0,0 +1,240 @@
+--
+-- ALTER xxx RENAME TO/SET SCHEMA statement
+--
+
+CREATE SCHEMA testschema_1;
+CREATE SCHEMA testschema_2;
+
+SET search_path = testschema_1, public;
+
+--
+-- ROLE
+--
+CREATE ROLE testrole_1;
+CREATE ROLE testrole_2;
+
+ALTER ROLE testrole_1 RENAME TO testrole_2;		-- fail
+ALTER ROLE testrole_1 RENAME TO testrole_3;		-- OK
+
+DROP ROLE testrole_2, testrole_3;
+
+--
+-- LANGUAGE
+--
+CREATE LANGUAGE testlang_1 HANDLER plpgsql_call_handler;
+CREATE LANGUAGE testlang_2 HANDLER plpgsql_call_handler;
+
+ALTER LANGUAGE testlang_1 RENAME TO testlang_2;	-- fail
+ALTER LANGUAGE testlang_1 RENAME TO testlang_3;	-- OK
+
+DROP LANGUAGE testlang_2;
+DROP LANGUAGE testlang_3;
+
+--
+-- TABLE
+--
+CREATE TABLE testtable_a(a int, b int);
+CREATE TABLE testtable_b(x int, y int);
+ALTER TABLE testtable_a RENAME TO testtable_b;		-- fail
+ALTER TABLE testtable_b SET SCHEMA testschema_2;	-- OK
+ALTER TABLE testtable_a RENAME TO testtable_b;		-- OK
+ALTER TABLE testtable_b SET SCHEMA testschema_2;	-- fail
+
+--
+-- VIEW
+--
+CREATE VIEW testview_a AS SELECT * FROM pg_class WHERE relname like 'pg_%';
+CREATE VIEW testview_b AS SELECT * FROM pg_class WHERE relname like 'pg_%';
+ALTER VIEW testview_a RENAME TO testview_b;		-- fail
+ALTER VIEW testview_b SET SCHEMA testschema_2;	-- OK
+ALTER VIEW testview_a RENAME TO testview_b;		-- OK
+ALTER VIEW testview_b SET SCHEMA testschema_2;	-- fail
+ALTER VIEW testtable_b SET SCHEMA public;		-- fail
+ALTER VIEW testtable_b RENAME TO testtable_c;	-- fail
+
+--
+-- SEQUENCE
+--
+CREATE SEQUENCE testseq_a;
+CREATE SEQUENCE testseq_b;
+ALTER SEQUENCE testseq_a RENAME TO testseq_b;		-- fail
+ALTER SEQUENCE testseq_b SET SCHEMA testschema_2;	-- OK
+ALTER SEQUENCE testseq_a RENAME TO testseq_b;		-- OK
+ALTER SEQUENCE testseq_b SET SCHEMA testschema_2;	-- fail
+ALTER SEQUENCE testview_b SET SCHEMA public;		-- fail
+ALTER SEQUENCE testview_b RENAME TO testview_c;		-- fail
+
+--
+-- COMPOSITE TYPE
+--
+CREATE TYPE testcomptype_a AS (a int, b int);
+CREATE TYPE testcomptype_b AS (a int, b int);
+ALTER TYPE testcomptype_a RENAME TO testcomptype_b;	-- fail
+ALTER TYPE testcomptype_b SET SCHEMA testschema_2;	-- OK
+ALTER TYPE testcomptype_a RENAME TO testcomptype_b;	-- OK
+ALTER TYPE testcomptype_b SET SCHEMA testschema_2;	-- fail
+ALTER TYPE testseq_b SET SCHEMA public;				-- fail
+ALTER TYPE testseq_b RENAME TO testseq_c;			-- fail
+
+--
+-- INDEX
+--
+CREATE INDEX testindex_a ON testtable_b (a);
+CREATE INDEX testindex_b ON testtable_b (b);
+ALTER INDEX testindex_a RENAME TO testindex_b;		-- fail
+ALTER INDEX testindex_a RENAME TO testindex_c;		-- OK
+
+--
+-- COLUMN
+--
+ALTER TABLE testtable_b RENAME a TO b;		-- fail
+ALTER TABLE testtable_b RENAME a TO x;		-- OK
+CREATE TABLE testtable_c (z int) INHERITS (testtable_b);
+ALTER TABLE ONLY testtable_b RENAME b TO y;	-- fail
+ALTER TABLE testtable_b RENAME b TO y;		-- OK
+ALTER TABLE testtable_c RENAME z TO zz;		-- OK
+ALTER TABLE testtable_c RENAME x TO xx;		-- fail
+
+--
+-- TRIGGER
+--
+CREATE TRIGGER testtrigger_a
+    BEFORE UPDATE ON testtable_b
+    FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger();
+CREATE TRIGGER testtrigger_b
+    BEFORE UPDATE ON testtable_b
+    FOR EACH ROW EXECUTE PROCEDURE suppress_redundant_updates_trigger();
+ALTER TRIGGER testtrigger_a ON testtable_b RENAME TO testtrigger_b;	-- fail
+ALTER TRIGGER testtrigger_a ON testtable_b RENAME TO testtrigger_c;	-- OK
+
+
+--
+-- FUNCTION, AGGREGATE
+--
+CREATE FUNCTION testfunc_a(int)
+	   RETURNS int LANGUAGE sql
+	   AS 'SELECT $1 + $1';
+CREATE FUNCTION testfunc_b(int)
+	   RETURNS int LANGUAGE sql
+	   AS 'SELECT $1 + $1';
+ALTER FUNCTION testfunc_a(int) RENAME TO testfunc_b;	-- fail
+ALTER FUNCTION testfunc_b(int) SET SCHEMA testschema_2;	-- OK
+ALTER FUNCTION testfunc_a(int) RENAME TO testfunc_b;	-- OK
+ALTER FUNCTION testfunc_b(int) SET SCHEMA testschema_2;	-- fail
+
+
+CREATE AGGREGATE testagg_a(
+	   sfunc1 = int4pl, basetype = int4, stype1 = int4,
+	   initcond1 = '0'
+);
+CREATE AGGREGATE testagg_b(
+	   sfunc1 = int4pl, basetype = int4, stype1 = int4,
+	   initcond1 = '0'
+);
+ALTER AGGREGATE testagg_a(int) RENAME TO testagg_b;		-- fail
+ALTER AGGREGATE testagg_b(int) SET SCHEMA testschema_2;	-- OK
+ALTER AGGREGATE testagg_a(int) RENAME TO testagg_b;		-- OK
+ALTER AGGREGATE testagg_b(int) SET SCHEMA testschema_2;	-- fail
+
+--
+-- TYPE
+--
+CREATE TYPE testtype_a;
+CREATE TYPE testtype_b;
+CREATE FUNCTION testtype_a_in (cstring) RETURNS testtype_a LANGUAGE 'internal' AS 'int4in';
+CREATE FUNCTION testtype_b_in (cstring) RETURNS testtype_b LANGUAGE 'internal' AS 'int4in';
+CREATE FUNCTION testtype_a_out (testtype_a) RETURNS cstring LANGUAGE 'internal' AS 'int4out';
+CREATE FUNCTION testtype_b_out (testtype_b) RETURNS cstring LANGUAGE 'internal' AS 'int4out';
+CREATE TYPE testtype_a (internallength = 4, input = testtype_a_in, output = testtype_a_out);
+CREATE TYPE testtype_b (internallength = 4, input = testtype_b_in, output = testtype_b_out);
+
+ALTER TYPE testtype_a RENAME TO testtype_b;		-- fail
+ALTER TYPE testtype_b SET SCHEMA testschema_2;	-- OK
+ALTER TYPE testtype_a RENAME TO testtype_b;		-- OK
+ALTER TYPE testtype_b SET SCHEMA testschema_2;	-- fail
+
+--
+-- OPERATOR, OPERATOR FAMILY and OPERATOR CLASS
+--
+
+CREATE OPERATOR @#@
+	   (leftarg = int8, rightarg = int8, procedure = int8xor);
+ALTER OPERATOR @#@(int8,int8) SET SCHEMA testschema_2;	-- OK
+CREATE OPERATOR @#@
+	   (leftarg = int8, rightarg = int8, procedure = int8xor);
+-- XXX - comment out due to error message with oid determinded at runtime
+-- ALTER OPERATOR @#@(int8,int8) SET SCHEMA testschema_2;	-- fail
+
+CREATE OPERATOR FAMILY testopfamily_a USING btree;
+CREATE OPERATOR FAMILY testopfamily_b USING btree;
+ALTER OPERATOR FAMILY testopfamily_a USING btree RENAME TO testopfamily_b;	-- fail
+ALTER OPERATOR FAMILY testopfamily_b USING btree SET SCHEMA testschema_2;	-- OK
+ALTER OPERATOR FAMILY testopfamily_a USING btree RENAME TO testopfamily_b;	-- OK
+-- XXX - comment out due to error message with oid determinded at runtime
+-- ALTER OPERATOR FAMILY testopfamily_b USING btree SET SCHEMA testschema_2;	-- fail
+
+
+CREATE OPERATOR CLASS testopclass_a
+	   FOR TYPE box USING btree FAMILY testopfamily_b AS OPERATOR 1 =;
+CREATE OPERATOR CLASS testopclass_b
+	   FOR TYPE circle USING btree FAMILY testopfamily_b AS OPERATOR 1 =;
+ALTER OPERATOR CLASS testopclass_a USING btree RENAME TO testopclass_b;		-- fail
+ALTER OPERATOR CLASS testopclass_b USING btree SET SCHEMA testschema_2;		-- OK
+ALTER OPERATOR CLASS testopclass_a USING btree RENAME TO testopclass_b;		-- OK
+-- XXX - comment out due to error message with oid determinded at runtime
+-- ALTER OPERATOR CLASS testopclass_b USING btree SET SCHEMA testschema_2;		-- fail
+
+--
+-- TEXT SEARCH
+--
+CREATE TEXT SEARCH DICTIONARY testtsdict_a (
+        Template=ispell,
+        DictFile=ispell_sample,
+        AffFile=ispell_sample
+);
+CREATE TEXT SEARCH DICTIONARY testtsdict_b (
+        Template=ispell,
+        DictFile=ispell_sample,
+        AffFile=ispell_sample
+);
+ALTER TEXT SEARCH DICTIONARY testtsdict_a RENAME TO testtsdict_b;	-- fail
+ALTER TEXT SEARCH DICTIONARY testtsdict_b SET SCHEMA testschema_2;	-- OK
+ALTER TEXT SEARCH DICTIONARY testtsdict_a RENAME TO testtsdict_b;	-- OK
+ALTER TEXT SEARCH DICTIONARY testtsdict_b SET SCHEMA testschema_2;	-- fail
+
+CREATE TEXT SEARCH CONFIGURATION testtsconf_a (COPY=english);
+CREATE TEXT SEARCH CONFIGURATION testtsconf_b (COPY=english);
+ALTER TEXT SEARCH CONFIGURATION testtsconf_a RENAME TO testtsconf_b;	-- fail
+ALTER TEXT SEARCH CONFIGURATION testtsconf_b SET SCHEMA testschema_2;	-- OK
+ALTER TEXT SEARCH CONFIGURATION testtsconf_a RENAME TO testtsconf_b;	-- OK
+ALTER TEXT SEARCH CONFIGURATION testtsconf_b SET SCHEMA testschema_2;	-- fail
+
+--
+-- COLLATION
+--
+CREATE COLLATION testcollation_a FROM "C";
+CREATE COLLATION testcollation_b FROM "C";
+
+ALTER COLLATION testcollation_a RENAME TO testcollation_b;	-- fail
+ALTER COLLATION testcollation_b SET SCHEMA testschema_2;	-- OK
+ALTER COLLATION testcollation_a RENAME TO testcollation_b;	-- OK
+ALTER COLLATION testcollation_b SET SCHEMA testschema_2;	-- fail
+
+--
+-- CONVERSION
+--
+CREATE CONVERSION testconv_a FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8;
+CREATE CONVERSION testconv_b FOR 'LATIN1' TO 'UTF8' FROM iso8859_1_to_utf8;
+
+ALTER CONVERSION testconv_a RENAME TO testconv_b;		-- fail
+ALTER CONVERSION testconv_b SET SCHEMA testschema_2;	-- OK
+ALTER CONVERSION testconv_a RENAME TO testconv_b;		-- OK
+ALTER CONVERSION testconv_b SET SCHEMA testschema_2;	-- fail
+
+--
+-- SCHEMA
+--
+ALTER SCHEMA testschema_1 RENAME TO testschema_2;	-- fail
+ALTER SCHEMA testschema_1 RENAME TO testschema_3;	-- OK
+
+DROP SCHEMA testschema_2, testschema_3 CASCADE;