>From f651595fa4d999f719d30c19e6b5b7d3a1dc8020 Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Thu, 26 Feb 2015 13:03:29 -0300
Subject: [PATCH 6/7] Have ALTER/SET SCHEMA return the original schema's
 ObjectAddress

This lets ddl_command_end event triggers know what the original schema
was, since when they are run the catalogs have already changed.

This isn't terribly exciting in itself but it supports future event
trigger changes.
---
 src/backend/commands/alter.c     | 34 +++++++++++++++++++++++++---------
 src/backend/commands/extension.c |  6 +++++-
 src/backend/commands/tablecmds.c |  5 ++++-
 src/backend/commands/typecmds.c  |  9 +++++++--
 src/backend/tcop/utility.c       |  5 +++--
 src/include/commands/alter.h     |  3 ++-
 src/include/commands/extension.h |  3 ++-
 src/include/commands/tablecmds.h |  3 ++-
 src/include/commands/typecmds.h  |  2 +-
 9 files changed, 51 insertions(+), 19 deletions(-)

diff --git a/src/backend/commands/alter.c b/src/backend/commands/alter.c
index e4d6d8c..81c7bed 100644
--- a/src/backend/commands/alter.c
+++ b/src/backend/commands/alter.c
@@ -393,26 +393,39 @@ ExecRenameStmt(RenameStmt *stmt)
 /*
  * Executes an ALTER OBJECT / SET SCHEMA statement.  Based on the object
  * type, the function appropriate to that type is executed.
+ *
+ * Return value is that of the altered object.  oldSchemaAddr, if not NULL, is
+ * set to the object address of the original schema.
  */
 ObjectAddress
-ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt)
+ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt,
+						  ObjectAddress *oldSchemaAddr)
 {
+	ObjectAddress	address;
+	Oid			oldNspOid;
+
 	switch (stmt->objectType)
 	{
 		case OBJECT_EXTENSION:
-			return AlterExtensionNamespace(stmt->object, stmt->newschema);
+			address = AlterExtensionNamespace(stmt->object, stmt->newschema,
+											  oldSchemaAddr ? &oldNspOid : NULL);
+			break;
 
 		case OBJECT_FOREIGN_TABLE:
 		case OBJECT_SEQUENCE:
 		case OBJECT_TABLE:
 		case OBJECT_VIEW:
 		case OBJECT_MATVIEW:
-			return AlterTableNamespace(stmt);
+			address = AlterTableNamespace(stmt,
+										  oldSchemaAddr ? &oldNspOid : NULL);
+			break;
 
 		case OBJECT_DOMAIN:
 		case OBJECT_TYPE:
-			return AlterTypeNamespace(stmt->object, stmt->newschema,
-									  stmt->objectType);
+			address = AlterTypeNamespace(stmt->object, stmt->newschema,
+										 stmt->objectType,
+										 oldSchemaAddr ? &oldNspOid : NULL);
+			break;
 
 			/* generic code path */
 		case OBJECT_AGGREGATE:
@@ -444,11 +457,9 @@ ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt)
 				catalog = heap_open(classId, RowExclusiveLock);
 				nspOid = LookupCreationNamespace(stmt->newschema);
 
-				AlterObjectNamespace_internal(catalog, address.objectId,
-											  nspOid);
+				oldNspOid = AlterObjectNamespace_internal(catalog, address.objectId,
+														  nspOid);
 				heap_close(catalog, RowExclusiveLock);
-
-				return address;
 			}
 			break;
 
@@ -457,6 +468,11 @@ ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt)
 				 (int) stmt->objectType);
 			return InvalidObjectAddress;	/* keep compiler happy */
 	}
+
+	if (oldSchemaAddr)
+		ObjectAddressSet(*oldSchemaAddr, NamespaceRelationId, oldNspOid);
+
+	return address;
 }
 
 /*
diff --git a/src/backend/commands/extension.c b/src/backend/commands/extension.c
index 71c5d68..7ed9321 100644
--- a/src/backend/commands/extension.c
+++ b/src/backend/commands/extension.c
@@ -2402,7 +2402,7 @@ extension_config_remove(Oid extensionoid, Oid tableoid)
  * Execute ALTER EXTENSION SET SCHEMA
  */
 ObjectAddress
-AlterExtensionNamespace(List *names, const char *newschema)
+AlterExtensionNamespace(List *names, const char *newschema, Oid *oldschema)
 {
 	char	   *extensionName;
 	Oid			extensionOid;
@@ -2560,6 +2560,10 @@ AlterExtensionNamespace(List *names, const char *newschema)
 							   get_namespace_name(oldNspOid))));
 	}
 
+	/* report old schema, if caller wants it */
+	if (oldschema)
+		*oldschema = oldNspOid;
+
 	systable_endscan(depScan);
 
 	relation_close(depRel, AccessShareLock);
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 733b987..92099a2 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -11048,7 +11048,7 @@ ATPrepChangePersistence(Relation rel, bool toLogged)
  * Execute ALTER TABLE SET SCHEMA
  */
 ObjectAddress
