From 3d9f865e94b2e7b926ef083dd555ecc7d33bccf9 Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Wed, 6 Mar 2002 19:58:26 +0000
Subject: [PATCH] Modify ALTER TABLE OWNER to change index ownership;  code
 cleanup.

Neil Conway
---
 src/backend/commands/command.c    | 113 +++++++++++++++++++-----------
 src/backend/utils/adt/ruleutils.c |  29 +-------
 2 files changed, 76 insertions(+), 66 deletions(-)

diff --git a/src/backend/commands/command.c b/src/backend/commands/command.c
index 4a2edd61bc0..b166ed539cd 100644
--- a/src/backend/commands/command.c
+++ b/src/backend/commands/command.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.159 2002/03/06 06:09:29 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/Attic/command.c,v 1.160 2002/03/06 19:58:26 momjian Exp $
  *
  * NOTES
  *	  The PerformAddAttribute() code, like most of the relation
@@ -53,10 +53,10 @@
 #include "utils/relcache.h"
 #include "utils/temprel.h"
 
-
 static void drop_default(Oid relid, int16 attnum);
 static bool needs_toast_table(Relation rel);
-
+static void AlterTableOwnerId(Oid relationOid, int32 newOwnerSysId);
+static void CheckTupleType(Form_pg_class tuple_class);
 
 /* --------------------------------
  *		PortalCleanup
@@ -1559,59 +1559,58 @@ AlterTableDropConstraint(const char *relationName,
 		elog(NOTICE, "Multiple constraints dropped");
 }
 
-
 /*
  * ALTER TABLE OWNER
  */
 void
 AlterTableOwner(const char *relationName, const char *newOwnerName)
 {
-	Relation	class_rel;
-	HeapTuple	tuple;
-	int32		newOwnerSysid;
-	Relation	idescs[Num_pg_class_indices];
+	Oid relationOid;
+	Relation relation;
+	int32 newOwnerSysId;
 
-	/*
-	 * first check that we are a superuser
-	 */
+	/* check that we are the superuser */
 	if (!superuser())
 		elog(ERROR, "ALTER TABLE: permission denied");
 
-	/*
-	 * look up the new owner in pg_shadow and get the sysid
-	 */
-	newOwnerSysid = get_usesysid(newOwnerName);
+	/* lookup the OID of the target relation */
+	relation = RelationNameGetRelation(relationName);
+	relationOid = relation->rd_id;
+	RelationClose(relation);
 
-	/*
-	 * find the table's entry in pg_class and make a modifiable copy
-	 */
-	class_rel = heap_openr(RelationRelationName, RowExclusiveLock);
+	/* lookup the sysid of the new owner */
+	newOwnerSysId = get_usesysid(newOwnerName);
+
+	/* do all the actual work */
+	AlterTableOwnerId(relationOid, newOwnerSysId);
+}
 
-	tuple = SearchSysCacheCopy(RELNAME,
-							   PointerGetDatum(relationName),
+static void
+AlterTableOwnerId(Oid relationOid, int32 newOwnerSysId)
+{
+	Relation		class_rel;
+	HeapTuple		tuple;
+	Relation		idescs[Num_pg_class_indices];
+	Form_pg_class	tuple_class;
+
+	tuple = SearchSysCacheCopy(RELOID,
+							   ObjectIdGetDatum(relationOid),
 							   0, 0, 0);
 	if (!HeapTupleIsValid(tuple))
-		elog(ERROR, "ALTER TABLE: relation \"%s\" not found",
-			 relationName);
+		elog(ERROR, "ALTER TABLE: object ID %hd not found",
+				relationOid);
 
-	switch (((Form_pg_class) GETSTRUCT(tuple))->relkind)
-	{
-		case RELKIND_RELATION:
-		case RELKIND_INDEX:
-		case RELKIND_VIEW:
-		case RELKIND_SEQUENCE:
-			/* ok to change owner */
-			break;
-		default:
-			elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table, index, view, or sequence",
-				 relationName);
-	}
+	tuple_class = (Form_pg_class) GETSTRUCT(tuple);
+
+	/* Can we change the ownership of this tuple? */
+	CheckTupleType(tuple_class);
 
 	/*
-	 * modify the table's entry and write to the heap
+	 * Okay, this is a valid tuple: change its ownership and
+	 * write to the heap.
 	 */
-	((Form_pg_class) GETSTRUCT(tuple))->relowner = newOwnerSysid;
-
+	class_rel = heap_openr(RelationRelationName, RowExclusiveLock);
+	tuple_class->relowner = newOwnerSysId;
 	simple_heap_update(class_rel, &tuple->t_self, tuple);
 
 	/* Keep the catalog indices up to date */
@@ -1620,12 +1619,48 @@ AlterTableOwner(const char *relationName, const char *newOwnerName)
 	CatalogCloseIndices(Num_pg_class_indices, idescs);
 
 	/*
-	 * unlock everything and return
+	 * If we are operating on a table, also change the ownership
+	 * of all of its indexes.
 	 */
+	if (tuple_class->relkind == RELKIND_RELATION)
+	{
+		Relation target_rel;
+		List *index_oid_list, *i;
+
+		/* Find all the indexes belonging to this relation */
+		target_rel = heap_open(relationOid, RowExclusiveLock);
+		index_oid_list = RelationGetIndexList(target_rel);
+		heap_close(target_rel, RowExclusiveLock);
+
+		/* For each index, recursively change its ownership */
+		foreach (i, index_oid_list)
+		{
+			AlterTableOwnerId(lfirsti(i), newOwnerSysId);
+		}
+
+		freeList(index_oid_list);
+	}
+
 	heap_freetuple(tuple);
 	heap_close(class_rel, NoLock);
 }
 
