diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index b7c431d3727232c4cbff26be43f98efec0f1e606..7622d035f7c177bc6f46d45dada2147f5dc06005 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.1 2002/07/12 18:43:13 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/dependency.c,v 1.2 2002/07/15 16:33:31 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -21,6 +21,7 @@
 #include "catalog/heap.h"
 #include "catalog/index.h"
 #include "catalog/indexing.h"
+#include "catalog/pg_attrdef.h"
 #include "catalog/pg_constraint.h"
 #include "catalog/pg_depend.h"
 #include "catalog/pg_language.h"
@@ -46,6 +47,7 @@ typedef enum ObjectClasses
 	OCLASS_PROC,				/* pg_proc */
 	OCLASS_TYPE,				/* pg_type */
 	OCLASS_CONSTRAINT,			/* pg_constraint */
+	OCLASS_DEFAULT,				/* pg_attrdef */
 	OCLASS_LANGUAGE,			/* pg_language */
 	OCLASS_OPERATOR,			/* pg_operator */
 	OCLASS_REWRITE,				/* pg_rewrite */
@@ -59,6 +61,7 @@ static bool recursiveDeletion(const ObjectAddress *object,
 static void doDeletion(const ObjectAddress *object);
 static ObjectClasses getObjectClass(const ObjectAddress *object);
 static char *getObjectDescription(const ObjectAddress *object);
+static void getRelationDescription(StringInfo buffer, Oid relid);
 
 
 /*
@@ -285,7 +288,7 @@ recursiveDeletion(const ObjectAddress *object,
 				 * RESTRICT case.  (However, normal dependencies on the
 				 * component object could still cause failure.)
 				 */
-				elog(DEBUG1, "Drop internally cascades to %s",
+				elog(DEBUG1, "Drop auto-cascades to %s",
 					 getObjectDescription(&otherObject));
 
 				if (!recursiveDeletion(&otherObject, behavior,
@@ -392,6 +395,10 @@ doDeletion(const ObjectAddress *object)
 			RemoveConstraintById(object->objectId);
 			break;
 
+		case OCLASS_DEFAULT:
+			RemoveAttrDefaultById(object->objectId);
+			break;
+
 		case OCLASS_LANGUAGE:
 			DropProceduralLanguageById(object->objectId);
 			break;
@@ -425,6 +432,7 @@ getObjectClass(const ObjectAddress *object)
 {
 	static bool reloids_initialized = false;
 	static Oid	reloid_pg_constraint;
+	static Oid	reloid_pg_attrdef;
 	static Oid	reloid_pg_language;
 	static Oid	reloid_pg_operator;
 	static Oid	reloid_pg_rewrite;
@@ -456,6 +464,7 @@ getObjectClass(const ObjectAddress *object)
 	if (!reloids_initialized)
 	{
 		reloid_pg_constraint = get_system_catalog_relid(ConstraintRelationName);
+		reloid_pg_attrdef = get_system_catalog_relid(AttrDefaultRelationName);
 		reloid_pg_language = get_system_catalog_relid(LanguageRelationName);
 		reloid_pg_operator = get_system_catalog_relid(OperatorRelationName);
 		reloid_pg_rewrite = get_system_catalog_relid(RewriteRelationName);
@@ -468,6 +477,11 @@ getObjectClass(const ObjectAddress *object)
 		Assert(object->objectSubId == 0);
 		return OCLASS_CONSTRAINT;
 	}
+	if (object->classId == reloid_pg_attrdef)
+	{
+		Assert(object->objectSubId == 0);
+		return OCLASS_DEFAULT;
+	}
 	if (object->classId == reloid_pg_language)
 	{
 		Assert(object->objectSubId == 0);
@@ -509,63 +523,12 @@ getObjectDescription(const ObjectAddress *object)
 	switch (getObjectClass(object))
 	{
 		case OCLASS_CLASS:
-		{
-			HeapTuple	relTup;
-			Form_pg_class	relForm;
-
-			relTup = SearchSysCache(RELOID,
-									ObjectIdGetDatum(object->objectId),
-									0, 0, 0);
-			if (!HeapTupleIsValid(relTup))
-				elog(ERROR, "getObjectDescription: Relation %u does not exist",
-					 object->objectId);
-			relForm = (Form_pg_class) GETSTRUCT(relTup);
-
-			switch (relForm->relkind)
-			{
-				case RELKIND_RELATION:
-					appendStringInfo(&buffer, "table %s",
-									 NameStr(relForm->relname));
-					break;
-				case RELKIND_INDEX:
-					appendStringInfo(&buffer, "index %s",
-									 NameStr(relForm->relname));
-					break;
-				case RELKIND_SPECIAL:
-					appendStringInfo(&buffer, "special system relation %s",
-									 NameStr(relForm->relname));
-					break;
-				case RELKIND_SEQUENCE:
-					appendStringInfo(&buffer, "sequence %s",
-									 NameStr(relForm->relname));
-					break;
-				case RELKIND_UNCATALOGED:
-					appendStringInfo(&buffer, "uncataloged table %s",
-									 NameStr(relForm->relname));
-					break;
-				case RELKIND_TOASTVALUE:
-					appendStringInfo(&buffer, "toast table %s",
-									 NameStr(relForm->relname));
-					break;
-				case RELKIND_VIEW:
-					appendStringInfo(&buffer, "view %s",
-									 NameStr(relForm->relname));
-					break;
-				default:
-					/* shouldn't get here */
-					appendStringInfo(&buffer, "relation %s",
-									 NameStr(relForm->relname));
-					break;
-			}
-
+			getRelationDescription(&buffer, object->objectId);
 			if (object->objectSubId != 0)
 				appendStringInfo(&buffer, " column %s",
 								 get_attname(object->objectId,
 											 object->objectSubId));
-
-			ReleaseSysCache(relTup);
 			break;
-		}
 
 		case OCLASS_PROC:
 			/* XXX could improve on this */
@@ -614,17 +577,61 @@ getObjectDescription(const ObjectAddress *object)
 
 			con = (Form_pg_constraint) GETSTRUCT(tup);
 
-			appendStringInfo(&buffer, "constraint %s",
-							 NameStr(con->conname));
 			if (OidIsValid(con->conrelid))
-				appendStringInfo(&buffer, " on table %s",
-								 get_rel_name(con->conrelid));
+			{
+				appendStringInfo(&buffer, "constraint %s on ",
+								 NameStr(con->conname));
+				getRelationDescription(&buffer, con->conrelid);
+			}
+			else
+			{
+				appendStringInfo(&buffer, "constraint %s",
+								 NameStr(con->conname));
+			}
 
 			systable_endscan(rcscan);
 			heap_close(conDesc, AccessShareLock);
 			break;
 		}
 
+		case OCLASS_DEFAULT:
+		{
+			Relation		attrdefDesc;
+			ScanKeyData		skey[1];
+			SysScanDesc		adscan;
+			HeapTuple		tup;
+			Form_pg_attrdef attrdef;
+			ObjectAddress	colobject;
+
+			attrdefDesc = heap_openr(AttrDefaultRelationName, AccessShareLock);
+
+			ScanKeyEntryInitialize(&skey[0], 0x0,
+								   ObjectIdAttributeNumber, F_OIDEQ,
+								   ObjectIdGetDatum(object->objectId));
+
+			adscan = systable_beginscan(attrdefDesc, AttrDefaultOidIndex, true,
+										SnapshotNow, 1, skey);
+
+			tup = systable_getnext(adscan);
+
+			if (!HeapTupleIsValid(tup))
+				elog(ERROR, "getObjectDescription: Default %u does not exist",
+					 object->objectId);
+
+			attrdef = (Form_pg_attrdef) GETSTRUCT(tup);
+
+			colobject.classId = RelOid_pg_class;
+			colobject.objectId = attrdef->adrelid;
+			colobject.objectSubId = attrdef->adnum;
+
+			appendStringInfo(&buffer, "default for %s",
+							 getObjectDescription(&colobject));
+
+			systable_endscan(adscan);
+			heap_close(attrdefDesc, AccessShareLock);
+			break;
+		}
+
 		case OCLASS_LANGUAGE:
 		{
 			HeapTuple		langTup;
@@ -672,11 +679,9 @@ getObjectDescription(const ObjectAddress *object)
 
 			rule = (Form_pg_rewrite) GETSTRUCT(tup);
 
-			appendStringInfo(&buffer, "rule %s",
+			appendStringInfo(&buffer, "rule %s on ",
 							 NameStr(rule->rulename));
-			if (OidIsValid(rule->ev_class))
-				appendStringInfo(&buffer, " on table %s",
-								 get_rel_name(rule->ev_class));
+			getRelationDescription(&buffer, rule->ev_class);
 
 			systable_endscan(rcscan);
 			heap_close(ruleDesc, AccessShareLock);
@@ -708,11 +713,9 @@ getObjectDescription(const ObjectAddress *object)
 
 			trig = (Form_pg_trigger) GETSTRUCT(tup);
 
-			appendStringInfo(&buffer, "trigger %s",
+			appendStringInfo(&buffer, "trigger %s on ",
 							 NameStr(trig->tgname));
-			if (OidIsValid(trig->tgrelid))
-				appendStringInfo(&buffer, " on table %s",
-								 get_rel_name(trig->tgrelid));
+			getRelationDescription(&buffer, trig->tgrelid);
 
 			systable_endscan(tgscan);
 			heap_close(trigDesc, AccessShareLock);
@@ -729,3 +732,60 @@ getObjectDescription(const ObjectAddress *object)
 
 	return buffer.data;
 }
+
+/*
+ * subroutine for getObjectDescription: describe a relation
+ */
+static void
+getRelationDescription(StringInfo buffer, Oid relid)
+{
+	HeapTuple	relTup;
+	Form_pg_class	relForm;
+
+	relTup = SearchSysCache(RELOID,
+							ObjectIdGetDatum(relid),
+							0, 0, 0);
+	if (!HeapTupleIsValid(relTup))
+		elog(ERROR, "getObjectDescription: Relation %u does not exist",
+			 relid);
+	relForm = (Form_pg_class) GETSTRUCT(relTup);
+
+	switch (relForm->relkind)
+	{
+		case RELKIND_RELATION:
+			appendStringInfo(buffer, "table %s",
+							 NameStr(relForm->relname));
+			break;
+		case RELKIND_INDEX:
+			appendStringInfo(buffer, "index %s",
+							 NameStr(relForm->relname));
+			break;
+		case RELKIND_SPECIAL:
+			appendStringInfo(buffer, "special system relation %s",
+							 NameStr(relForm->relname));
+			break;
+		case RELKIND_SEQUENCE:
+			appendStringInfo(buffer, "sequence %s",
+							 NameStr(relForm->relname));
+			break;
+		case RELKIND_UNCATALOGED:
+			appendStringInfo(buffer, "uncataloged table %s",
+							 NameStr(relForm->relname));
+			break;
+		case RELKIND_TOASTVALUE:
+			appendStringInfo(buffer, "toast table %s",
+							 NameStr(relForm->relname));
+			break;
+		case RELKIND_VIEW:
+			appendStringInfo(buffer, "view %s",
+							 NameStr(relForm->relname));
+			break;
+		default:
+			/* shouldn't get here */
+			appendStringInfo(buffer, "relation %s",
+							 NameStr(relForm->relname));
+			break;
+	}
+
+	ReleaseSysCache(relTup);
+}
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index 48f7cae1aa0e4a87f30be1179c6750cb55e843fb..5c9499c86b5b51cbeb89945f8c9c56951e122f54 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.206 2002/07/14 21:08:08 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.207 2002/07/15 16:33:31 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -75,7 +75,6 @@ static void StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin);
 static void StoreRelCheck(Relation rel, char *ccname, char *ccbin);
 static void StoreConstraints(Relation rel, TupleDesc tupdesc);
 static void SetRelationNumChecks(Relation rel, int numchecks);
-static void RemoveDefaults(Relation rel);
 static void RemoveStatistics(Relation rel);
 
 
@@ -767,18 +766,18 @@ static void
 RelationRemoveInheritance(Relation relation)
 {
 	Relation	catalogRelation;
-	HeapTuple	tuple;
 	SysScanDesc scan;
-	ScanKeyData entry;
+	ScanKeyData key;
+	HeapTuple	tuple;
 
 	catalogRelation = heap_openr(InheritsRelationName, RowExclusiveLock);
 
-	ScanKeyEntryInitialize(&entry, 0x0,
+	ScanKeyEntryInitialize(&key, 0x0,
 						   Anum_pg_inherits_inhrelid, F_OIDEQ,
 						   ObjectIdGetDatum(RelationGetRelid(relation)));
 
 	scan = systable_beginscan(catalogRelation, InheritsRelidSeqnoIndex, true,
-							  SnapshotNow, 1, &entry);
+							  SnapshotNow, 1, &key);
 
 	while (HeapTupleIsValid(tuple = systable_getnext(scan)))
 	{
@@ -859,6 +858,125 @@ DeleteAttributeTuples(Oid relid)
 	heap_close(attrel, RowExclusiveLock);
 }
 
+/*
+ *		RemoveAttrDefault
+ *
+ * If the specified relation/attribute has a default, remove it.
+ * (If no default, raise error if complain is true, else return quietly.)
+ */
+void
+RemoveAttrDefault(Oid relid, AttrNumber attnum,
+				  DropBehavior behavior, bool complain)
+{
+	Relation	attrdef_rel;
+	ScanKeyData scankeys[2];
+	SysScanDesc scan;
+	HeapTuple	tuple;
+	bool		found = false;
+
+	attrdef_rel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
+
+	ScanKeyEntryInitialize(&scankeys[0], 0x0,
+						   Anum_pg_attrdef_adrelid, F_OIDEQ,
+						   ObjectIdGetDatum(relid));
+	ScanKeyEntryInitialize(&scankeys[1], 0x0,
+						   Anum_pg_attrdef_adnum, F_INT2EQ,
+						   Int16GetDatum(attnum));
+
+	scan = systable_beginscan(attrdef_rel, AttrDefaultIndex, true,
+							  SnapshotNow, 2, scankeys);
+
+	/* There should be at most one matching tuple, but we loop anyway */
+	while (HeapTupleIsValid(tuple = systable_getnext(scan)))
+	{
+		ObjectAddress	object;
+
+		object.classId = RelationGetRelid(attrdef_rel);
+		object.objectId = tuple->t_data->t_oid;
+		object.objectSubId = 0;
+
+		performDeletion(&object, behavior);
+
+		found = true;
+	}
+
+	systable_endscan(scan);
+	heap_close(attrdef_rel, RowExclusiveLock);
+
+	if (complain && !found)
+		elog(ERROR, "RemoveAttrDefault: no default found for rel %u attnum %d",
+			 relid, attnum);
+}
+
+/*
+ *		RemoveAttrDefaultById
+ *
+ * Remove a pg_attrdef entry specified by OID.  This is the guts of
+ * attribute-default removal.  Note it should be called via performDeletion,
+ * not directly.
+ */
+void
+RemoveAttrDefaultById(Oid attrdefId)
+{
+	Relation	attrdef_rel;
+	Relation	attr_rel;
+	ScanKeyData scankeys[1];
+	SysScanDesc scan;
+	HeapTuple	tuple;
+	Oid			myrelid;
+	AttrNumber	myattnum;
+
+	/* Grab an appropriate lock on the pg_attrdef relation */
+	attrdef_rel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
+
+	ScanKeyEntryInitialize(&scankeys[0], 0x0,
+						   ObjectIdAttributeNumber, F_OIDEQ,
+						   ObjectIdGetDatum(attrdefId));
+
+	scan = systable_beginscan(attrdef_rel, AttrDefaultOidIndex, true,
+							  SnapshotNow, 1, scankeys);
+
+	tuple = systable_getnext(scan);
+	if (!HeapTupleIsValid(tuple))
+		elog(ERROR, "RemoveAttrDefaultById: cache lookup failed for attrdef %u",
+			 attrdefId);
+
+	myrelid = ((Form_pg_attrdef) GETSTRUCT(tuple))->adrelid;
+	myattnum = ((Form_pg_attrdef) GETSTRUCT(tuple))->adnum;
+
+	simple_heap_delete(attrdef_rel, &tuple->t_self);
+
+	systable_endscan(scan);
+	heap_close(attrdef_rel, RowExclusiveLock);
+
+	/* Fix the pg_attribute row */
+	attr_rel = heap_openr(AttributeRelationName, RowExclusiveLock);
+
+	tuple = SearchSysCacheCopy(ATTNUM,
+							   ObjectIdGetDatum(myrelid),
+							   Int16GetDatum(myattnum),
+							   0, 0);
+	if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
+		elog(ERROR, "RemoveAttrDefaultById: cache lookup failed for rel %u attr %d",
+			 myrelid, myattnum);
+
+	((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = false;
+
+	simple_heap_update(attr_rel, &tuple->t_self, tuple);
+
+	/* keep the system catalog indices current */
+	if (RelationGetForm(attr_rel)->relhasindex)
+	{
+		Relation	idescs[Num_pg_attr_indices];
+
+		CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
+		CatalogIndexInsert(idescs, Num_pg_attr_indices, attr_rel, tuple);
+		CatalogCloseIndices(Num_pg_attr_indices, idescs);
+	}
+
+	heap_close(attr_rel, RowExclusiveLock);
+}
+
 /* ----------------------------------------------------------------
  *		heap_drop_with_catalog	- removes specified relation from catalogs
  *
@@ -866,7 +984,7 @@ DeleteAttributeTuples(Oid relid)
  *		2)	flush relation buffers from bufmgr
  *		3)	remove inheritance information
  *		4)	remove pg_statistic tuples
- *		5)	remove pg_attribute tuples and related items
+ *		5)	remove pg_attribute tuples
  *		6)	remove pg_class tuple
  *		7)	unlink relation file
  *
@@ -908,12 +1026,10 @@ heap_drop_with_catalog(Oid rid)
 	RemoveStatistics(rel);
 
 	/*
-	 * delete attribute tuples and associated defaults
+	 * delete attribute tuples
 	 */
 	DeleteAttributeTuples(RelationGetRelid(rel));
 
-	RemoveDefaults(rel);
-
 	/*
 	 * delete relation tuple
 	 */
@@ -957,6 +1073,9 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin)
 	Relation	attridescs[Num_pg_attr_indices];
 	HeapTuple	atttup;
 	Form_pg_attribute attStruct;
+	Oid			attrdefOid;
+	ObjectAddress	colobject,
+				defobject;
 
 	/*
 	 * Need to construct source equivalent of given node-string.
@@ -971,21 +1090,33 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin)
 											RelationGetRelid(rel)),
 							   false);
 
+	/*
+	 * Make the pg_attrdef entry.
+	 */
 	values[Anum_pg_attrdef_adrelid - 1] = RelationGetRelid(rel);
 	values[Anum_pg_attrdef_adnum - 1] = attnum;
 	values[Anum_pg_attrdef_adbin - 1] = DirectFunctionCall1(textin,
 												 CStringGetDatum(adbin));
 	values[Anum_pg_attrdef_adsrc - 1] = DirectFunctionCall1(textin,
 												 CStringGetDatum(adsrc));
+
 	adrel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
+
 	tuple = heap_formtuple(adrel->rd_att, values, nulls);
-	simple_heap_insert(adrel, tuple);
+	attrdefOid = simple_heap_insert(adrel, tuple);
+
 	CatalogOpenIndices(Num_pg_attrdef_indices, Name_pg_attrdef_indices,
 					   idescs);
 	CatalogIndexInsert(idescs, Num_pg_attrdef_indices, adrel, tuple);
 	CatalogCloseIndices(Num_pg_attrdef_indices, idescs);
+
+	defobject.classId = RelationGetRelid(adrel);
+	defobject.objectId = attrdefOid;
+	defobject.objectSubId = 0;
+
 	heap_close(adrel, RowExclusiveLock);
 
+	/* now can free some of the stuff allocated above */
 	pfree(DatumGetPointer(values[Anum_pg_attrdef_adbin - 1]));
 	pfree(DatumGetPointer(values[Anum_pg_attrdef_adsrc - 1]));
 	heap_freetuple(tuple);
@@ -1016,6 +1147,16 @@ StoreAttrDefault(Relation rel, AttrNumber attnum, char *adbin)
 	}
 	heap_close(attrrel, RowExclusiveLock);
 	heap_freetuple(atttup);
+
+	/*
+	 * Make a dependency so that the pg_attrdef entry goes away if the
+	 * column (or whole table) is deleted.
+	 */
+	colobject.classId = RelOid_pg_class;
+	colobject.objectId = RelationGetRelid(rel);
+	colobject.objectSubId = attnum;
+
+	recordDependencyOn(&defobject, &colobject, DEPENDENCY_AUTO);
 }
 
 /*
@@ -1497,29 +1638,6 @@ cookDefault(ParseState *pstate,
 }
 
 
-static void
-RemoveAttrDefaults(Relation rel)
-{
-	Relation	adrel;
-	HeapScanDesc adscan;
-	ScanKeyData key;
-	HeapTuple	tup;
-
-	adrel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
-
-	ScanKeyEntryInitialize(&key, 0, Anum_pg_attrdef_adrelid,
-						   F_OIDEQ,
-						   ObjectIdGetDatum(RelationGetRelid(rel)));
-
-	adscan = heap_beginscan(adrel, SnapshotNow, 1, &key);
-
-	while ((tup = heap_getnext(adscan, ForwardScanDirection)) != NULL)
-		simple_heap_delete(adrel, &tup->t_self);
-
-	heap_endscan(adscan);
-	heap_close(adrel, RowExclusiveLock);
-}
-
 /*
  * Removes all constraints on a relation that match the given name.
  *
@@ -1577,18 +1695,6 @@ RemoveRelConstraints(Relation rel, const char *constrName,
 	return ndeleted;
 }
 
-static void
-RemoveDefaults(Relation rel)
-{
-	TupleConstr *constr = rel->rd_att->constr;
-
-	/*
-	 * We can skip looking at pg_attrdef if there are no defaults recorded
-	 * in the Relation.
-	 */
-	if (constr && constr->num_defval > 0)
-		RemoveAttrDefaults(rel);
-}
 
 static void
 RemoveStatistics(Relation rel)
diff --git a/src/backend/catalog/indexing.c b/src/backend/catalog/indexing.c
index 9925c39af1e1cac39d7b31d3c4d2e88763129f45..9f16b4d4cc18ea3cd89a2ddb94509c6a0776436d 100644
--- a/src/backend/catalog/indexing.c
+++ b/src/backend/catalog/indexing.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.96 2002/07/12 18:43:14 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/indexing.c,v 1.97 2002/07/15 16:33:31 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -42,13 +42,13 @@ char	   *Name_pg_amproc_indices[Num_pg_amproc_indices] =
 char	   *Name_pg_attr_indices[Num_pg_attr_indices] =
 {AttributeRelidNameIndex, AttributeRelidNumIndex};
 char	   *Name_pg_attrdef_indices[Num_pg_attrdef_indices] =
-{AttrDefaultIndex};
+{AttrDefaultIndex, AttrDefaultOidIndex};
 char	   *Name_pg_class_indices[Num_pg_class_indices] =
 {ClassNameNspIndex, ClassOidIndex};
 char	   *Name_pg_constraint_indices[Num_pg_constraint_indices] =
 {ConstraintNameNspIndex, ConstraintOidIndex, ConstraintRelidIndex};
 char	   *Name_pg_conversion_indices[Num_pg_conversion_indices] =
-{ConversionNameNspIndex, ConversionDefaultIndex};
+{ConversionDefaultIndex, ConversionNameNspIndex, ConversionOidIndex};
 char	   *Name_pg_database_indices[Num_pg_database_indices] =
 {DatabaseNameIndex, DatabaseOidIndex};
 char	   *Name_pg_depend_indices[Num_pg_depend_indices] =
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 0d4d277bae4e6faa10102e912018314b6853d4e1..3722a071082acb6f3975c81e8b7d63f38bf89213 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.20 2002/07/12 18:43:16 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.21 2002/07/15 16:33:31 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -23,7 +23,6 @@
 #include "catalog/index.h"
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
-#include "catalog/pg_attrdef.h"
 #include "catalog/pg_constraint.h"
 #include "catalog/pg_inherits.h"
 #include "catalog/pg_namespace.h"
@@ -57,7 +56,6 @@ static bool change_varattnos_of_a_node(Node *node, const AttrNumber *newattno);
 static void StoreCatalogInheritance(Oid relationId, List *supers);
 static int	findAttrByName(const char *attributeName, List *schema);
 static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass);
-static void drop_default(Oid relid, int16 attnum);
 static void CheckTupleType(Form_pg_class tuple_class);
 static bool needs_toast_table(Relation rel);
 static void validateForeignKeyConstraint(FkConstraint *fkconstraint,
@@ -2080,14 +2078,18 @@ AlterTableAlterColumnDefault(Oid myrelid,
 	attnum = ((Form_pg_attribute) GETSTRUCT(tuple))->attnum;
 	ReleaseSysCache(tuple);
 
+	/*
+	 * Remove any old default for the column.  We use RESTRICT here for
+	 * safety, but at present we do not expect anything to depend on the
+	 * default.
+	 */
+	RemoveAttrDefault(myrelid, attnum, DROP_RESTRICT, false);
+
 	if (newDefault)
 	{
 		/* SET DEFAULT */
 		RawColumnDefault *rawEnt;
 
-		/* Get rid of the old one first */
-		drop_default(myrelid, attnum);
-
 		rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
 		rawEnt->attnum = attnum;
 		rawEnt->raw_default = newDefault;
@@ -2098,73 +2100,10 @@ AlterTableAlterColumnDefault(Oid myrelid,
 		 */
 		AddRelationRawConstraints(rel, makeList1(rawEnt), NIL);
 	}
-	else
-	{
-		/* DROP DEFAULT */
-		Relation	attr_rel;
-
-		/* Fix the pg_attribute row */
-		attr_rel = heap_openr(AttributeRelationName, RowExclusiveLock);
-
-		tuple = SearchSysCacheCopy(ATTNAME,
-								   ObjectIdGetDatum(myrelid),
-								   PointerGetDatum(colName),
-								   0, 0);
-		if (!HeapTupleIsValid(tuple)) /* shouldn't happen */
-			elog(ERROR, "ALTER TABLE: relation \"%s\" has no column \"%s\"",
-				 RelationGetRelationName(rel), colName);
-
-		((Form_pg_attribute) GETSTRUCT(tuple))->atthasdef = FALSE;
-
-		simple_heap_update(attr_rel, &tuple->t_self, tuple);
-
-		/* keep the system catalog indices current */
-		if (RelationGetForm(attr_rel)->relhasindex)
-		{
-			Relation	idescs[Num_pg_attr_indices];
-
-			CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
-			CatalogIndexInsert(idescs, Num_pg_attr_indices, attr_rel, tuple);
-			CatalogCloseIndices(Num_pg_attr_indices, idescs);
-		}
-
-		heap_close(attr_rel, RowExclusiveLock);
-
-		/* get rid of actual default definition in pg_attrdef */
-		drop_default(myrelid, attnum);
-	}
 
 	heap_close(rel, NoLock);
 }
 
-
-static void
-drop_default(Oid relid, int16 attnum)
-{
-	ScanKeyData scankeys[2];
-	HeapScanDesc scan;
-	Relation	attrdef_rel;
-	HeapTuple	tuple;
-
-	attrdef_rel = heap_openr(AttrDefaultRelationName, RowExclusiveLock);
-	ScanKeyEntryInitialize(&scankeys[0], 0x0,
-						   Anum_pg_attrdef_adrelid, F_OIDEQ,
-						   ObjectIdGetDatum(relid));
-	ScanKeyEntryInitialize(&scankeys[1], 0x0,
-						   Anum_pg_attrdef_adnum, F_INT2EQ,
-						   Int16GetDatum(attnum));
-
-	scan = heap_beginscan(attrdef_rel, SnapshotNow, 2, scankeys);
-
-	if ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
-		simple_heap_delete(attrdef_rel, &tuple->t_self);
-
-	heap_endscan(scan);
-
-	heap_close(attrdef_rel, NoLock);
-}
-
-
 /*
  * ALTER TABLE ALTER COLUMN SET STATISTICS / STORAGE
  */
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 9d3acbe35f558ebbf77884997d6af9c5fb69a9e5..5fd581b254870a82320ff205d5b0944d2e526674 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.139 2002/07/12 18:43:19 tgl Exp $
+ * $Id: catversion.h,v 1.140 2002/07/15 16:33:31 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	200207112
+#define CATALOG_VERSION_NO	200207141
 
 #endif
diff --git a/src/include/catalog/heap.h b/src/include/catalog/heap.h
index 44c8e13bf61721aef89ca1a02f1b7eaaa5d3ec0e..3148fd32633c3d3fe7adde956660e161e09e542a 100644
--- a/src/include/catalog/heap.h
+++ b/src/include/catalog/heap.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: heap.h,v 1.53 2002/07/14 21:08:08 tgl Exp $
+ * $Id: heap.h,v 1.54 2002/07/15 16:33:31 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -63,6 +63,9 @@ extern int	RemoveRelConstraints(Relation rel, const char *constrName,
 
 extern void DeleteRelationTuple(Oid relid);
 extern void DeleteAttributeTuples(Oid relid);
+extern void RemoveAttrDefault(Oid relid, AttrNumber attnum,
+							  DropBehavior behavior, bool complain);
+extern void RemoveAttrDefaultById(Oid attrdefId);
 
 extern Form_pg_attribute SystemAttributeDefinition(AttrNumber attno,
 						  bool relhasoids);
diff --git a/src/include/catalog/indexing.h b/src/include/catalog/indexing.h
index d4ca744172b621279ac10331b7ffa37008db20b6..91e35934470387e668f8cf8d4d409db5dee0f367 100644
--- a/src/include/catalog/indexing.h
+++ b/src/include/catalog/indexing.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: indexing.h,v 1.69 2002/07/12 18:43:19 tgl Exp $
+ * $Id: indexing.h,v 1.70 2002/07/15 16:33:31 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -25,10 +25,10 @@
 #define Num_pg_amop_indices			2
 #define Num_pg_amproc_indices		1
 #define Num_pg_attr_indices			2
-#define Num_pg_attrdef_indices		1
+#define Num_pg_attrdef_indices		2
 #define Num_pg_class_indices		2
 #define Num_pg_constraint_indices	3
-#define Num_pg_conversion_indices	2
+#define Num_pg_conversion_indices	3
 #define Num_pg_database_indices		2
 #define Num_pg_depend_indices		2
 #define Num_pg_description_indices	1
@@ -57,6 +57,7 @@
 #define AmNameIndex					"pg_am_name_index"
 #define AmOidIndex					"pg_am_oid_index"
 #define AttrDefaultIndex			"pg_attrdef_adrelid_adnum_index"
+#define AttrDefaultOidIndex			"pg_attrdef_oid_index"
 #define AttributeRelidNameIndex		"pg_attribute_relid_attnam_index"
 #define AttributeRelidNumIndex		"pg_attribute_relid_attnum_index"
 #define ClassNameNspIndex			"pg_class_relname_nsp_index"
@@ -66,6 +67,7 @@
 #define ConstraintRelidIndex		"pg_constraint_conrelid_index"
 #define ConversionDefaultIndex		"pg_conversion_default_index"
 #define ConversionNameNspIndex		"pg_conversion_name_nsp_index"
+#define ConversionOidIndex			"pg_conversion_oid_index"
 #define DatabaseNameIndex			"pg_database_datname_index"
 #define DatabaseOidIndex			"pg_database_oid_index"
 #define DependDependerIndex			"pg_depend_depender_index"
@@ -161,6 +163,7 @@ DECLARE_UNIQUE_INDEX(pg_amop_opc_opr_index on pg_amop using btree(amopclaid oid_
 DECLARE_UNIQUE_INDEX(pg_amop_opc_strategy_index on pg_amop using btree(amopclaid oid_ops, amopstrategy int2_ops));
 DECLARE_UNIQUE_INDEX(pg_amproc_opc_procnum_index on pg_amproc using btree(amopclaid oid_ops, amprocnum int2_ops));
 DECLARE_UNIQUE_INDEX(pg_attrdef_adrelid_adnum_index on pg_attrdef using btree(adrelid oid_ops, adnum int2_ops));
+DECLARE_UNIQUE_INDEX(pg_attrdef_oid_index on pg_attrdef using btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnam_index on pg_attribute using btree(attrelid oid_ops, attname name_ops));
 DECLARE_UNIQUE_INDEX(pg_attribute_relid_attnum_index on pg_attribute using btree(attrelid oid_ops, attnum int2_ops));
 DECLARE_UNIQUE_INDEX(pg_class_oid_index on pg_class using btree(oid oid_ops));
@@ -173,6 +176,7 @@ DECLARE_UNIQUE_INDEX(pg_constraint_oid_index on pg_constraint using btree(oid oi
 /* This following index is not used for a cache and is not unique */
 DECLARE_INDEX(pg_conversion_default_index on pg_conversion using btree(connamespace oid_ops, conforencoding int4_ops, contoencoding int4_ops));
 DECLARE_UNIQUE_INDEX(pg_conversion_name_nsp_index on pg_conversion using btree(conname name_ops, connamespace oid_ops));
+DECLARE_UNIQUE_INDEX(pg_conversion_oid_index on pg_conversion using btree(oid oid_ops));
 DECLARE_UNIQUE_INDEX(pg_database_datname_index on pg_database using btree(datname name_ops));
 DECLARE_UNIQUE_INDEX(pg_database_oid_index on pg_database using btree(oid oid_ops));
 /* This following index is not used for a cache and is not unique */
diff --git a/src/include/catalog/pg_attrdef.h b/src/include/catalog/pg_attrdef.h
index 7df4f324e050f7a6c7a8429e13a06beb167f1e9a..3d39911d83f504dbc1773edbfcef571becb5ece3 100644
--- a/src/include/catalog/pg_attrdef.h
+++ b/src/include/catalog/pg_attrdef.h
@@ -1,11 +1,15 @@
 /*-------------------------------------------------------------------------
  *
  * pg_attrdef.h
+ *	  definition of the system "attribute defaults" relation (pg_attrdef)
+ *	  along with the relation's initial contents.
  *
  *
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
+ * $Id: pg_attrdef.h,v 1.13 2002/07/15 16:33:32 tgl Exp $
+ *
  * NOTES
  *	  the genbki.sh script reads this file and generates .bki
  *	  information from the DATA() statements.
@@ -27,7 +31,7 @@
  *		typedef struct FormData_pg_attrdef
  * ----------------
  */
-CATALOG(pg_attrdef) BKI_WITHOUT_OIDS
+CATALOG(pg_attrdef)
 {
 	Oid			adrelid;
 	int2		adnum;