From e49c1a9234cdce95a263801136cbbcb1082531e5 Mon Sep 17 00:00:00 2001
From: Bruce Momjian <bruce@momjian.us>
Date: Mon, 21 Oct 2002 20:31:52 +0000
Subject: [PATCH] Fix ALTER TABLE ... ADD COLUMN for inheritance cases.

Alvaro Herrera
---
 src/backend/commands/tablecmds.c    | 50 ++++++++++++++++++++++-------
 src/backend/tcop/utility.c          |  3 +-
 src/include/commands/tablecmds.h    |  5 ++-
 src/test/regress/output/misc.source |  1 +
 4 files changed, 42 insertions(+), 17 deletions(-)

diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 52e2ee5b7c1..ae15b815332 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.48 2002/10/19 03:01:09 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.49 2002/10/21 20:31:51 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1584,7 +1584,6 @@ update_ri_trigger_args(Oid relid,
 void
 AlterTableAddColumn(Oid myrelid,
 					bool recurse,
-					bool recursing,
 					ColumnDef *colDef)
 {
 	Relation	rel,
@@ -1643,22 +1642,50 @@ AlterTableAddColumn(Oid myrelid,
 		colDefChild->inhcount = 1;
 		colDefChild->is_local = false;
 
-		/* this routine is actually in the planner */
-		children = find_all_inheritors(myrelid);
+		/* We only want direct inheritors */
+		children = find_inheritance_children(myrelid);
 
-		/*
-		 * find_all_inheritors does the recursive search of the
-		 * inheritance hierarchy, so all we have to do is process all of
-		 * the relids in the list that it returns.
-		 */
 		foreach(child, children)
 		{
 			Oid			childrelid = lfirsti(child);
+			HeapTuple	tuple;
+			Form_pg_attribute childatt;
+			Relation	childrel;
 
 			if (childrelid == myrelid)
 				continue;
 
-			AlterTableAddColumn(childrelid, false, true, colDefChild);
+			attrdesc = heap_openr(AttributeRelationName, RowExclusiveLock);
+			tuple = SearchSysCacheCopyAttName(childrelid, colDef->colname);
+			if (!HeapTupleIsValid(tuple))
+			{
+				heap_close(attrdesc, RowExclusiveLock);
+				AlterTableAddColumn(childrelid, true, colDefChild);
+				continue;
+			}
+			childatt = (Form_pg_attribute) GETSTRUCT(tuple);
+
+			typeTuple = typenameType(colDef->typename);
+
+			if (HeapTupleGetOid(typeTuple) != childatt->atttypid ||
+					colDef->typename->typmod != childatt->atttypmod)
+				elog(ERROR, "ALTER TABLE: child table %u has different "
+						"type for column \"%s\"",
+						childrelid, colDef->colname);
+
+			childatt->attinhcount++;
+			simple_heap_update(attrdesc, &tuple->t_self, tuple);
+			CatalogUpdateIndexes(attrdesc, tuple);
+			
+			childrel = RelationIdGetRelation(childrelid);
+			elog(NOTICE, "ALTER TABLE: merging definition of column "
+					"\"%s\" for child %s", colDef->colname,
+					RelationGetRelationName(childrel));
+			RelationClose(childrel);
+
+			heap_close(attrdesc, RowExclusiveLock);
+			heap_freetuple(tuple);
+			ReleaseSysCache(typeTuple);
 		}
 	}
 	else
@@ -1667,8 +1694,7 @@ AlterTableAddColumn(Oid myrelid,
 		 * If we are told not to recurse, there had better not be any
 		 * child tables; else the addition would put them out of step.
 		 */
-		if (!recursing &&
-			find_inheritance_children(myrelid) != NIL)
+		if (find_inheritance_children(myrelid) != NIL)
 			elog(ERROR, "Attribute must be added to child tables too");
 	}
 
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 1b857a816d4..1c3ea71d2fe 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.179 2002/10/08 17:17:19 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/tcop/utility.c,v 1.180 2002/10/21 20:31:52 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -475,7 +475,6 @@ ProcessUtility(Node *parsetree,
 						 */
 						AlterTableAddColumn(relid,
 							  interpretInhOption(stmt->relation->inhOpt),
-											false,
 											(ColumnDef *) stmt->def);
 						break;
 					case 'T':	/* ALTER COLUMN DEFAULT */
diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h
index b4bb0f0a283..d2a05578369 100644
--- a/src/include/commands/tablecmds.h
+++ b/src/include/commands/tablecmds.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: tablecmds.h,v 1.7 2002/09/04 20:31:42 momjian Exp $
+ * $Id: tablecmds.h,v 1.8 2002/10/21 20:31:52 momjian Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,8 +16,7 @@
 
 #include "nodes/parsenodes.h"
 
-extern void AlterTableAddColumn(Oid myrelid, bool recurse, bool recursing,
-					ColumnDef *colDef);
+extern void AlterTableAddColumn(Oid myrelid, bool recurse, ColumnDef *colDef);
 
 extern void AlterTableAlterColumnDropNotNull(Oid myrelid, bool recurse,
 								 const char *colName);
diff --git a/src/test/regress/output/misc.source b/src/test/regress/output/misc.source
index 971ccfca10c..01b88045ac1 100644
--- a/src/test/regress/output/misc.source
+++ b/src/test/regress/output/misc.source
@@ -373,6 +373,7 @@ SELECT * FROM e_star*;
 (23 rows)
 
 ALTER TABLE a_star* ADD COLUMN a text;
+NOTICE:  ALTER TABLE: merging definition of column "a" for child d_star
 --UPDATE b_star*
 --   SET a = text 'gazpacho'
 --   WHERE aa > 4;
-- 
GitLab