diff --git a/src/backend/catalog/pg_inherits.c b/src/backend/catalog/pg_inherits.c
index 00f2ae0..348e8e9 100644
--- a/src/backend/catalog/pg_inherits.c
+++ b/src/backend/catalog/pg_inherits.c
@@ -32,7 +32,121 @@
 #include "utils/tqual.h"
 
 static int	oid_cmp(const void *p1, const void *p2);
+static List *check_rel_entries(Oid *oidarr, int numoids, LOCKMODE lockmode);
 
+/*
+ * check_rel_entries
+ *
+ * Check the existence of relation entries scanned in pg_inherits and
+ * generate a list removing the ones that are deleted.
+ */
+static List *
+check_rel_entries(Oid *oidarr, int numoids, LOCKMODE lockmode)
+{
+	int		i;
+	List   *list = NIL;
+
+	/*
+	 * If we found more than one element, be it parent or child, sort them
+	 * by OID.  This ensures reasonably consistent behavior regardless of
+	 * the vagaries of an indexscan.  This is important since we need to
+	 * be sure all backends lock children in the same order to avoid needless
+	 * deadlocks.
+	 */
+	if (numoids > 1)
+		qsort(oidarr, numoids, sizeof(Oid), oid_cmp);
+
+	/*
+	 * Acquire locks and build the result list.
+	 */
+	for (i = 0; i < numoids; i++)
+	{
+		Oid relid;
+
+		relid = oidarr[i];
+
+		if (lockmode != NoLock)
+		{
+			/* Get the lock to synchronize against concurrent drop */
+			LockRelationOid(relid, lockmode);
+
+			/*
+			 * Now that we have the lock, double-check to see if the relation
+			 * really exists or not.  If not, assume it was dropped while we
+			 * waited to acquire lock, and ignore it.
+			 */
+			if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(relid)))
+			{
+				/* Release useless lock */
+				UnlockRelationOid(relid, lockmode);
+				/* And ignore this relation */
+				continue;
+			}
+		}
+
+		list = lappend_oid(list, relid);
+	}
+
+	return list;
+}
+
+/*
+ * find_inheritance_parents
+ *
+ * Returns a list containing the OIDs of all the relations that are direct
+ * parents of the given relation.
+ */
+List *
+find_inheritance_parents(Oid childrelid, LOCKMODE lockmode)
+{
+	List	   *list = NIL;
+	Relation	relation;
+	SysScanDesc	scan;
+	ScanKeyData	key[1];
+	HeapTuple	inheritsTuple;
+	Oid		   *oidarr;
+	int			maxoids,
+				numoids;
+
+	/*
+	 * Scan pg_inherits and build a working array of subclass OIDs.
+	 */
+	maxoids = 32;
+	oidarr = (Oid *) palloc(maxoids * sizeof(Oid));
+	numoids = 0;
+
+	relation = heap_open(InheritsRelationId, AccessShareLock);
+
+	ScanKeyInit(&key[0],
+				Anum_pg_inherits_inhrelid,
+				BTEqualStrategyNumber, F_OIDEQ,
+				ObjectIdGetDatum(childrelid));
+
+	scan = systable_beginscan(relation, InheritsRelidIndexId, true,
+							  NULL, 1, key);
+
+	while ((inheritsTuple = systable_getnext(scan)) != NULL)
+	{
+		Oid parentOid = ((Form_pg_inherits) GETSTRUCT(inheritsTuple))->inhparent;
+		if (numoids >= maxoids)
+		{
+			maxoids *= 2;
+			oidarr = (Oid *) repalloc(oidarr, maxoids * sizeof(Oid));
+		}
+		oidarr[numoids++] = parentOid;
+	}
+
+	systable_endscan(scan);
+
+	heap_close(relation, AccessShareLock);
+
+	/* remove relations potentially already deleted */
+	list = check_rel_entries(oidarr, numoids, lockmode);
+
+	pfree(oidarr);
+
+	return list;
+}
 
 /*
  * find_inheritance_children
@@ -56,8 +170,7 @@ find_inheritance_children(Oid parentrelId, LOCKMODE lockmode)
 	Oid			inhrelid;
 	Oid		   *oidarr;
 	int			maxoids,
-				numoids,
-				i;
+				numoids;
 
 	/*
 	 * Can skip the scan if pg_class shows the relation has never had a
@@ -98,43 +211,8 @@ find_inheritance_children(Oid parentrelId, LOCKMODE lockmode)
 
 	heap_close(relation, AccessShareLock);
 
-	/*
-	 * If we found more than one child, sort them by OID.  This ensures
-	 * reasonably consistent behavior regardless of the vagaries of an
-	 * indexscan.  This is important since we need to be sure all backends
-	 * lock children in the same order to avoid needless deadlocks.
-	 */
-	if (numoids > 1)
-		qsort(oidarr, numoids, sizeof(Oid), oid_cmp);
-
-	/*
-	 * Acquire locks and build the result list.
-	 */
-	for (i = 0; i < numoids; i++)
-	{
-		inhrelid = oidarr[i];
-
-		if (lockmode != NoLock)
-		{
-			/* Get the lock to synchronize against concurrent drop */
-			LockRelationOid(inhrelid, lockmode);
-
-			/*
-			 * Now that we have the lock, double-check to see if the relation
-			 * really exists or not.  If not, assume it was dropped while we
-			 * waited to acquire lock, and ignore it.
-			 */
-			if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(inhrelid)))
-			{
-				/* Release useless lock */
-				UnlockRelationOid(inhrelid, lockmode);
-				/* And ignore this relation */
-				continue;
-			}
-		}
-
-		list = lappend_oid(list, inhrelid);
-	}
+	/* remove relations potentially already deleted */
+	list = check_rel_entries(oidarr, numoids, lockmode);
 
 	pfree(oidarr);
 
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 86e9814..cc13982 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -5180,8 +5180,8 @@ ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode)
 	HeapTuple	tuple;
 	AttrNumber	attnum;
 	Relation	attr_rel;
