From c328b6dd8bd85d91a0fd465c30b0bb352ea51e2b Mon Sep 17 00:00:00 2001
From: Tom Lane <tgl@sss.pgh.pa.us>
Date: Sun, 22 Sep 2002 19:42:52 +0000
Subject: [PATCH] Replace pg_attribute.attisinherited with attislocal and
 attinhcount columns, to allow more correct behavior in multiple-inheritance
 cases. Patch by Alvaro Herrera, review by Tom Lane.

---
 doc/src/sgml/catalogs.sgml                |  24 +-
 src/backend/access/common/tupdesc.c       |  12 +-
 src/backend/bootstrap/bootstrap.c         |   5 +-
 src/backend/catalog/heap.c                |  16 +-
 src/backend/catalog/index.c               |  10 +-
 src/backend/commands/sequence.c           |   5 +-
 src/backend/commands/tablecmds.c          |  83 +++-
 src/backend/commands/view.c               |   5 +-
 src/backend/nodes/copyfuncs.c             |   5 +-
 src/backend/nodes/equalfuncs.c            |   6 +-
 src/backend/nodes/outfuncs.c              |   7 +-
 src/backend/nodes/readfuncs.c             |  12 +-
 src/backend/parser/gram.y                 |   6 +-
 src/include/catalog/catversion.h          |   4 +-
 src/include/catalog/pg_attribute.h        | 473 +++++++++++-----------
 src/include/catalog/pg_class.h            |   4 +-
 src/include/nodes/parsenodes.h            |   5 +-
 src/test/regress/expected/alter_table.out | 113 ++++++
 src/test/regress/expected/type_sanity.out |   3 +-
 src/test/regress/sql/alter_table.sql      |  80 ++++
 src/test/regress/sql/type_sanity.sql      |   3 +-
 21 files changed, 583 insertions(+), 298 deletions(-)

diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 01dfe6ad73b..1a3765ab633 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -1,6 +1,6 @@
 <!--
  Documentation of the system catalogs, directed toward PostgreSQL developers
- $Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.60 2002/09/18 21:35:20 tgl Exp $
+ $Header: /cvsroot/pgsql/doc/src/sgml/catalogs.sgml,v 2.61 2002/09/22 19:42:50 tgl Exp $
  -->
 
 <chapter id="catalogs">
@@ -822,12 +822,22 @@
      </row>
 
      <row>
-      <entry>attisinherited</entry>
+      <entry>attislocal</entry>
       <entry><type>bool</type></entry>
       <entry></entry>
       <entry>
-       This column is inherited from some other relation.  An inherited
-       column cannot be dropped nor renamed.
+       This column is defined locally in the relation.  Note that a column may
+       be locally defined and inherited simultaneously.
+      </entry>
+     </row>
+
+     <row>
+      <entry>attinhcount</entry>
+      <entry><type>int4</type></entry>
+      <entry></entry>
+      <entry>
+       The number of direct ancestors this column has.  A column with a 
+       nonzero number of ancestors cannot be dropped nor renamed.
       </entry>
      </row>
 
@@ -1213,8 +1223,8 @@
       <entry></entry>
       <entry>
         'c' = check constraint,
-	'f' = foreign key constraint,
-	'p' = primary key constraint,
+        'f' = foreign key constraint,
+        'p' = primary key constraint,
         'u' = unique constraint
       </entry>
      </row>
@@ -3316,7 +3326,7 @@
        when storing a value of this type.  It applies to storage on
        disk as well as most representations of the value inside
        <productname>PostgreSQL</>.
-	When multiple values are stored consecutively, such
+       When multiple values are stored consecutively, such
        as in the representation of a complete row on disk, padding is
        inserted before a datum of this type so that it begins on the
        specified boundary.  The alignment reference is the beginning
diff --git a/src/backend/access/common/tupdesc.c b/src/backend/access/common/tupdesc.c
index ce4452eec51..5a1b912b379 100644
--- a/src/backend/access/common/tupdesc.c
+++ b/src/backend/access/common/tupdesc.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.89 2002/09/04 20:31:09 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/access/common/tupdesc.c,v 1.90 2002/09/22 19:42:50 tgl Exp $
  *
  * NOTES
  *	  some of the executor utility code such as "ExecTypeFromTL" should be
@@ -271,7 +271,9 @@ equalTupleDescs(TupleDesc tupdesc1, TupleDesc tupdesc2)
 			return false;
 		if (attr1->attisdropped != attr2->attisdropped)
 			return false;
-		if (attr1->attisinherited != attr2->attisinherited)
+		if (attr1->attislocal != attr2->attislocal)
+			return false;
+		if (attr1->attinhcount != attr2->attinhcount)
 			return false;
 	}
 	if (tupdesc1->constr != NULL)
@@ -396,7 +398,8 @@ TupleDescInitEntry(TupleDesc desc,
 	att->attnotnull = false;
 	att->atthasdef = false;
 	att->attisdropped = false;
-	att->attisinherited = false;
+	att->attislocal = true;
+	att->attinhcount = 0;
 
 	tuple = SearchSysCache(TYPEOID,
 						   ObjectIdGetDatum(oidtypeid),
@@ -543,7 +546,8 @@ BuildDescForRelation(List *schema)
 			desc->attrs[attnum - 1]->atthasdef = true;
 		}
 
-		desc->attrs[attnum - 1]->attisinherited = entry->is_inherited;
+		desc->attrs[attnum - 1]->attislocal = entry->is_local;
+		desc->attrs[attnum - 1]->attinhcount = entry->inhcount;
 	}
 
 	if (constr->has_not_null || ndef > 0)
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index 26e522f6cfa..b22631700b4 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.141 2002/09/04 20:31:13 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/bootstrap/bootstrap.c,v 1.142 2002/09/22 19:42:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -587,7 +587,7 @@ DefineAttr(char *name, char *type, int attnum)
 
 	namestrcpy(&attrtypes[attnum]->attname, name);
 	elog(DEBUG3, "column %s %s", NameStr(attrtypes[attnum]->attname), type);
-	attrtypes[attnum]->attnum = 1 + attnum;		/* fillatt */
+	attrtypes[attnum]->attnum = attnum + 1;		/* fillatt */
 
 	typeoid = gettype(type);
 
@@ -640,6 +640,7 @@ DefineAttr(char *name, char *type, int attnum)
 	}
 	attrtypes[attnum]->attcacheoff = -1;
 	attrtypes[attnum]->atttypmod = -1;
+	attrtypes[attnum]->attislocal = true;
 
 	/*
 	 * Mark as "not null" if type is fixed-width and prior columns are
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index fa5aec0203b..dea79dc4d6e 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.230 2002/09/22 00:37:09 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.231 2002/09/22 19:42:50 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -97,37 +97,37 @@ static void RemoveStatistics(Relation rel);
 static FormData_pg_attribute a1 = {
 	0, {"ctid"}, TIDOID, 0, sizeof(ItemPointerData),
 	SelfItemPointerAttributeNumber, 0, -1, -1,
-	false, 'p', false, 'i', true, false, false
+	false, 'p', false, 'i', true, false, false, true, 0
 };
 
 static FormData_pg_attribute a2 = {
 	0, {"oid"}, OIDOID, 0, sizeof(Oid),
 	ObjectIdAttributeNumber, 0, -1, -1,
-	true, 'p', false, 'i', true, false, false
+	true, 'p', false, 'i', true, false, false, true, 0
 };
 
 static FormData_pg_attribute a3 = {
 	0, {"xmin"}, XIDOID, 0, sizeof(TransactionId),
 	MinTransactionIdAttributeNumber, 0, -1, -1,
-	true, 'p', false, 'i', true, false, false
+	true, 'p', false, 'i', true, false, false, true, 0
 };
 
 static FormData_pg_attribute a4 = {
 	0, {"cmin"}, CIDOID, 0, sizeof(CommandId),
 	MinCommandIdAttributeNumber, 0, -1, -1,
-	true, 'p', false, 'i', true, false, false
+	true, 'p', false, 'i', true, false, false, true, 0
 };
 
 static FormData_pg_attribute a5 = {
 	0, {"xmax"}, XIDOID, 0, sizeof(TransactionId),
 	MaxTransactionIdAttributeNumber, 0, -1, -1,
-	true, 'p', false, 'i', true, false, false
+	true, 'p', false, 'i', true, false, false, true, 0
 };
 
 static FormData_pg_attribute a6 = {
 	0, {"cmax"}, CIDOID, 0, sizeof(CommandId),
 	MaxCommandIdAttributeNumber, 0, -1, -1,
-	true, 'p', false, 'i', true, false, false
+	true, 'p', false, 'i', true, false, false, true, 0
 };
 
 /*
@@ -139,7 +139,7 @@ static FormData_pg_attribute a6 = {
 static FormData_pg_attribute a7 = {
 	0, {"tableoid"}, OIDOID, 0, sizeof(Oid),
 	TableOidAttributeNumber, 0, -1, -1,
-	true, 'p', false, 'i', true, false, false
+	true, 'p', false, 'i', true, false, false, true, 0
 };
 
 static Form_pg_attribute SysAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6, &a7};
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 23fd0f6a171..e917b684c3b 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.197 2002/09/22 00:37:09 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/index.c,v 1.198 2002/09/22 19:42:50 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -165,10 +165,11 @@ BuildFuncTupleDesc(Oid funcOid,
 	funcTupDesc->attrs[0]->atttypid = keyType;
 	funcTupDesc->attrs[0]->attlen = typeTup->typlen;
 	funcTupDesc->attrs[0]->attbyval = typeTup->typbyval;
-	funcTupDesc->attrs[0]->attcacheoff = -1;
-	funcTupDesc->attrs[0]->atttypmod = -1;
 	funcTupDesc->attrs[0]->attstorage = typeTup->typstorage;
 	funcTupDesc->attrs[0]->attalign = typeTup->typalign;
+	funcTupDesc->attrs[0]->attcacheoff = -1;
+	funcTupDesc->attrs[0]->atttypmod = -1;
+	funcTupDesc->attrs[0]->attislocal = true;
 
 	ReleaseSysCache(tuple);
 
@@ -259,7 +260,8 @@ ConstructTupleDescriptor(Relation heapRelation,
 		to->attcacheoff = -1;
 		to->attnotnull = false;
 		to->atthasdef = false;
-		to->attisinherited = false;
+		to->attislocal = true;
+		to->attinhcount = 0;
 
 		/*
 		 * We do not yet have the correct relation OID for the index, so
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 5906788247c..f6ace0d2d93 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.87 2002/09/04 20:31:15 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.88 2002/09/22 19:42:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -127,7 +127,8 @@ DefineSequence(CreateSeqStmt *seq)
 
 		coldef = makeNode(ColumnDef);
 		coldef->typename = typnam;
-		coldef->is_inherited = false;
+		coldef->inhcount = 0;
+		coldef->is_local = true;
 		coldef->is_not_null = true;
 		coldef->raw_default = NULL;
 		coldef->cooked_default = NULL;
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index c79cd1f9edd..7b2bab71c34 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.42 2002/09/22 00:37:09 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.43 2002/09/22 19:42:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -609,6 +609,7 @@ MergeAttributes(List *schema, List *supers, bool istemp,
 						 attributeName,
 						 TypeNameToString(def->typename),
 						 format_type_be(attribute->atttypid));
+				def->inhcount++;
 				/* Merge of NOT NULL constraints = OR 'em together */
 				def->is_not_null |= attribute->attnotnull;
 				/* Default and other constraints are handled below */