+static void
+CheckTupleType(Form_pg_class tuple_class)
+{
+	switch (tuple_class->relkind)
+	{
+		case RELKIND_RELATION:
+		case RELKIND_INDEX:
+		case RELKIND_VIEW:
+		case RELKIND_SEQUENCE:
+			/* ok to change owner */
+			break;
+		default:
+			elog(ERROR, "ALTER TABLE: relation \"%s\" is not a table, index, view, or sequence",
+				 NameStr(tuple_class->relname));
+	}
+}
 
 /*
  * ALTER TABLE CREATE TOAST TABLE
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index 2d14e4ff752..169bcd23e29 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -3,7 +3,7 @@
  *				back to source text
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.91 2002/03/06 06:10:16 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/utils/adt/ruleutils.c,v 1.92 2002/03/06 19:58:26 momjian Exp $
  *
  *	  This software is copyrighted by Jan Wieck - Hamburg.
  *
@@ -141,7 +141,6 @@ static void get_opclass_name(Oid opclass, Oid actual_datatype,
 				 StringInfo buf);
 static bool tleIsArrayAssign(TargetEntry *tle);
 static char *quote_identifier(char *ident);
-static char *get_relation_name(Oid relid);
 static char *get_relid_attribute_name(Oid relid, AttrNumber attnum);
 
 #define only_marker(rte)  ((rte)->inh ? "" : "ONLY ")
@@ -752,7 +751,7 @@ make_ruledef(StringInfo buf, HeapTuple ruletup, TupleDesc rulettc)
 
 	/* The relation the rule is fired on */
 	appendStringInfo(buf, " TO %s",
-					 quote_identifier(get_relation_name(ev_class)));
+					 quote_identifier(get_rel_name(ev_class)));
 	if (ev_attr > 0)
 		appendStringInfo(buf, ".%s",
 					  quote_identifier(get_relid_attribute_name(ev_class,
@@ -2697,30 +2696,6 @@ quote_identifier(char *ident)
 	return result;
 }
 
-/* ----------
- * get_relation_name			- Get a relation name by Oid
- * ----------
- */
-static char *
-get_relation_name(Oid relid)
-{
-	HeapTuple	classtup;
-	Form_pg_class classStruct;
-	char	   *result;
-
-	classtup = SearchSysCache(RELOID,
-							  ObjectIdGetDatum(relid),
-							  0, 0, 0);
-	if (!HeapTupleIsValid(classtup))
-		elog(ERROR, "cache lookup of relation %u failed", relid);
-
-	classStruct = (Form_pg_class) GETSTRUCT(classtup);
-	result = pstrdup(NameStr(classStruct->relname));
-	ReleaseSysCache(classtup);
-	return result;
-}
-
-
 /* ----------
  * get_relid_attribute_name
  *		Get an attribute name by its relations Oid and its attnum
-- 
GitLab