-	List	   *indexoidlist;
-	ListCell   *indexoidscan;
+	List	   *oidlist;
+	ListCell   *oidscan;
 	ObjectAddress address;
 
 	/*
@@ -5213,11 +5213,11 @@ ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode)
 	 */
 
 	/* Loop over all indexes on the relation */
-	indexoidlist = RelationGetIndexList(rel);
+	oidlist = RelationGetIndexList(rel);
 
-	foreach(indexoidscan, indexoidlist)
+	foreach(oidscan, oidlist)
 	{
-		Oid			indexoid = lfirst_oid(indexoidscan);
+		Oid			indexoid = lfirst_oid(oidscan);
 		HeapTuple	indexTuple;
 		Form_pg_index indexStruct;
 		int			i;
@@ -5247,7 +5247,45 @@ ATExecDropNotNull(Relation rel, const char *colName, LOCKMODE lockmode)
 		ReleaseSysCache(indexTuple);
 	}
 
-	list_free(indexoidlist);
+	list_free(oidlist);
+
+	/*
+	 * Check if parent relations have a NOT NULL constraint on this column
+	 * and throw an error if that is the case.  All the direct parent
+	 * relations found in pg_inherits are checked.
+	 */
+	oidlist = find_inheritance_parents(RelationGetRelid(rel), lockmode);
+
+	foreach(oidscan, oidlist)
+	{
+		Oid			parentoid = lfirst_oid(oidscan);
+		HeapTuple	tuple;
+		Relation	attr_rel;
+		Form_pg_attribute parentatt;
+
+		attr_rel = heap_open(AttributeRelationId, RowExclusiveLock);
+
+		tuple = SearchSysCacheCopyAttName(parentoid, colName);
+		if (!HeapTupleIsValid(tuple))	/* shouldn't happen */
+			elog(ERROR, "cache lookup failed for attribute \"%s\" of relation %u",
+				 colName, parentoid);
+
+		parentatt = (Form_pg_attribute) GETSTRUCT(tuple);
+
+		if (parentatt->attnotnull)
+			ereport(ERROR,
+					(errcode(ERRCODE_INVALID_TABLE_DEFINITION),
+					 errmsg("cannot drop NOT NULL constraint for attribute \"%s\"",
+							colName),
+					 errdetail("The same column in parent relation \"%s\" is marked NOT NULL.",
+							   get_rel_name(parentoid))));
+
+		heap_freetuple(tuple);
+
+		heap_close(attr_rel, NoLock);
+	}
+
+	list_free(oidlist);
 
 	/*
 	 * Okay, actually perform the catalog change ... if needed
diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h
index ca5eb3d..dffa15f 100644
--- a/src/include/catalog/indexing.h
+++ b/src/include/catalog/indexing.h
@@ -161,6 +161,8 @@ DECLARE_UNIQUE_INDEX(pg_inherits_relid_seqno_index, 2680, on pg_inherits using b
 #define InheritsRelidSeqnoIndexId  2680
 DECLARE_INDEX(pg_inherits_parent_index, 2187, on pg_inherits using btree(inhparent oid_ops));
 #define InheritsParentIndexId  2187
+DECLARE_INDEX(pg_inherits_relid_index, 3343, on pg_inherits using btree(inhrelid oid_ops));
+#define InheritsRelidIndexId  3343
 
 DECLARE_UNIQUE_INDEX(pg_init_privs_o_c_o_index, 3395, on pg_init_privs using btree(objoid oid_ops, classoid oid_ops, objsubid int4_ops));
 #define InitPrivsObjIndexId  3395
diff --git a/src/include/catalog/pg_inherits_fn.h b/src/include/catalog/pg_inherits_fn.h
index a717108..bb924ed 100644
--- a/src/include/catalog/pg_inherits_fn.h
+++ b/src/include/catalog/pg_inherits_fn.h
@@ -17,6 +17,7 @@
 #include "nodes/pg_list.h"
 #include "storage/lock.h"
 
+extern List *find_inheritance_parents(Oid childrelid, LOCKMODE lockmode);
 extern List *find_inheritance_children(Oid parentrelId, LOCKMODE lockmode);
 extern List *find_all_inheritors(Oid parentrelId, LOCKMODE lockmode,
 					List **parents);
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index 3232cda..026233c 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -2914,3 +2914,15 @@ Table "public.test_add_column"
  c4     | integer | 
 
 DROP TABLE test_add_column;
+-- tests for NOT NULL with inherited tables
+CREATE TABLE parent_drop_null (id int NOT NULL);
+CREATE TABLE child_drop_null (id int);
+ALTER TABLE child_drop_null INHERIT parent_drop_null; -- error
+ERROR:  column "id" in child table must be marked NOT NULL
+ALTER TABLE child_drop_null ALTER COLUMN id SET NOT NULL;
+ALTER TABLE child_drop_null INHERIT parent_drop_null; -- ok
+ALTER TABLE child_drop_null ALTER COLUMN id DROP NOT NULL; -- error
+ERROR:  cannot drop NOT NULL constraint for attribute "id"
+DETAIL:  The same column in parent relation "parent_drop_null" is marked NOT NULL.
+DROP TABLE child_drop_null;
+DROP TABLE parent_drop_null;
diff --git a/src/test/regress/sql/alter_table.sql b/src/test/regress/sql/alter_table.sql
index 72e65d4..bd40297 100644
--- a/src/test/regress/sql/alter_table.sql
+++ b/src/test/regress/sql/alter_table.sql
@@ -1842,3 +1842,13 @@ ALTER TABLE test_add_column
 	ADD COLUMN c4 integer;
 \d test_add_column
 DROP TABLE test_add_column;
+
+-- tests for NOT NULL with inherited tables
+CREATE TABLE parent_drop_null (id int NOT NULL);
+CREATE TABLE child_drop_null (id int);
+ALTER TABLE child_drop_null INHERIT parent_drop_null; -- error
+ALTER TABLE child_drop_null ALTER COLUMN id SET NOT NULL;
+ALTER TABLE child_drop_null INHERIT parent_drop_null; -- ok
+ALTER TABLE child_drop_null ALTER COLUMN id DROP NOT NULL; -- error
+DROP TABLE child_drop_null;
+DROP TABLE parent_drop_null;