-AlterTableNamespace(AlterObjectSchemaStmt *stmt)
+AlterTableNamespace(AlterObjectSchemaStmt *stmt, Oid *oldschema)
 {
 	Relation	rel;
 	Oid			relid;
@@ -11103,6 +11103,9 @@ AlterTableNamespace(AlterObjectSchemaStmt *stmt)
 
 	ObjectAddressSet(myself, RelationRelationId, relid);
 
+	if (oldschema)
+		*oldschema = oldNspOid;
+
 	/* close rel, but keep lock until commit */
 	relation_close(rel, NoLock);
 
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index e246719..4df7e64 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -3540,11 +3540,13 @@ AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId,
  * Execute ALTER TYPE SET SCHEMA
  */
 ObjectAddress
-AlterTypeNamespace(List *names, const char *newschema, ObjectType objecttype)
+AlterTypeNamespace(List *names, const char *newschema, ObjectType objecttype,
+				   Oid *oldschema)
 {
 	TypeName   *typename;
 	Oid			typeOid;
 	Oid			nspOid;
+	Oid			oldNspOid;
 	ObjectAddresses *objsMoved;
 	ObjectAddress myself;
 
@@ -3563,9 +3565,12 @@ AlterTypeNamespace(List *names, const char *newschema, ObjectType objecttype)
 	nspOid = LookupCreationNamespace(newschema);
 
 	objsMoved = new_object_addresses();
-	AlterTypeNamespace_oid(typeOid, nspOid, objsMoved);
+	oldNspOid = AlterTypeNamespace_oid(typeOid, nspOid, objsMoved);
 	free_object_addresses(objsMoved);
 
+	if (oldschema)
+		*oldschema = oldNspOid;
+
 	ObjectAddressSet(myself, TypeRelationId, typeOid);
 
 	return myself;
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 33b20b8..2f34c03 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -818,7 +818,7 @@ standard_ProcessUtility(Node *parsetree,
 									   context, params,
 									   dest, completionTag);
 				else
-					ExecAlterObjectSchemaStmt(stmt);
+					ExecAlterObjectSchemaStmt(stmt, NULL);
 			}
 			break;
 
@@ -1336,7 +1336,8 @@ ProcessUtilitySlow(Node *parsetree,
 				break;
 
 			case T_AlterObjectSchemaStmt:
-				ExecAlterObjectSchemaStmt((AlterObjectSchemaStmt *) parsetree);
+				ExecAlterObjectSchemaStmt((AlterObjectSchemaStmt *) parsetree,
+										  NULL);
 				break;
 
 			case T_AlterOwnerStmt:
diff --git a/src/include/commands/alter.h b/src/include/commands/alter.h
index 46d22fd..be68890 100644
--- a/src/include/commands/alter.h
+++ b/src/include/commands/alter.h
@@ -21,7 +21,8 @@
 
 extern ObjectAddress ExecRenameStmt(RenameStmt *stmt);
 
-extern ObjectAddress ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt);
+extern ObjectAddress ExecAlterObjectSchemaStmt(AlterObjectSchemaStmt *stmt,
+						  ObjectAddress *oldSchemaAddr);
 extern Oid AlterObjectNamespace_oid(Oid classId, Oid objid, Oid nspOid,
 						 ObjectAddresses *objsMoved);
 
diff --git a/src/include/commands/extension.h b/src/include/commands/extension.h
index 5640cac..40ecea2 100644
--- a/src/include/commands/extension.h
+++ b/src/include/commands/extension.h
@@ -45,7 +45,8 @@ extern ObjectAddress ExecAlterExtensionContentsStmt(AlterExtensionContentsStmt *
 extern Oid	get_extension_oid(const char *extname, bool missing_ok);
 extern char *get_extension_name(Oid ext_oid);
 
-extern ObjectAddress AlterExtensionNamespace(List *names, const char *newschema);
+extern ObjectAddress AlterExtensionNamespace(List *names, const char *newschema,
+						Oid *oldschema);
 
 extern void AlterExtensionOwner_oid(Oid extensionOid, Oid newOwnerId);
 
diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h
index 2027a8c..f269c63 100644
--- a/src/include/commands/tablecmds.h
+++ b/src/include/commands/tablecmds.h
@@ -39,7 +39,8 @@ extern void AlterTableInternal(Oid relid, List *cmds, bool recurse);
 
 extern Oid	AlterTableMoveAll(AlterTableMoveAllStmt *stmt);
 
-extern ObjectAddress AlterTableNamespace(AlterObjectSchemaStmt *stmt);
+extern ObjectAddress AlterTableNamespace(AlterObjectSchemaStmt *stmt,
+					Oid *oldschema);
 
 extern void AlterTableNamespaceInternal(Relation rel, Oid oldNspOid,
 							Oid nspOid, ObjectAddresses *objsMoved);
diff --git a/src/include/commands/typecmds.h b/src/include/commands/typecmds.h
index d9bd9d8..2cca88d 100644
--- a/src/include/commands/typecmds.h
+++ b/src/include/commands/typecmds.h
@@ -46,7 +46,7 @@ extern ObjectAddress AlterTypeOwner(List *names, Oid newOwnerId, ObjectType obje
 extern void AlterTypeOwnerInternal(Oid typeOid, Oid newOwnerId,
 					   bool hasDependEntry);
 extern ObjectAddress AlterTypeNamespace(List *names, const char *newschema,
-				   ObjectType objecttype);
+				   ObjectType objecttype, Oid *oldschema);
 extern Oid	AlterTypeNamespace_oid(Oid typeOid, Oid nspOid, ObjectAddresses *objsMoved);
 extern Oid AlterTypeNamespaceInternal(Oid typeOid, Oid nspOid,
 						   bool isImplicitArray,
-- 
2.1.4