@@ -625,7 +626,8 @@ MergeAttributes(List *schema, List *supers, bool istemp,
 				typename->typeid = attribute->atttypid;
 				typename->typmod = attribute->atttypmod;
 				def->typename = typename;
-				def->is_inherited = true;
+				def->inhcount = 1;
+				def->is_local = false;
 				def->is_not_null = attribute->attnotnull;
 				def->raw_default = NULL;
 				def->cooked_default = NULL;
@@ -758,6 +760,8 @@ MergeAttributes(List *schema, List *supers, bool istemp,
 						 attributeName,
 						 TypeNameToString(def->typename),
 						 TypeNameToString(newdef->typename));
+				/* Mark the column as locally defined */
+				def->is_local = true;
 				/* Merge of NOT NULL constraints = OR 'em together */
 				def->is_not_null |= newdef->is_not_null;
 				/* If new def has a default, override previous default */
@@ -1155,7 +1159,7 @@ renameatt(Oid myrelid,
 	 * if the attribute is inherited, forbid the renaming, unless we are
 	 * already inside a recursive rename.
 	 */
-	if (attform->attisinherited && !recursing)
+	if (attform->attinhcount > 0 && !recursing)
 		elog(ERROR, "renameatt: inherited attribute \"%s\" may not be renamed",
 			 oldattname);
 
@@ -1628,7 +1632,8 @@ AlterTableAddColumn(Oid myrelid,
 				   *children;
 		ColumnDef  *colDefChild = copyObject(colDef);
 
-		colDefChild->is_inherited = true;
+		colDefChild->inhcount = 1;
+		colDefChild->is_local = false;
 
 		/* this routine is actually in the planner */
 		children = find_all_inheritors(myrelid);
@@ -1742,7 +1747,8 @@ AlterTableAddColumn(Oid myrelid,
 	attribute->atthasdef = (colDef->raw_default != NULL ||
 							colDef->cooked_default != NULL);
 	attribute->attisdropped = false;
-	attribute->attisinherited = colDef->is_inherited;
+	attribute->attislocal = colDef->is_local;
+	attribute->attinhcount = colDef->inhcount;
 
 	ReleaseSysCache(typeTuple);
 
@@ -2373,13 +2379,14 @@ AlterTableDropColumn(Oid myrelid, bool recurse, bool recursing,
 			 RelationGetRelationName(rel));
 
 	/* Don't drop inherited columns */
-	if (tupleDesc->attrs[attnum - 1]->attisinherited && !recursing)
+	if (tupleDesc->attrs[attnum - 1]->attinhcount > 0 && !recursing)
 		elog(ERROR, "ALTER TABLE: Cannot drop inherited column \"%s\"",
 			 colName);
 
 	/*
 	 * If we are asked to drop ONLY in this table (no recursion), we need
-	 * to mark the inheritors' attribute as non-inherited.
+	 * to mark the inheritors' attribute as locally defined rather than
+	 * inherited.
 	 */
 	if (!recurse && !recursing)
 	{
@@ -2396,6 +2403,7 @@ AlterTableDropColumn(Oid myrelid, bool recurse, bool recursing,
 			Oid			childrelid = lfirsti(child);
 			Relation	childrel;
 			HeapTuple	tuple;
+			Form_pg_attribute childatt;
 
 			childrel = heap_open(childrelid, AccessExclusiveLock);
 
@@ -2403,43 +2411,84 @@ AlterTableDropColumn(Oid myrelid, bool recurse, bool recursing,
 			if (!HeapTupleIsValid(tuple))		/* shouldn't happen */
 				elog(ERROR, "ALTER TABLE: relation %u has no column \"%s\"",
 					 childrelid, colName);
+			childatt = (Form_pg_attribute) GETSTRUCT(tuple);
 
-			((Form_pg_attribute) GETSTRUCT(tuple))->attisinherited = false;
+			if (childatt->attinhcount <= 0)
+				elog(ERROR, "ALTER TABLE: relation %u has non-inherited column \"%s\"",
+					 childrelid, colName);
+			childatt->attinhcount--;
+			childatt->attislocal = true;
 
 			simple_heap_update(attr_rel, &tuple->t_self, tuple);
 
 			/* keep the system catalog indexes current */
 			CatalogUpdateIndexes(attr_rel, tuple);
 
+			heap_freetuple(tuple);
+
 			heap_close(childrel, NoLock);
 		}
 		heap_close(attr_rel, RowExclusiveLock);
 	}
 
 	/*
-	 * Propagate to children if desired
+	 * Propagate to children if desired.  Unlike most other ALTER routines,
+	 * we have to do this one level of recursion at a time; we can't use
+	 * find_all_inheritors to do it in one pass.
 	 */
 	if (recurse)
 	{
+		Relation	attr_rel;
 		List	   *child,
 				   *children;
 
-		/* this routine is actually in the planner */
-		children = find_all_inheritors(myrelid);
+		/* We only want direct inheritors in this case */
+		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.
-		 */
+		attr_rel = heap_openr(AttributeRelationName, RowExclusiveLock);
 		foreach(child, children)
 		{
 			Oid			childrelid = lfirsti(child);
+			Relation	childrel;
+			HeapTuple	tuple;
+			Form_pg_attribute childatt;
 
 			if (childrelid == myrelid)
 				continue;
-			AlterTableDropColumn(childrelid, false, true, colName, behavior);
+
+			childrel = heap_open(childrelid, AccessExclusiveLock);
+
+			tuple = SearchSysCacheCopyAttName(childrelid, colName);
+			if (!HeapTupleIsValid(tuple))		/* shouldn't happen */
+				elog(ERROR, "ALTER TABLE: relation %u has no column \"%s\"",
+					 childrelid, colName);
+			childatt = (Form_pg_attribute) GETSTRUCT(tuple);
+
+			if (childatt->attinhcount <= 0)
+				elog(ERROR, "ALTER TABLE: relation %u has non-inherited column \"%s\"",
+					 childrelid, colName);
+
+			if (childatt->attinhcount == 1 && !childatt->attislocal)
+			{
+				/* Time to delete this child column, too */
+				AlterTableDropColumn(childrelid, true, true, colName, behavior);
+			}
+			else
+			{
+				/* Child column must survive my deletion */
+				childatt->attinhcount--;
+
+				simple_heap_update(attr_rel, &tuple->t_self, tuple);
+
+				/* keep the system catalog indexes current */
+				CatalogUpdateIndexes(attr_rel, tuple);
+			}
+
+			heap_freetuple(tuple);
+
+			heap_close(childrel, NoLock);
 		}
+		heap_close(attr_rel, RowExclusiveLock);
 	}
 
 	/*
diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c
index 0ce309750c9..17a5cdaa0d4 100644
--- a/src/backend/commands/view.c
+++ b/src/backend/commands/view.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/view.c,v 1.71 2002/09/04 20:31:17 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/view.c,v 1.72 2002/09/22 19:42:50 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -71,7 +71,8 @@ DefineVirtualRelation(const RangeVar *relation, List *tlist, bool replace)
 			typename->typmod = res->restypmod;
 			def->typename = typename;
 
-			def->is_inherited = false;
+			def->inhcount = 0;
+			def->is_local = true;
 			def->is_not_null = false;
 			def->raw_default = NULL;
 			def->cooked_default = NULL;
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 73e240aca7c..bce849e4ec5 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -15,7 +15,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.212 2002/09/18 21:35:20 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.213 2002/09/22 19:42:51 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1732,7 +1732,8 @@ _copyColumnDef(ColumnDef *from)
 	if (from->colname)
 		newnode->colname = pstrdup(from->colname);
 	Node_Copy(from, newnode, typename);
-	newnode->is_inherited = from->is_inherited;
+	newnode->inhcount = from->inhcount;
+	newnode->is_local = from->is_local;
 	newnode->is_not_null = from->is_not_null;
 	Node_Copy(from, newnode, raw_default);
 	if (from->cooked_default)
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 8c5d6a0337a..82d4fc6ab63 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -20,7 +20,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.159 2002/09/18 21:35:20 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.160 2002/09/22 19:42:51 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1769,7 +1769,9 @@ _equalColumnDef(ColumnDef *a, ColumnDef *b)
 		return false;
 	if (!equal(a->typename, b->typename))
 		return false;
-	if (a->is_inherited != b->is_inherited)
+	if (a->inhcount != b->inhcount)
+		return false;
+	if (a->is_local != b->is_local)
 		return false;
 	if (a->is_not_null != b->is_not_null)
 		return false;
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index fde42291691..364aa774ada 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -5,7 +5,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *	$Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.174 2002/09/18 21:35:21 tgl Exp $
+ *	$Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.175 2002/09/22 19:42:51 tgl Exp $
  *
  * NOTES
  *	  Every (plan) node in POSTGRES has an associated "out" routine which
@@ -176,8 +176,9 @@ _outColumnDef(StringInfo str, ColumnDef *node)
 	_outToken(str, node->colname);
 	appendStringInfo(str, " :typename ");
 	_outNode(str, node->typename);
-	appendStringInfo(str, " :is_inherited %s :is_not_null %s :raw_default ",
-					 booltostr(node->is_inherited),
+	appendStringInfo(str, " :inhcount %d :is_local %s :is_not_null %s :raw_default ",
+					 node->inhcount,
+					 booltostr(node->is_local),
 					 booltostr(node->is_not_null));
 	_outNode(str, node->raw_default);
 	appendStringInfo(str, " :cooked_default ");
diff --git a/src/backend/nodes/readfuncs.c b/src/backend/nodes/readfuncs.c
index a4f0c81fa1e..fc4bb97e4a7 100644
--- a/src/backend/nodes/readfuncs.c
+++ b/src/backend/nodes/readfuncs.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.133 2002/09/18 21:35:21 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/readfuncs.c,v 1.134 2002/09/22 19:42:51 tgl Exp $
  *
  * NOTES
  *	  Most of the read functions for plan nodes are tested. (In fact, they
@@ -1526,9 +1526,13 @@ _readColumnDef(void)
 	token = pg_strtok(&length); /* eat :typename */
 	local_node->typename = nodeRead(true);		/* now read it */
 
-	token = pg_strtok(&length); /* eat :is_inherited */
-	token = pg_strtok(&length); /* get :is_inherited */
-	local_node->is_inherited = strtobool(token);
+	token = pg_strtok(&length); /* eat :inhcount */
+	token = pg_strtok(&length); /* get :inhcount */
+	local_node->inhcount = atoi(token);
+
+	token = pg_strtok(&length); /* eat :is_local */
+	token = pg_strtok(&length); /* get :is_local */
+	local_node->is_local = strtobool(token);
 
 	token = pg_strtok(&length); /* eat :is_not_null */
 	token = pg_strtok(&length); /* get :is_not_null */
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index be45d7bde16..bbee0097243 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.368 2002/09/22 17:27:23 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.369 2002/09/22 19:42:51 tgl Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -1453,6 +1453,7 @@ columnDef:	ColId Typename ColQualList opt_collate
 					n->colname = $1;
 					n->typename = $2;
 					n->constraints = $3;
+					n->is_local = true;
 
 					if ($4 != NULL)
 						elog(NOTICE,
@@ -1842,6 +1843,8 @@ CreateAsElement:
 					ColumnDef *n = makeNode(ColumnDef);
 					n->colname = $1;
 					n->typename = NULL;
+					n->inhcount = 0;
+					n->is_local = true;
 					n->is_not_null = false;
 					n->raw_default = NULL;
 					n->cooked_default = NULL;
@@ -4844,6 +4847,7 @@ TableFuncElement:	ColId Typename
 					n->colname = $1;
 					n->typename = $2;
 					n->constraints = NIL;
+					n->is_local = true;
 					$$ = (Node *)n;
 				}
 		;
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 21a7732c5fb..431e317c89b 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: catversion.h,v 1.159 2002/09/18 21:35:23 tgl Exp $
+ * $Id: catversion.h,v 1.160 2002/09/22 19:42:51 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	200209181
+#define CATALOG_VERSION_NO	200209221
 
 #endif
diff --git a/src/include/catalog/pg_attribute.h b/src/include/catalog/pg_attribute.h
index 918b17bac37..e23f793bc7e 100644
--- a/src/include/catalog/pg_attribute.h
+++ b/src/include/catalog/pg_attribute.h
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_attribute.h,v 1.99 2002/09/04 20:31:37 momjian Exp $
+ * $Id: pg_attribute.h,v 1.100 2002/09/22 19:42:51 tgl Exp $
  *
  * NOTES
  *	  the genbki.sh script reads this file and generates .bki
@@ -147,8 +147,11 @@ CATALOG(pg_attribute) BOOTSTRAP BKI_WITHOUT_OIDS
 	/* Is dropped (ie, logically invisible) or not */
 	bool		attisdropped;
 
-	/* Is inherited from a parent relation */
-	bool		attisinherited;
+	/* Has a local definition (hence, do not drop when attinhcount is 0) */
+	bool		attislocal;
+
+	/* Number of times inherited from direct parent relation(s) */
+	int4		attinhcount;
 } FormData_pg_attribute;
 
 /*
@@ -157,7 +160,7 @@ CATALOG(pg_attribute) BOOTSTRAP BKI_WITHOUT_OIDS
  * because of alignment padding at the end of the struct.)
  */
 #define ATTRIBUTE_TUPLE_SIZE \
-	(offsetof(FormData_pg_attribute,attisinherited) + sizeof(bool))
+	(offsetof(FormData_pg_attribute,attinhcount) + sizeof(int4))
 
 /* ----------------
  *		Form_pg_attribute corresponds to a pointer to a tuple with
@@ -171,7 +174,7 @@ typedef FormData_pg_attribute *Form_pg_attribute;
  * ----------------
  */
 
-#define Natts_pg_attribute				17
+#define Natts_pg_attribute				18
 #define Anum_pg_attribute_attrelid		1
 #define Anum_pg_attribute_attname		2
 #define Anum_pg_attribute_atttypid		3
@@ -188,7 +191,8 @@ typedef FormData_pg_attribute *Form_pg_attribute;
 #define Anum_pg_attribute_attnotnull	14
 #define Anum_pg_attribute_atthasdef		15
 #define Anum_pg_attribute_attisdropped	16
-#define Anum_pg_attribute_attisinherited 17
+#define Anum_pg_attribute_attislocal	17
+#define Anum_pg_attribute_attinhcount	18
 
 
 
@@ -211,6 +215,9 @@ typedef FormData_pg_attribute *Form_pg_attribute;
  *		initial contents of pg_attribute
  *
  * NOTE: only "bootstrapped" relations need to be declared here.
+ *
+ * NOTE: if changing pg_attribute column set, also see the hard-coded
+ * entries for system attributes in catalog/heap.c.
  * ----------------
  */
 
@@ -219,268 +226,270 @@ typedef FormData_pg_attribute *Form_pg_attribute;
  * ----------------
  */
 #define Schema_pg_type \
-{ 1247, {"typname"},	   19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', false, 'i', true, false, false, false }, \
-{ 1247, {"typnamespace"},  26, -1,	4,	2, 0, -1, -1, true, 'p', false, 'i', true, false, false, false }, \
-{ 1247, {"typowner"},	   23, 0,	4,	3, 0, -1, -1, true, 'p', false, 'i', true, false, false, false }, \
-{ 1247, {"typlen"},		   21, 0,	2,	4, 0, -1, -1, true, 'p', false, 's', true, false, false, false }, \
-{ 1247, {"typbyval"},	   16, 0,	1,	5, 0, -1, -1, true, 'p', false, 'c', true, false, false, false }, \
-{ 1247, {"typtype"},	   18, -1,	1,	6, 0, -1, -1, true, 'p', false, 'c', true, false, false, false }, \
-{ 1247, {"typisdefined"},  16, -1,	1,	7, 0, -1, -1, true, 'p', false, 'c', true, false, false, false }, \
-{ 1247, {"typdelim"},	   18, 0,	1,	8, 0, -1, -1, true, 'p', false, 'c', true, false, false, false }, \
-{ 1247, {"typrelid"},	   26, 0,	4,	9, 0, -1, -1, true, 'p', false, 'i', true, false, false, false }, \
-{ 1247, {"typelem"},	   26, 0,	4, 10, 0, -1, -1, true, 'p', false, 'i', true, false, false, false }, \
-{ 1247, {"typinput"},	   24, 0,	4, 11, 0, -1, -1, true, 'p', false, 'i', true, false, false, false }, \
-{ 1247, {"typoutput"},	   24, 0,	4, 12, 0, -1, -1, true, 'p', false, 'i', true, false, false, false }, \
-{ 1247, {"typalign"},	   18, 0,	1, 13, 0, -1, -1, true, 'p', false, 'c', true, false, false, false }, \
-{ 1247, {"typstorage"},    18, 0,	1, 14, 0, -1, -1, true, 'p', false, 'c', true, false, false, false }, \
-{ 1247, {"typnotnull"},    16, 0,	1, 15, 0, -1, -1, true, 'p', false, 'c', true, false, false, false }, \
-{ 1247, {"typbasetype"},   26, 0,	4, 16, 0, -1, -1, true, 'p', false, 'i', true, false, false, false }, \
-{ 1247, {"typtypmod"},	   23, 0,	4, 17, 0, -1, -1, true, 'p', false, 'i', true, false, false, false }, \
-{ 1247, {"typndims"},	   23, 0,	4, 18, 0, -1, -1, true, 'p', false, 'i', true, false, false, false }, \
-{ 1247, {"typdefaultbin"}, 25, 0,  -1, 19, 0, -1, -1, false, 'x', false, 'i', false, false, false, false }, \
-{ 1247, {"typdefault"},    25, 0,  -1, 20, 0, -1, -1, false, 'x', false, 'i', false, false, false, false }
-
-
-DATA(insert ( 1247 typname			19 -1 NAMEDATALEN	1 0 -1 -1 f p f i t f f f));
-DATA(insert ( 1247 typnamespace		26 -1 4   2 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1247 typowner			23 0  4   3 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1247 typlen			21 0  2   4 0 -1 -1 t p f s t f f f));
-DATA(insert ( 1247 typbyval			16 0  1   5 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1247 typtype			18 -1 1   6 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1247 typisdefined		16 -1 1   7 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1247 typdelim			18 0  1   8 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1247 typrelid			26 0  4   9 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1247 typelem			26 0  4  10 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1247 typinput			24 0  4  11 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1247 typoutput		24 0  4  12 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1247 typalign			18 0  1  13 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1247 typstorage		18 0  1  14 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1247 typnotnull		16 0  1  15 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1247 typbasetype		26 0  4  16 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1247 typtypmod		23 0  4  17 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1247 typndims			23 0  4  18 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1247 typdefaultbin	25 0 -1  19 0 -1 -1 f x f i f f f f));
-DATA(insert ( 1247 typdefault		25 0 -1  20 0 -1 -1 f x f i f f f f));
-DATA(insert ( 1247 ctid				27 0  6  -1 0 -1 -1 f p f i t f f f));
-DATA(insert ( 1247 oid				26 0  4  -2 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1247 xmin				28 0  4  -3 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1247 cmin				29 0  4  -4 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1247 xmax				28 0  4  -5 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1247 cmax				29 0  4  -6 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1247 tableoid			26 0  4  -7 0 -1 -1 t p f i t f f f));
+{ 1247, {"typname"},	   19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1247, {"typnamespace"},  26, -1,	4,	2, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1247, {"typowner"},	   23, 0,	4,	3, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1247, {"typlen"},		   21, 0,	2,	4, 0, -1, -1, true, 'p', false, 's', true, false, false, true, 0 }, \
+{ 1247, {"typbyval"},	   16, 0,	1,	5, 0, -1, -1, true, 'p', false, 'c', true, false, false, true, 0 }, \
+{ 1247, {"typtype"},	   18, -1,	1,	6, 0, -1, -1, true, 'p', false, 'c', true, false, false, true, 0 }, \
+{ 1247, {"typisdefined"},  16, -1,	1,	7, 0, -1, -1, true, 'p', false, 'c', true, false, false, true, 0 }, \
+{ 1247, {"typdelim"},	   18, 0,	1,	8, 0, -1, -1, true, 'p', false, 'c', true, false, false, true, 0 }, \
+{ 1247, {"typrelid"},	   26, 0,	4,	9, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1247, {"typelem"},	   26, 0,	4, 10, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1247, {"typinput"},	   24, 0,	4, 11, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1247, {"typoutput"},	   24, 0,	4, 12, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1247, {"typalign"},	   18, 0,	1, 13, 0, -1, -1, true, 'p', false, 'c', true, false, false, true, 0 }, \
+{ 1247, {"typstorage"},    18, 0,	1, 14, 0, -1, -1, true, 'p', false, 'c', true, false, false, true, 0 }, \
+{ 1247, {"typnotnull"},    16, 0,	1, 15, 0, -1, -1, true, 'p', false, 'c', true, false, false, true, 0 }, \
+{ 1247, {"typbasetype"},   26, 0,	4, 16, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1247, {"typtypmod"},	   23, 0,	4, 17, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1247, {"typndims"},	   23, 0,	4, 18, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1247, {"typdefaultbin"}, 25, 0,  -1, 19, 0, -1, -1, false, 'x', false, 'i', false, false, false, true, 0 }, \
+{ 1247, {"typdefault"},    25, 0,  -1, 20, 0, -1, -1, false, 'x', false, 'i', false, false, false, true, 0 }
+
+
+DATA(insert ( 1247 typname			19 -1 NAMEDATALEN	1 0 -1 -1 f p f i t f f t 0));
+DATA(insert ( 1247 typnamespace		26 -1 4   2 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1247 typowner			23 0  4   3 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1247 typlen			21 0  2   4 0 -1 -1 t p f s t f f t 0));
+DATA(insert ( 1247 typbyval			16 0  1   5 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1247 typtype			18 -1 1   6 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1247 typisdefined		16 -1 1   7 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1247 typdelim			18 0  1   8 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1247 typrelid			26 0  4   9 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1247 typelem			26 0  4  10 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1247 typinput			24 0  4  11 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1247 typoutput		24 0  4  12 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1247 typalign			18 0  1  13 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1247 typstorage		18 0  1  14 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1247 typnotnull		16 0  1  15 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1247 typbasetype		26 0  4  16 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1247 typtypmod		23 0  4  17 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1247 typndims			23 0  4  18 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1247 typdefaultbin	25 0 -1  19 0 -1 -1 f x f i f f f t 0));
+DATA(insert ( 1247 typdefault		25 0 -1  20 0 -1 -1 f x f i f f f t 0));
+DATA(insert ( 1247 ctid				27 0  6  -1 0 -1 -1 f p f i t f f t 0));
+DATA(insert ( 1247 oid				26 0  4  -2 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1247 xmin				28 0  4  -3 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1247 cmin				29 0  4  -4 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1247 xmax				28 0  4  -5 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1247 cmax				29 0  4  -6 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1247 tableoid			26 0  4  -7 0 -1 -1 t p f i t f f t 0));
 
 /* ----------------
  *		pg_database
  * ----------------
  */
-DATA(insert ( 1262 datname			19 0 NAMEDATALEN   1 0 -1 -1 f p f i t f f f));
-DATA(insert ( 1262 datdba			23 0  4   2 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1262 encoding			23 0  4   3 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1262 datistemplate	16 0  1   4 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1262 datallowconn		16 0  1   5 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1262 datlastsysoid	26 0  4   6 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1262 datvacuumxid		28 0  4   7 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1262 datfrozenxid		28 0  4   8 0 -1 -1 t p f i t f f f));
+DATA(insert ( 1262 datname			19 0 NAMEDATALEN   1 0 -1 -1 f p f i t f f t 0));
+DATA(insert ( 1262 datdba			23 0  4   2 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1262 encoding			23 0  4   3 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1262 datistemplate	16 0  1   4 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1262 datallowconn		16 0  1   5 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1262 datlastsysoid	26 0  4   6 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1262 datvacuumxid		28 0  4   7 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1262 datfrozenxid		28 0  4   8 0 -1 -1 t p f i t f f t 0));
 /* do not mark datpath as toastable; GetRawDatabaseInfo won't cope */
-DATA(insert ( 1262 datpath			25 0 -1   9 0 -1 -1 f p f i t f f f));
-DATA(insert ( 1262 datconfig	  1009 0 -1  10 0 -1 -1 f x f i f f f f));
-DATA(insert ( 1262 datacl		  1034 0 -1  11 0 -1 -1 f x f i f f f f));
-DATA(insert ( 1262 ctid				27 0  6  -1 0 -1 -1 f p f i t f f f));
-DATA(insert ( 1262 oid				26 0  4  -2 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1262 xmin				28 0  4  -3 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1262 cmin				29 0  4  -4 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1262 xmax				28 0  4  -5 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1262 cmax				29 0  4  -6 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1262 tableoid			26 0  4  -7 0 -1 -1 t p f i t f f f));
+DATA(insert ( 1262 datpath			25 0 -1   9 0 -1 -1 f p f i t f f t 0));
+DATA(insert ( 1262 datconfig	  1009 0 -1  10 0 -1 -1 f x f i f f f t 0));
+DATA(insert ( 1262 datacl		  1034 0 -1  11 0 -1 -1 f x f i f f f t 0));
+DATA(insert ( 1262 ctid				27 0  6  -1 0 -1 -1 f p f i t f f t 0));
+DATA(insert ( 1262 oid				26 0  4  -2 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1262 xmin				28 0  4  -3 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1262 cmin				29 0  4  -4 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1262 xmax				28 0  4  -5 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1262 cmax				29 0  4  -6 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1262 tableoid			26 0  4  -7 0 -1 -1 t p f i t f f t 0));
 
 /* ----------------
  *		pg_proc
  * ----------------
  */
 #define Schema_pg_proc \
-{ 1255, {"proname"},			19, -1, NAMEDATALEN,  1, 0, -1, -1, false, 'p', false, 'i', true, false, false, false }, \
-{ 1255, {"pronamespace"},		26, -1, 4,	2, 0, -1, -1, true, 'p', false, 'i', true, false, false, false }, \
-{ 1255, {"proowner"},			23, 0,	4,	3, 0, -1, -1, true, 'p', false, 'i', true, false, false, false }, \
-{ 1255, {"prolang"},			26, 0,	4,	4, 0, -1, -1, true, 'p', false, 'i', true, false, false, false }, \
-{ 1255, {"proisagg"},			16, -1, 1,	5, 0, -1, -1, true, 'p', false, 'c', true, false, false, false }, \
-{ 1255, {"prosecdef"},			16, 0,	1,	6, 0, -1, -1, true, 'p', false, 'c', true, false, false, false }, \
-{ 1255, {"proisstrict"},		16, 0,	1,	7, 0, -1, -1, true, 'p', false, 'c', true, false, false, false }, \
-{ 1255, {"proretset"},			16, 0,	1,	8, 0, -1, -1, true, 'p', false, 'c', true, false, false, false }, \
-{ 1255, {"provolatile"},		18, 0,	1,	9, 0, -1, -1, true, 'p', false, 'c', true, false, false, false }, \
-{ 1255, {"pronargs"},			21, 0,	2, 10, 0, -1, -1, true, 'p', false, 's', true, false, false, false }, \
-{ 1255, {"prorettype"},			26, 0,	4, 11, 0, -1, -1, true, 'p', false, 'i', true, false, false, false }, \
-{ 1255, {"proargtypes"},		30, 0, INDEX_MAX_KEYS*4, 12, 0, -1, -1, false, 'p', false, 'i', true, false, false, false }, \
-{ 1255, {"prosrc"},				25, 0, -1, 13, 0, -1, -1, false, 'x', false, 'i', false, false, false, false }, \
-{ 1255, {"probin"},				17, 0, -1, 14, 0, -1, -1, false, 'x', false, 'i', false, false, false, false }, \
-{ 1255, {"proacl"},			  1034, 0, -1, 15, 0, -1, -1, false, 'x', false, 'i', false, false, false, false }
-
-DATA(insert ( 1255 proname			19 -1 NAMEDATALEN	1 0 -1 -1 f p f i t f f f));
-DATA(insert ( 1255 pronamespace		26 -1 4   2 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1255 proowner			23 0  4   3 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1255 prolang			26 0  4   4 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1255 proisagg			16 -1 1   5 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1255 prosecdef		16 0  1   6 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1255 proisstrict		16 0  1   7 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1255 proretset		16 0  1   8 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1255 provolatile		18 0  1   9 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1255 pronargs			21 0  2  10 0 -1 -1 t p f s t f f f));
-DATA(insert ( 1255 prorettype		26 0  4  11 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1255 proargtypes		30 0 INDEX_MAX_KEYS*4 12 0 -1 -1 f p f i t f f f));
-DATA(insert ( 1255 prosrc			25 0 -1  13 0 -1 -1 f x f i f f f f));
-DATA(insert ( 1255 probin			17 0 -1  14 0 -1 -1 f x f i f f f f));
-DATA(insert ( 1255 proacl		  1034 0 -1  15 0 -1 -1 f x f i f f f f));
-DATA(insert ( 1255 ctid				27 0  6  -1 0 -1 -1 f p f i t f f f));
-DATA(insert ( 1255 oid				26 0  4  -2 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1255 xmin				28 0  4  -3 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1255 cmin				29 0  4  -4 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1255 xmax				28 0  4  -5 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1255 cmax				29 0  4  -6 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1255 tableoid			26 0  4  -7 0 -1 -1 t p f i t f f f));
+{ 1255, {"proname"},			19, -1, NAMEDATALEN,  1, 0, -1, -1, false, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1255, {"pronamespace"},		26, -1, 4,	2, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1255, {"proowner"},			23, 0,	4,	3, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1255, {"prolang"},			26, 0,	4,	4, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1255, {"proisagg"},			16, -1, 1,	5, 0, -1, -1, true, 'p', false, 'c', true, false, false, true, 0 }, \
+{ 1255, {"prosecdef"},			16, 0,	1,	6, 0, -1, -1, true, 'p', false, 'c', true, false, false, true, 0 }, \
+{ 1255, {"proisstrict"},		16, 0,	1,	7, 0, -1, -1, true, 'p', false, 'c', true, false, false, true, 0 }, \
+{ 1255, {"proretset"},			16, 0,	1,	8, 0, -1, -1, true, 'p', false, 'c', true, false, false, true, 0 }, \
+{ 1255, {"provolatile"},		18, 0,	1,	9, 0, -1, -1, true, 'p', false, 'c', true, false, false, true, 0 }, \
+{ 1255, {"pronargs"},			21, 0,	2, 10, 0, -1, -1, true, 'p', false, 's', true, false, false, true, 0 }, \
+{ 1255, {"prorettype"},			26, 0,	4, 11, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1255, {"proargtypes"},		30, 0, INDEX_MAX_KEYS*4, 12, 0, -1, -1, false, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1255, {"prosrc"},				25, 0, -1, 13, 0, -1, -1, false, 'x', false, 'i', false, false, false, true, 0 }, \
+{ 1255, {"probin"},				17, 0, -1, 14, 0, -1, -1, false, 'x', false, 'i', false, false, false, true, 0 }, \
+{ 1255, {"proacl"},			  1034, 0, -1, 15, 0, -1, -1, false, 'x', false, 'i', false, false, false, true, 0 }
+
+DATA(insert ( 1255 proname			19 -1 NAMEDATALEN	1 0 -1 -1 f p f i t f f t 0));
+DATA(insert ( 1255 pronamespace		26 -1 4   2 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1255 proowner			23 0  4   3 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1255 prolang			26 0  4   4 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1255 proisagg			16 -1 1   5 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1255 prosecdef		16 0  1   6 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1255 proisstrict		16 0  1   7 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1255 proretset		16 0  1   8 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1255 provolatile		18 0  1   9 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1255 pronargs			21 0  2  10 0 -1 -1 t p f s t f f t 0));
+DATA(insert ( 1255 prorettype		26 0  4  11 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1255 proargtypes		30 0 INDEX_MAX_KEYS*4 12 0 -1 -1 f p f i t f f t 0));
+DATA(insert ( 1255 prosrc			25 0 -1  13 0 -1 -1 f x f i f f f t 0));
+DATA(insert ( 1255 probin			17 0 -1  14 0 -1 -1 f x f i f f f t 0));
+DATA(insert ( 1255 proacl		  1034 0 -1  15 0 -1 -1 f x f i f f f t 0));
+DATA(insert ( 1255 ctid				27 0  6  -1 0 -1 -1 f p f i t f f t 0));
+DATA(insert ( 1255 oid				26 0  4  -2 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1255 xmin				28 0  4  -3 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1255 cmin				29 0  4  -4 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1255 xmax				28 0  4  -5 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1255 cmax				29 0  4  -6 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1255 tableoid			26 0  4  -7 0 -1 -1 t p f i t f f t 0));
 
 /* ----------------
  *		pg_shadow
  * ----------------
  */
-DATA(insert ( 1260 usename			19	-1 NAMEDATALEN	1 0 -1 -1 f p f i t f f f));
-DATA(insert ( 1260 usesysid			23	-1	4	2 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1260 usecreatedb		16	0	1	3 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1260 usesuper			16	0	1	4 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1260 usecatupd		16	0	1	5 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1260 passwd			25	0  -1	6 0 -1 -1 f x f i f f f f));
-DATA(insert ( 1260 valuntil			702 0	4	7 0 -1 -1 t p f i f f f f));
-DATA(insert ( 1260 useconfig	  1009	0  -1	8 0 -1 -1 f x f i f f f f));
-DATA(insert ( 1260 ctid				27 0  6  -1 0 -1 -1 f p f i t f f f));
+DATA(insert ( 1260 usename			19	-1 NAMEDATALEN	1 0 -1 -1 f p f i t f f t 0));
+DATA(insert ( 1260 usesysid			23	-1	4	2 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1260 usecreatedb		16	0	1	3 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1260 usesuper			16	0	1	4 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1260 usecatupd		16	0	1	5 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1260 passwd			25	0  -1	6 0 -1 -1 f x f i f f f t 0));
+DATA(insert ( 1260 valuntil			702 0	4	7 0 -1 -1 t p f i f f f t 0));
+DATA(insert ( 1260 useconfig	  1009	0  -1	8 0 -1 -1 f x f i f f f t 0));
+DATA(insert ( 1260 ctid				27 0  6  -1 0 -1 -1 f p f i t f f t 0));
 /* no OIDs in pg_shadow */
-DATA(insert ( 1260 xmin				28 0  4  -3 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1260 cmin				29 0  4  -4 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1260 xmax				28 0  4  -5 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1260 cmax				29 0  4  -6 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1260 tableoid			26 0  4  -7 0 -1 -1 t p f i t f f f));
+DATA(insert ( 1260 xmin				28 0  4  -3 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1260 cmin				29 0  4  -4 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1260 xmax				28 0  4  -5 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1260 cmax				29 0  4  -6 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1260 tableoid			26 0  4  -7 0 -1 -1 t p f i t f f t 0));
 
 /* ----------------
  *		pg_group
  * ----------------
  */
-DATA(insert ( 1261 groname			19 -1 NAMEDATALEN  1 0 -1 -1 f p f i t f f f));
-DATA(insert ( 1261 grosysid			23 -1  4   2 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1261 grolist		  1007 0 -1   3 0 -1 -1 f x f i f f f f));
-DATA(insert ( 1261 ctid				27 0  6  -1 0 -1 -1 f p f i t f f f));
+DATA(insert ( 1261 groname			19 -1 NAMEDATALEN  1 0 -1 -1 f p f i t f f t 0));
+DATA(insert ( 1261 grosysid			23 -1  4   2 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1261 grolist		  1007 0 -1   3 0 -1 -1 f x f i f f f t 0));
+DATA(insert ( 1261 ctid				27 0  6  -1 0 -1 -1 f p f i t f f t 0));
 /* no OIDs in pg_group */
-DATA(insert ( 1261 xmin				28 0  4  -3 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1261 cmin				29 0  4  -4 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1261 xmax				28 0  4  -5 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1261 cmax				29 0  4  -6 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1261 tableoid			26 0  4  -7 0 -1 -1 t p f i t f f f));
+DATA(insert ( 1261 xmin				28 0  4  -3 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1261 cmin				29 0  4  -4 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1261 xmax				28 0  4  -5 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1261 cmax				29 0  4  -6 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1261 tableoid			26 0  4  -7 0 -1 -1 t p f i t f f t 0));
 
 /* ----------------
  *		pg_attribute
  * ----------------
  */
 #define Schema_pg_attribute \
-{ 1249, {"attrelid"},	  26, -1,	4,	1, 0, -1, -1, true, 'p', false, 'i', true, false, false, false }, \
-{ 1249, {"attname"},	  19, -1, NAMEDATALEN,	2, 0, -1, -1, false, 'p', false, 'i', true, false, false, false }, \
-{ 1249, {"atttypid"},	  26, 0,	4,	3, 0, -1, -1, true, 'p', false, 'i', true, false, false, false }, \
-{ 1249, {"attstattarget"}, 23, 0,	4,	4, 0, -1, -1, true, 'p', false, 'i', true, false, false, false }, \
-{ 1249, {"attlen"},		  21, 0,	2,	5, 0, -1, -1, true, 'p', false, 's', true, false, false, false }, \
-{ 1249, {"attnum"},		  21, 0,	2,	6, 0, -1, -1, true, 'p', false, 's', true, false, false, false }, \
-{ 1249, {"attndims"},	  23, 0,	4,	7, 0, -1, -1, true, 'p', false, 'i', true, false, false, false }, \
-{ 1249, {"attcacheoff"},  23, 0,	4,	8, 0, -1, -1, true, 'p', false, 'i', true, false, false, false }, \
-{ 1249, {"atttypmod"},	  23, 0,	4,	9, 0, -1, -1, true, 'p', false, 'i', true, false, false, false }, \
-{ 1249, {"attbyval"},	  16, 0,	1, 10, 0, -1, -1, true, 'p', false, 'c', true, false, false, false }, \
-{ 1249, {"attstorage"},   18, 0,	1, 11, 0, -1, -1, true, 'p', false, 'c', true, false, false, false }, \
-{ 1249, {"attisset"},	  16, 0,	1, 12, 0, -1, -1, true, 'p', false, 'c', true, false, false, false }, \
-{ 1249, {"attalign"},	  18, 0,	1, 13, 0, -1, -1, true, 'p', false, 'c', true, false, false, false }, \
-{ 1249, {"attnotnull"},   16, 0, 1, 14, 0, -1, -1, true, 'p', false, 'c', true, false, false, false }, \
-{ 1249, {"atthasdef"},	  16, 0, 1, 15, 0, -1, -1, true, 'p', false, 'c', true, false, false, false }, \
-{ 1249, {"attisdropped"}, 16, 0, 1, 16, 0, -1, -1, true, 'p', false, 'c', true, false, false, false }, \
-{ 1249, {"attisinherited"},16,0, 1, 17, 0, -1, -1, true, 'p', false, 'c', true, false, false, false }
-
-DATA(insert ( 1249 attrelid			26 -1  4   1 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1249 attname			19 -1 NAMEDATALEN  2 0 -1 -1 f p f i t f f f));
-DATA(insert ( 1249 atttypid			26 0  4   3 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1249 attstattarget	23 0  4   4 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1249 attlen			21 0  2   5 0 -1 -1 t p f s t f f f));
-DATA(insert ( 1249 attnum			21 0  2   6 0 -1 -1 t p f s t f f f));
-DATA(insert ( 1249 attndims			23 0  4   7 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1249 attcacheoff		23 0  4   8 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1249 atttypmod		23 0  4   9 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1249 attbyval			16 0  1  10 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1249 attstorage		18 0  1  11 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1249 attisset			16 0  1  12 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1249 attalign			18 0  1  13 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1249 attnotnull		16 0  1  14 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1249 atthasdef		16 0  1  15 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1249 attisdropped		16 0  1  16 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1249 attisinherited	16 0  1  17 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1249 ctid				27 0  6  -1 0 -1 -1 f p f i t f f f));
+{ 1249, {"attrelid"},	  26, -1,	4,	1, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1249, {"attname"},	  19, -1, NAMEDATALEN,	2, 0, -1, -1, false, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1249, {"atttypid"},	  26, 0,	4,	3, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1249, {"attstattarget"}, 23, 0,	4,	4, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1249, {"attlen"},		  21, 0,	2,	5, 0, -1, -1, true, 'p', false, 's', true, false, false, true, 0 }, \
+{ 1249, {"attnum"},		  21, 0,	2,	6, 0, -1, -1, true, 'p', false, 's', true, false, false, true, 0 }, \
+{ 1249, {"attndims"},	  23, 0,	4,	7, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1249, {"attcacheoff"},  23, 0,	4,	8, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1249, {"atttypmod"},	  23, 0,	4,	9, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1249, {"attbyval"},	  16, 0,	1, 10, 0, -1, -1, true, 'p', false, 'c', true, false, false, true, 0 }, \
+{ 1249, {"attstorage"},   18, 0,	1, 11, 0, -1, -1, true, 'p', false, 'c', true, false, false, true, 0 }, \
+{ 1249, {"attisset"},	  16, 0,	1, 12, 0, -1, -1, true, 'p', false, 'c', true, false, false, true, 0 }, \
+{ 1249, {"attalign"},	  18, 0,	1, 13, 0, -1, -1, true, 'p', false, 'c', true, false, false, true, 0 }, \
+{ 1249, {"attnotnull"},   16, 0, 1, 14, 0, -1, -1, true, 'p', false, 'c', true, false, false, true, 0 }, \
+{ 1249, {"atthasdef"},	  16, 0, 1, 15, 0, -1, -1, true, 'p', false, 'c', true, false, false, true, 0 }, \
+{ 1249, {"attisdropped"}, 16, 0, 1, 16, 0, -1, -1, true, 'p', false, 'c', true, false, false, true, 0 }, \
+{ 1249, {"attislocal"},	  16, 0, 1, 17, 0, -1, -1, true, 'p', false, 'c', true, false, false, true, 0 }, \
+{ 1249, {"attinhcount"},  23, 0, 4,	18, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }
+
+DATA(insert ( 1249 attrelid			26 -1  4   1 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1249 attname			19 -1 NAMEDATALEN  2 0 -1 -1 f p f i t f f t 0));
+DATA(insert ( 1249 atttypid			26 0  4   3 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1249 attstattarget	23 0  4   4 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1249 attlen			21 0  2   5 0 -1 -1 t p f s t f f t 0));
+DATA(insert ( 1249 attnum			21 0  2   6 0 -1 -1 t p f s t f f t 0));
+DATA(insert ( 1249 attndims			23 0  4   7 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1249 attcacheoff		23 0  4   8 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1249 atttypmod		23 0  4   9 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1249 attbyval			16 0  1  10 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1249 attstorage		18 0  1  11 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1249 attisset			16 0  1  12 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1249 attalign			18 0  1  13 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1249 attnotnull		16 0  1  14 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1249 atthasdef		16 0  1  15 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1249 attisdropped		16 0  1  16 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1249 attislocal		16 0  1  17 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1249 attinhcount		23 0  4  18 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1249 ctid				27 0  6  -1 0 -1 -1 f p f i t f f t 0));
 /* no OIDs in pg_attribute */
-DATA(insert ( 1249 xmin				28 0  4  -3 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1249 cmin				29 0  4  -4 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1249 xmax				28 0  4  -5 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1249 cmax				29 0  4  -6 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1249 tableoid			26 0  4  -7 0 -1 -1 t p f i t f f f));
+DATA(insert ( 1249 xmin				28 0  4  -3 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1249 cmin				29 0  4  -4 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1249 xmax				28 0  4  -5 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1249 cmax				29 0  4  -6 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1249 tableoid			26 0  4  -7 0 -1 -1 t p f i t f f t 0));
 
 /* ----------------
  *		pg_class
  * ----------------
  */
 #define Schema_pg_class \
-{ 1259, {"relname"},	   19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', false, 'i', true, false, false, false }, \
-{ 1259, {"relnamespace"},  26, -1,	4,	2, 0, -1, -1, true, 'p', false, 'i', true, false, false, false }, \
-{ 1259, {"reltype"},	   26, 0,	4,	3, 0, -1, -1, true, 'p', false, 'i', true, false, false, false }, \
-{ 1259, {"relowner"},	   23, 0,	4,	4, 0, -1, -1, true, 'p', false, 'i', true, false, false, false }, \
-{ 1259, {"relam"},		   26, 0,	4,	5, 0, -1, -1, true, 'p', false, 'i', true, false, false, false }, \
-{ 1259, {"relfilenode"},   26, 0,	4,	6, 0, -1, -1, true, 'p', false, 'i', true, false, false, false }, \
-{ 1259, {"relpages"},	   23, 0,	4,	7, 0, -1, -1, true, 'p', false, 'i', true, false, false, false }, \
-{ 1259, {"reltuples"},	   700, 0,	4,	8, 0, -1, -1, false, 'p', false, 'i', true, false, false, false }, \
-{ 1259, {"reltoastrelid"}, 26, 0,	4,	9, 0, -1, -1, true, 'p', false, 'i', true, false, false, false }, \
-{ 1259, {"reltoastidxid"}, 26, 0,	4, 10, 0, -1, -1, true, 'p', false, 'i', true, false, false, false }, \
-{ 1259, {"relhasindex"},   16, 0,	1, 11, 0, -1, -1, true, 'p', false, 'c', true, false, false, false }, \
-{ 1259, {"relisshared"},   16, 0,	1, 12, 0, -1, -1, true, 'p', false, 'c', true, false, false, false }, \
-{ 1259, {"relkind"},	   18, -1,	1, 13, 0, -1, -1, true, 'p', false, 'c', true, false, false, false }, \
-{ 1259, {"relnatts"},	   21, 0,	2, 14, 0, -1, -1, true, 'p', false, 's', true, false, false, false }, \
-{ 1259, {"relchecks"},	   21, 0,	2, 15, 0, -1, -1, true, 'p', false, 's', true, false, false, false }, \
-{ 1259, {"reltriggers"},   21, 0,	2, 16, 0, -1, -1, true, 'p', false, 's', true, false, false, false }, \
-{ 1259, {"relukeys"},	   21, 0,	2, 17, 0, -1, -1, true, 'p', false, 's', true, false, false, false }, \
-{ 1259, {"relfkeys"},	   21, 0,	2, 18, 0, -1, -1, true, 'p', false, 's', true, false, false, false }, \
-{ 1259, {"relrefs"},	   21, 0,	2, 19, 0, -1, -1, true, 'p', false, 's', true, false, false, false }, \
-{ 1259, {"relhasoids"},    16, 0,	1, 20, 0, -1, -1, true, 'p', false, 'c', true, false, false, false }, \
-{ 1259, {"relhaspkey"},    16, 0,	1, 21, 0, -1, -1, true, 'p', false, 'c', true, false, false, false }, \
-{ 1259, {"relhasrules"},   16, 0,	1, 22, 0, -1, -1, true, 'p', false, 'c', true, false, false, false }, \
-{ 1259, {"relhassubclass"},16, 0,	1, 23, 0, -1, -1, true, 'p', false, 'c', true, false, false, false }, \
-{ 1259, {"relacl"},		 1034, 0,  -1, 24, 0, -1, -1, false, 'x', false, 'i', false, false, false, false }
-
-DATA(insert ( 1259 relname			19 -1 NAMEDATALEN	1 0 -1 -1 f p f i t f f f));
-DATA(insert ( 1259 relnamespace		26 -1 4   2 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1259 reltype			26 0  4   3 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1259 relowner			23 0  4   4 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1259 relam			26 0  4   5 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1259 relfilenode		26 0  4   6 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1259 relpages			23 0  4   7 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1259 reltuples	   700 0  4   8 0 -1 -1 f p f i t f f f));
-DATA(insert ( 1259 reltoastrelid	26 0  4   9 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1259 reltoastidxid	26 0  4  10 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1259 relhasindex		16 0  1  11 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1259 relisshared		16 0  1  12 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1259 relkind			18 -1 1  13 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1259 relnatts			21 0  2  14 0 -1 -1 t p f s t f f f));
-DATA(insert ( 1259 relchecks		21 0  2  15 0 -1 -1 t p f s t f f f));
-DATA(insert ( 1259 reltriggers		21 0  2  16 0 -1 -1 t p f s t f f f));
-DATA(insert ( 1259 relukeys			21 0  2  17 0 -1 -1 t p f s t f f f));
-DATA(insert ( 1259 relfkeys			21 0  2  18 0 -1 -1 t p f s t f f f));
-DATA(insert ( 1259 relrefs			21 0  2  19 0 -1 -1 t p f s t f f f));
-DATA(insert ( 1259 relhasoids		16 0  1  20 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1259 relhaspkey		16 0  1  21 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1259 relhasrules		16 0  1  22 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1259 relhassubclass	16 0  1  23 0 -1 -1 t p f c t f f f));
-DATA(insert ( 1259 relacl		  1034 0 -1  24 0 -1 -1 f x f i f f f f));
-DATA(insert ( 1259 ctid				27 0  6  -1 0 -1 -1 f p f i t f f f));
-DATA(insert ( 1259 oid				26 0  4  -2 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1259 xmin				28 0  4  -3 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1259 cmin				29 0  4  -4 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1259 xmax				28 0  4  -5 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1259 cmax				29 0  4  -6 0 -1 -1 t p f i t f f f));
-DATA(insert ( 1259 tableoid			26 0  4  -7 0 -1 -1 t p f i t f f f));
+{ 1259, {"relname"},	   19, -1, NAMEDATALEN, 1, 0, -1, -1, false, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1259, {"relnamespace"},  26, -1,	4,	2, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1259, {"reltype"},	   26, 0,	4,	3, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1259, {"relowner"},	   23, 0,	4,	4, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1259, {"relam"},		   26, 0,	4,	5, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1259, {"relfilenode"},   26, 0,	4,	6, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1259, {"relpages"},	   23, 0,	4,	7, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1259, {"reltuples"},	   700, 0,	4,	8, 0, -1, -1, false, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1259, {"reltoastrelid"}, 26, 0,	4,	9, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1259, {"reltoastidxid"}, 26, 0,	4, 10, 0, -1, -1, true, 'p', false, 'i', true, false, false, true, 0 }, \
+{ 1259, {"relhasindex"},   16, 0,	1, 11, 0, -1, -1, true, 'p', false, 'c', true, false, false, true, 0 }, \
+{ 1259, {"relisshared"},   16, 0,	1, 12, 0, -1, -1, true, 'p', false, 'c', true, false, false, true, 0 }, \
+{ 1259, {"relkind"},	   18, -1,	1, 13, 0, -1, -1, true, 'p', false, 'c', true, false, false, true, 0 }, \
+{ 1259, {"relnatts"},	   21, 0,	2, 14, 0, -1, -1, true, 'p', false, 's', true, false, false, true, 0 }, \
+{ 1259, {"relchecks"},	   21, 0,	2, 15, 0, -1, -1, true, 'p', false, 's', true, false, false, true, 0 }, \
+{ 1259, {"reltriggers"},   21, 0,	2, 16, 0, -1, -1, true, 'p', false, 's', true, false, false, true, 0 }, \
+{ 1259, {"relukeys"},	   21, 0,	2, 17, 0, -1, -1, true, 'p', false, 's', true, false, false, true, 0 }, \
+{ 1259, {"relfkeys"},	   21, 0,	2, 18, 0, -1, -1, true, 'p', false, 's', true, false, false, true, 0 }, \
+{ 1259, {"relrefs"},	   21, 0,	2, 19, 0, -1, -1, true, 'p', false, 's', true, false, false, true, 0 }, \
+{ 1259, {"relhasoids"},    16, 0,	1, 20, 0, -1, -1, true, 'p', false, 'c', true, false, false, true, 0 }, \
+{ 1259, {"relhaspkey"},    16, 0,	1, 21, 0, -1, -1, true, 'p', false, 'c', true, false, false, true, 0 }, \
+{ 1259, {"relhasrules"},   16, 0,	1, 22, 0, -1, -1, true, 'p', false, 'c', true, false, false, true, 0 }, \
+{ 1259, {"relhassubclass"},16, 0,	1, 23, 0, -1, -1, true, 'p', false, 'c', true, false, false, true, 0 }, \
+{ 1259, {"relacl"},		 1034, 0,  -1, 24, 0, -1, -1, false, 'x', false, 'i', false, false, false, true, 0 }
+
+DATA(insert ( 1259 relname			19 -1 NAMEDATALEN	1 0 -1 -1 f p f i t f f t 0));
+DATA(insert ( 1259 relnamespace		26 -1 4   2 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1259 reltype			26 0  4   3 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1259 relowner			23 0  4   4 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1259 relam			26 0  4   5 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1259 relfilenode		26 0  4   6 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1259 relpages			23 0  4   7 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1259 reltuples	   700 0  4   8 0 -1 -1 f p f i t f f t 0));
+DATA(insert ( 1259 reltoastrelid	26 0  4   9 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1259 reltoastidxid	26 0  4  10 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1259 relhasindex		16 0  1  11 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1259 relisshared		16 0  1  12 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1259 relkind			18 -1 1  13 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1259 relnatts			21 0  2  14 0 -1 -1 t p f s t f f t 0));
+DATA(insert ( 1259 relchecks		21 0  2  15 0 -1 -1 t p f s t f f t 0));
+DATA(insert ( 1259 reltriggers		21 0  2  16 0 -1 -1 t p f s t f f t 0));
+DATA(insert ( 1259 relukeys			21 0  2  17 0 -1 -1 t p f s t f f t 0));
+DATA(insert ( 1259 relfkeys			21 0  2  18 0 -1 -1 t p f s t f f t 0));
+DATA(insert ( 1259 relrefs			21 0  2  19 0 -1 -1 t p f s t f f t 0));
+DATA(insert ( 1259 relhasoids		16 0  1  20 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1259 relhaspkey		16 0  1  21 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1259 relhasrules		16 0  1  22 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1259 relhassubclass	16 0  1  23 0 -1 -1 t p f c t f f t 0));
+DATA(insert ( 1259 relacl		  1034 0 -1  24 0 -1 -1 f x f i f f f t 0));
+DATA(insert ( 1259 ctid				27 0  6  -1 0 -1 -1 f p f i t f f t 0));
+DATA(insert ( 1259 oid				26 0  4  -2 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1259 xmin				28 0  4  -3 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1259 cmin				29 0  4  -4 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1259 xmax				28 0  4  -5 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1259 cmax				29 0  4  -6 0 -1 -1 t p f i t f f t 0));
+DATA(insert ( 1259 tableoid			26 0  4  -7 0 -1 -1 t p f i t f f t 0));
 
 /* ----------------
  *		pg_xactlock - this is not a real relation, but is a placeholder
@@ -490,6 +499,6 @@ DATA(insert ( 1259 tableoid			26 0  4  -7 0 -1 -1 t p f i t f f f));
  *				  table; and this entry is just to link to that one.
  * ----------------
  */
-DATA(insert ( 376 xactlockfoo		26 0  4   1 0 -1 -1 t p f i t f f f));
+DATA(insert ( 376 xactlockfoo		26 0  4   1 0 -1 -1 t p f i t f f t 0));
 
 #endif   /* PG_ATTRIBUTE_H */
diff --git a/src/include/catalog/pg_class.h b/src/include/catalog/pg_class.h
index 59e4e929acd..0843cbf6fc8 100644
--- a/src/include/catalog/pg_class.h
+++ b/src/include/catalog/pg_class.h
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $Id: pg_class.h,v 1.73 2002/09/04 20:31:37 momjian Exp $
+ * $Id: pg_class.h,v 1.74 2002/09/22 19:42:52 tgl Exp $
  *
  * NOTES
  *	  the genbki.sh script reads this file and generates .bki
@@ -136,7 +136,7 @@ typedef FormData_pg_class *Form_pg_class;
 
 DATA(insert OID = 1247 (  pg_type		PGNSP 71 PGUID 0 1247 0 0 0 0 f f r 20 0 0 0 0 0 t f f f _null_ ));
 DESCR("");
-DATA(insert OID = 1249 (  pg_attribute	PGNSP 75 PGUID 0 1249 0 0 0 0 f f r 17 0 0 0 0 0 f f f f _null_ ));
+DATA(insert OID = 1249 (  pg_attribute	PGNSP 75 PGUID 0 1249 0 0 0 0 f f r 18 0 0 0 0 0 f f f f _null_ ));
 DESCR("");
 DATA(insert OID = 1255 (  pg_proc		PGNSP 81 PGUID 0 1255 0 0 0 0 f f r 15 0 0 0 0 0 t f f f _null_ ));
 DESCR("");
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 56e3922ea9f..cde4acebc21 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.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: parsenodes.h,v 1.207 2002/09/18 21:35:24 tgl Exp $
+ * $Id: parsenodes.h,v 1.208 2002/09/22 19:42:52 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -301,7 +301,8 @@ typedef struct ColumnDef
 	NodeTag		type;
 	char	   *colname;		/* name of column */
 	TypeName   *typename;		/* type of column */
-	bool		is_inherited;	/* column is inherited? */
+	int			inhcount;		/* number of times column is inherited */
+	bool		is_local;		/* column has local (non-inherited) def'n */
 	bool		is_not_null;	/* NOT NULL constraint specified? */
 	Node	   *raw_default;	/* default value (untransformed parse
 								 * tree) */
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index ac4efb8e9cc..de2e4a29757 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -1054,3 +1054,116 @@ alter table renameColumn add column w int;
 -- this should fail
 alter table only renameColumn add column x int;
 ERROR:  Attribute must be added to child tables too
+-- Test corner cases in dropping of inherited columns
+create table p1 (f1 int, f2 int);
+create table c1 (f1 int not null) inherits(p1);
+NOTICE:  CREATE TABLE: merging attribute "f1" with inherited definition
+-- should be rejected since c1.f1 is inherited
+alter table c1 drop column f1;
+ERROR:  ALTER TABLE: Cannot drop inherited column "f1"
+-- should work
+alter table p1 drop column f1;
+-- c1.f1 is still there, but no longer inherited
+select f1 from c1;
+ f1 
+----
+(0 rows)
+
+alter table c1 drop column f1;
+select f1 from c1;
+ERROR:  Attribute "f1" not found
+drop table p1 cascade;
+NOTICE:  Drop cascades to table c1
+create table p1 (f1 int, f2 int);
+create table c1 () inherits(p1);
+-- should be rejected since c1.f1 is inherited
+alter table c1 drop column f1;
+ERROR:  ALTER TABLE: Cannot drop inherited column "f1"
+alter table p1 drop column f1;
+-- c1.f1 is dropped now, since there is no local definition for it
+select f1 from c1;
+ERROR:  Attribute "f1" not found
+drop table p1 cascade;
+NOTICE:  Drop cascades to table c1
+create table p1 (f1 int, f2 int);
+create table c1 () inherits(p1);
+-- should be rejected since c1.f1 is inherited
+alter table c1 drop column f1;
+ERROR:  ALTER TABLE: Cannot drop inherited column "f1"
+alter table only p1 drop column f1;
+-- c1.f1 is NOT dropped, but must now be considered non-inherited
+alter table c1 drop column f1;
+drop table p1 cascade;
+NOTICE:  Drop cascades to table c1
+create table p1 (f1 int, f2 int);
+create table c1 (f1 int not null) inherits(p1);
+NOTICE:  CREATE TABLE: merging attribute "f1" with inherited definition
+-- should be rejected since c1.f1 is inherited
+alter table c1 drop column f1;
+ERROR:  ALTER TABLE: Cannot drop inherited column "f1"
+alter table only p1 drop column f1;
+-- c1.f1 is still there, but no longer inherited
+alter table c1 drop column f1;
+drop table p1 cascade;
+NOTICE:  Drop cascades to table c1
+create table p1(id int, name text);
+create table p2(id2 int, name text, height int);
+create table c1(age int) inherits(p1,p2);
+NOTICE:  CREATE TABLE: merging multiple inherited definitions of attribute "name"
+create table gc1() inherits (c1);
+select relname, attname, attinhcount, attislocal
+from pg_class join pg_attribute on (pg_class.oid = pg_attribute.attrelid)
+where relname in ('p1','p2','c1','gc1') and attnum > 0 and not attisdropped
+order by relname, attnum;
+ relname | attname | attinhcount | attislocal 
+---------+---------+-------------+------------
+ c1      | id      |           1 | f
+ c1      | name    |           2 | f
+ c1      | id2     |           1 | f
+ c1      | height  |           1 | f
+ c1      | age     |           0 | t
+ gc1     | id      |           1 | f
+ gc1     | name    |           1 | f
+ gc1     | id2     |           1 | f
+ gc1     | height  |           1 | f
+ gc1     | age     |           1 | f
+ p1      | id      |           0 | t
+ p1      | name    |           0 | t
+ p2      | id2     |           0 | t
+ p2      | name    |           0 | t
+ p2      | height  |           0 | t
+(15 rows)
+
+-- should work
+alter table only p1 drop column name;
+-- should work. Now c1.name is local and inhcount is 0.
+alter table p2 drop column name;
+-- should be rejected since its inherited
+alter table gc1 drop column name;
+ERROR:  ALTER TABLE: Cannot drop inherited column "name"
+-- should work, and drop gc1.name along
+alter table c1 drop column name;
+-- should fail: column does not exist
+alter table gc1 drop column name;
+ERROR:  Relation "gc1" has no column "name"
+-- should work and drop the attribute in all tables
+alter table p2 drop column height;
+select relname, attname, attinhcount, attislocal
+from pg_class join pg_attribute on (pg_class.oid = pg_attribute.attrelid)
+where relname in ('p1','p2','c1','gc1') and attnum > 0 and not attisdropped
+order by relname, attnum;
+ relname | attname | attinhcount | attislocal 
+---------+---------+-------------+------------
+ c1      | id      |           1 | f
+ c1      | id2     |           1 | f
+ c1      | age     |           0 | t
+ gc1     | id      |           1 | f
+ gc1     | id2     |           1 | f
+ gc1     | age     |           1 | f
+ p1      | id      |           0 | t
+ p2      | id2     |           0 | t
+(8 rows)
+
+drop table p1, p2 cascade;
+NOTICE:  Drop cascades to table c1
+NOTICE:  Drop cascades to table gc1
diff --git a/src/test/regress/expected/type_sanity.out b/src/test/regress/expected/type_sanity.out
index 50000afcf90..03fbae2cadd 100644
--- a/src/test/regress/expected/type_sanity.out
+++ b/src/test/regress/expected/type_sanity.out
@@ -170,7 +170,8 @@ WHERE (p1.relkind = 'i' AND p1.relam = 0) OR
 SELECT p1.attrelid, p1.attname
 FROM pg_attribute as p1
 WHERE p1.attrelid = 0 OR p1.atttypid = 0 OR p1.attnum = 0 OR
-    p1.attcacheoff != -1;
+    p1.attcacheoff != -1 OR p1.attinhcount < 0 OR
+    (p1.attinhcount = 0 AND NOT p1.attislocal);
  attrelid | attname 
 ----------+---------
 (0 rows)
diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql
index a5b6bd8f037..b74df5a7256 100644
--- a/src/test/regress/sql/alter_table.sql
+++ b/src/test/regress/sql/alter_table.sql
@@ -764,3 +764,83 @@ alter table renameColumn add column w int;
 
 -- this should fail
 alter table only renameColumn add column x int;
+
+
+-- Test corner cases in dropping of inherited columns
+
+create table p1 (f1 int, f2 int);
+create table c1 (f1 int not null) inherits(p1);
+
+-- should be rejected since c1.f1 is inherited
+alter table c1 drop column f1;
+-- should work
+alter table p1 drop column f1;
+-- c1.f1 is still there, but no longer inherited
+select f1 from c1;
+alter table c1 drop column f1;
+select f1 from c1;
+
+drop table p1 cascade;
+
+create table p1 (f1 int, f2 int);
+create table c1 () inherits(p1);
+
+-- should be rejected since c1.f1 is inherited
+alter table c1 drop column f1;
+alter table p1 drop column f1;
+-- c1.f1 is dropped now, since there is no local definition for it
+select f1 from c1;
+
+drop table p1 cascade;
+
+create table p1 (f1 int, f2 int);
+create table c1 () inherits(p1);
+
+-- should be rejected since c1.f1 is inherited
+alter table c1 drop column f1;
+alter table only p1 drop column f1;
+-- c1.f1 is NOT dropped, but must now be considered non-inherited
+alter table c1 drop column f1;
+
+drop table p1 cascade;
+
+create table p1 (f1 int, f2 int);
+create table c1 (f1 int not null) inherits(p1);
+
+-- should be rejected since c1.f1 is inherited
+alter table c1 drop column f1;
+alter table only p1 drop column f1;
+-- c1.f1 is still there, but no longer inherited
+alter table c1 drop column f1;
+
+drop table p1 cascade;
+
+create table p1(id int, name text);
+create table p2(id2 int, name text, height int);
+create table c1(age int) inherits(p1,p2);
+create table gc1() inherits (c1);
+
+select relname, attname, attinhcount, attislocal
+from pg_class join pg_attribute on (pg_class.oid = pg_attribute.attrelid)
+where relname in ('p1','p2','c1','gc1') and attnum > 0 and not attisdropped
+order by relname, attnum;
+
+-- should work
+alter table only p1 drop column name;
+-- should work. Now c1.name is local and inhcount is 0.
+alter table p2 drop column name;
+-- should be rejected since its inherited
+alter table gc1 drop column name;
+-- should work, and drop gc1.name along
+alter table c1 drop column name;
+-- should fail: column does not exist
+alter table gc1 drop column name;
+-- should work and drop the attribute in all tables
+alter table p2 drop column height;
+
+select relname, attname, attinhcount, attislocal
+from pg_class join pg_attribute on (pg_class.oid = pg_attribute.attrelid)
+where relname in ('p1','p2','c1','gc1') and attnum > 0 and not attisdropped
+order by relname, attnum;
+
+drop table p1, p2 cascade;
diff --git a/src/test/regress/sql/type_sanity.sql b/src/test/regress/sql/type_sanity.sql
index 3b297b3694d..4f827cd8bae 100644
--- a/src/test/regress/sql/type_sanity.sql
+++ b/src/test/regress/sql/type_sanity.sql
@@ -137,7 +137,8 @@ WHERE (p1.relkind = 'i' AND p1.relam = 0) OR
 SELECT p1.attrelid, p1.attname
 FROM pg_attribute as p1
 WHERE p1.attrelid = 0 OR p1.atttypid = 0 OR p1.attnum = 0 OR
-    p1.attcacheoff != -1;
+    p1.attcacheoff != -1 OR p1.attinhcount < 0 OR
+    (p1.attinhcount = 0 AND NOT p1.attislocal);
 
 -- Cross-check attnum against parent relation
 
-- 
GitLab