diff --git a/doc/src/sgml/release.sgml b/doc/src/sgml/release.sgml
index 7fd8c92e371b85bd131d6376f7d9993bb5291694..f215c84b93e0c0c73808f36020b071b6302ba95f 100644
--- a/doc/src/sgml/release.sgml
+++ b/doc/src/sgml/release.sgml
@@ -1,5 +1,5 @@
 <!--
-$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.140 2002/07/12 18:43:12 tgl Exp $
+$Header: /cvsroot/pgsql/doc/src/sgml/release.sgml,v 1.141 2002/07/16 22:12:18 tgl Exp $
 -->
 
 <appendix id="release">
@@ -24,6 +24,7 @@ CDATA means the content is "SGML-free", so you can write without
 worries about funny characters.
 -->
 <literallayout><![CDATA[
+Sequences created by SERIAL column definitions now auto-drop with the column
 Most forms of DROP now support RESTRICT and CASCADE options
 Recursive SQL functions can be defined
 User-defined procedural languages can register a validator function to check new functions as they are created
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index a8700c5efd9f8d8dc4701a1bfc674e105436034a..51933d32ede8891df61e5f1be660bb77a4dd3437 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.208 2002/07/16 05:53:33 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/heap.c,v 1.209 2002/07/16 22:12:18 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', false, false
+	false, 'p', false, 'i', true, false
 };
 
 static FormData_pg_attribute a2 = {
 	0, {"oid"}, OIDOID, 0, sizeof(Oid),
 	ObjectIdAttributeNumber, 0, -1, -1,
-	true, 'p', false, 'i', false, false
+	true, 'p', false, 'i', true, false
 };
 
 static FormData_pg_attribute a3 = {
 	0, {"xmin"}, XIDOID, 0, sizeof(TransactionId),
 	MinTransactionIdAttributeNumber, 0, -1, -1,
-	true, 'p', false, 'i', false, false
+	true, 'p', false, 'i', true, false
 };
 
 static FormData_pg_attribute a4 = {
 	0, {"cmin"}, CIDOID, 0, sizeof(CommandId),
 	MinCommandIdAttributeNumber, 0, -1, -1,
-	true, 'p', false, 'i', false, false
+	true, 'p', false, 'i', true, false
 };
 
 static FormData_pg_attribute a5 = {
 	0, {"xmax"}, XIDOID, 0, sizeof(TransactionId),
 	MaxTransactionIdAttributeNumber, 0, -1, -1,
-	true, 'p', false, 'i', false, false
+	true, 'p', false, 'i', true, false
 };
 
 static FormData_pg_attribute a6 = {
 	0, {"cmax"}, CIDOID, 0, sizeof(CommandId),
 	MaxCommandIdAttributeNumber, 0, -1, -1,
-	true, 'p', false, 'i', false, false
+	true, 'p', false, 'i', true, false
 };
 
 /*
@@ -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', false, false
+	true, 'p', false, 'i', true, false
 };
 
 static Form_pg_attribute SysAtt[] = {&a1, &a2, &a3, &a4, &a5, &a6, &a7};
@@ -416,6 +416,8 @@ AddNewAttributeTuples(Oid new_rel_oid,
 	bool		hasindex;
 	Relation	idescs[Num_pg_attr_indices];
 	int			natts = tupdesc->natts;
+	ObjectAddress	myself,
+					referenced;
 
 	/*
 	 * open pg_attribute
@@ -430,7 +432,8 @@ AddNewAttributeTuples(Oid new_rel_oid,
 		CatalogOpenIndices(Num_pg_attr_indices, Name_pg_attr_indices, idescs);
 
 	/*
-	 * first we add the user attributes..
+	 * First we add the user attributes.  This is also a convenient place
+	 * to add dependencies on their datatypes.
 	 */
 	dpp = tupdesc->attrs;
 	for (i = 0; i < natts; i++)
@@ -451,11 +454,22 @@ AddNewAttributeTuples(Oid new_rel_oid,
 			CatalogIndexInsert(idescs, Num_pg_attr_indices, rel, tup);
 
 		heap_freetuple(tup);
+
+		myself.classId = RelOid_pg_class;
+		myself.objectId = new_rel_oid;
+		myself.objectSubId = i+1;
+		referenced.classId = RelOid_pg_type;
+		referenced.objectId = (*dpp)->atttypid;
+		referenced.objectSubId = 0;
+		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
 		dpp++;
 	}
 
 	/*
-	 * next we add the system attributes.  Skip OID if rel has no OIDs.
+	 * Next we add the system attributes.  Skip OID if rel has no OIDs.
+	 * Skip all for a view.  We don't bother with making datatype
+	 * dependencies here, since presumably all these types are pinned.
 	 */
 	if (relkind != RELKIND_VIEW)
 	{
@@ -493,7 +507,7 @@ AddNewAttributeTuples(Oid new_rel_oid,
 	}
 
 	/*
-	 * close pg_attribute indices
+	 * clean up
 	 */
 	if (hasindex)
 		CatalogCloseIndices(Num_pg_attr_indices, idescs);
diff --git a/src/backend/catalog/pg_aggregate.c b/src/backend/catalog/pg_aggregate.c
index be84bf4acf281d2251b71026355aad91ab50bc49..28d7e83f575e8026e191ec2304fd3ebf678ffb5c 100644
--- a/src/backend/catalog/pg_aggregate.c
+++ b/src/backend/catalog/pg_aggregate.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.49 2002/06/20 20:29:26 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_aggregate.c,v 1.50 2002/07/16 22:12:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,6 +16,7 @@
 
 #include "access/heapam.h"
 #include "catalog/catname.h"
+#include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
 #include "catalog/pg_aggregate.h"
@@ -53,6 +54,8 @@ AggregateCreate(const char *aggName,
 	Oid			procOid;
 	TupleDesc	tupDesc;
 	int			i;
+	ObjectAddress	myself,
+					referenced;
 
 	/* sanity checks */
 	if (!aggName)
@@ -187,4 +190,29 @@ AggregateCreate(const char *aggName,
 	}
 
 	heap_close(aggdesc, RowExclusiveLock);
+
+	/*
+	 * Create dependencies for the aggregate (above and beyond those
+	 * already made by ProcedureCreate).  Note: we don't need an explicit
+	 * dependency on aggTransType since we depend on it indirectly through
+	 * transfn.
+	 */
+	myself.classId = RelOid_pg_proc;
+	myself.objectId = procOid;
+	myself.objectSubId = 0;
+
+	/* Depends on transition function */
+	referenced.classId = RelOid_pg_proc;
+	referenced.objectId = transfn;
+	referenced.objectSubId = 0;
+	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+	/* Depends on final function, if any */
+	if (OidIsValid(finalfn))
+	{
+		referenced.classId = RelOid_pg_proc;
+		referenced.objectId = finalfn;
+		referenced.objectSubId = 0;
+		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	}
 }
diff --git a/src/backend/catalog/pg_constraint.c b/src/backend/catalog/pg_constraint.c
index 41580f2c53fe518a7bbe687d5227484c6dfdf277..96784e73e36f164415ff8a9a49621c17c4622a42 100644
--- a/src/backend/catalog/pg_constraint.c
+++ b/src/backend/catalog/pg_constraint.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_constraint.c,v 1.2 2002/07/16 05:53:33 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_constraint.c,v 1.3 2002/07/16 22:12:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -198,17 +198,11 @@ CreateConstraintEntry(const char *constraintName,
 	if (OidIsValid(foreignRelId))
 	{
 		/*
-		 * Register dependency from constraint to foreign relation,
+		 * Register normal dependency from constraint to foreign relation,
 		 * or to specific column(s) if any are mentioned.
-		 *
-		 * In normal case of two separate relations, make this a NORMAL
-		 * dependency (so dropping the FK table would require CASCADE).
-		 * However, for a self-reference just make it AUTO.
 		 */
-		DependencyType	deptype;
 		ObjectAddress	relobject;
 
-		deptype = (foreignRelId == relId) ? DEPENDENCY_AUTO : DEPENDENCY_NORMAL;
 		relobject.classId = RelOid_pg_class;
 		relobject.objectId = foreignRelId;
 		if (foreignNKeys > 0)
@@ -217,14 +211,14 @@ CreateConstraintEntry(const char *constraintName,
 			{
 				relobject.objectSubId = foreignKey[i];
 
-				recordDependencyOn(&conobject, &relobject, deptype);
+				recordDependencyOn(&conobject, &relobject, DEPENDENCY_NORMAL);
 			}
 		}
 		else
 		{
 			relobject.objectSubId = 0;
 
-			recordDependencyOn(&conobject, &relobject, deptype);
+			recordDependencyOn(&conobject, &relobject, DEPENDENCY_NORMAL);
 		}
 	}
 
diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c
index 75a1ba01c4e44c1c7eaabe02e6f6c15440cd73c6..7319cec682e24bcb8518a188c0d4d2a6d2b48be1 100644
--- a/src/backend/catalog/pg_depend.c
+++ b/src/backend/catalog/pg_depend.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_depend.c,v 1.2 2002/07/16 05:53:33 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_depend.c,v 1.3 2002/07/16 22:12:18 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -121,6 +121,43 @@ recordMultipleDependencies(const ObjectAddress *depender,
 	heap_close(dependDesc, RowExclusiveLock);
 }
 
+/*
+ * deleteDependencyRecordsFor -- delete all records with given depender
+ * classId/objectId.
+ *
+ * This is used when redefining an existing object.  Links leading to the
+ * object do not change, and links leading from it will be recreated
+ * (possibly with some differences from before).
+ */
+void
+deleteDependencyRecordsFor(Oid classId, Oid objectId)
+{
+	Relation		depRel;
+	ScanKeyData		key[2];
+	SysScanDesc		scan;
+	HeapTuple		tup;
+
+	depRel = heap_openr(DependRelationName, RowExclusiveLock);
+
+	ScanKeyEntryInitialize(&key[0], 0x0,
+						   Anum_pg_depend_classid, F_OIDEQ,
+						   ObjectIdGetDatum(classId));
+	ScanKeyEntryInitialize(&key[1], 0x0,
+						   Anum_pg_depend_objid, F_OIDEQ,
+						   ObjectIdGetDatum(objectId));
+
+	scan = systable_beginscan(depRel, DependDependerIndex, true,
+							  SnapshotNow, 2, key);
+
+	while (HeapTupleIsValid(tup = systable_getnext(scan)))
+	{
+		simple_heap_delete(depRel, &tup->t_self);
+	}
+
+	systable_endscan(scan);
+
+	heap_close(depRel, RowExclusiveLock);
+}
 
 /*
  * isObjectPinned()
diff --git a/src/backend/catalog/pg_operator.c b/src/backend/catalog/pg_operator.c
index 95eac6bd4ef113c2d3f9bdc9e11508ec54ef887d..09c3f6be76fb8b653b0e68d1d2f059e4b01de20b 100644
--- a/src/backend/catalog/pg_operator.c
+++ b/src/backend/catalog/pg_operator.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.70 2002/06/20 20:29:26 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_operator.c,v 1.71 2002/07/16 22:12:18 tgl Exp $
  *
  * NOTES
  *	  these routines moved here from commands/define.c and somewhat cleaned up.
@@ -19,6 +19,7 @@
 
 #include "access/heapam.h"
 #include "catalog/catname.h"
+#include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
 #include "catalog/pg_operator.h"
@@ -56,6 +57,8 @@ static Oid get_other_operator(List *otherOp,
 							  Oid leftTypeId, Oid rightTypeId,
 							  bool isCommutator);
 
+static void makeOperatorDependencies(HeapTuple tuple, Oid pg_operator_relid);
+
 
 /*
  * Check whether a proposed operator name is legal
@@ -271,6 +274,9 @@ OperatorShellMake(const char *operatorName,
 		CatalogCloseIndices(Num_pg_operator_indices, idescs);
 	}
 
+	/* Add dependencies for the entry */
+	makeOperatorDependencies(tup, RelationGetRelid(pg_operator_desc));
+
 	heap_freetuple(tup);
 
 	/*
@@ -659,6 +665,9 @@ OperatorCreate(const char *operatorName,
 		CatalogCloseIndices(Num_pg_operator_indices, idescs);
 	}
 
+	/* Add dependencies for the entry */
+	makeOperatorDependencies(tup, RelationGetRelid(pg_operator_desc));
+
 	heap_close(pg_operator_desc, RowExclusiveLock);
 
 	/*
@@ -893,3 +902,89 @@ OperatorUpd(Oid baseId, Oid commId, Oid negId)
 
 	heap_close(pg_operator_desc, RowExclusiveLock);
 }
+
+/*
+ * Create dependencies for a new operator (either a freshly inserted
+ * complete operator, a new shell operator, or a just-updated shell).
+ *
+ * NB: the OidIsValid tests in this routine are *all* necessary, in case
+ * the given operator is a shell.
+ */
+static void
+makeOperatorDependencies(HeapTuple tuple, Oid pg_operator_relid)
+{
+	Form_pg_operator	oper = (Form_pg_operator) GETSTRUCT(tuple);
+	ObjectAddress	myself,
+					referenced;
+
+	myself.classId = pg_operator_relid;
+	myself.objectId = tuple->t_data->t_oid;
+	myself.objectSubId = 0;
+
+	/* In case we are updating a shell, delete any existing entries */
+	deleteDependencyRecordsFor(myself.classId, myself.objectId);
+
+	/* Dependency on left type */
+	if (OidIsValid(oper->oprleft))
+	{
+		referenced.classId = RelOid_pg_type;
+		referenced.objectId = oper->oprleft;
+		referenced.objectSubId = 0;
+		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	}
+
+	/* Dependency on right type */
+	if (OidIsValid(oper->oprright))
+	{
+		referenced.classId = RelOid_pg_type;
+		referenced.objectId = oper->oprright;
+		referenced.objectSubId = 0;
+		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	}
+
+	/* Dependency on result type */
+	if (OidIsValid(oper->oprresult))
+	{
+		referenced.classId = RelOid_pg_type;
+		referenced.objectId = oper->oprresult;
+		referenced.objectSubId = 0;
+		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	}
+
+	/*
+	 * NOTE: we do not consider the operator to depend on the associated
+	 * operators oprcom, oprnegate, oprlsortop, oprrsortop, oprltcmpop,
+	 * oprgtcmpop.  We would not want to delete this operator if those
+	 * go away, but only reset the link fields; which is not a function
+	 * that the dependency code can presently handle.  (Something could
+	 * perhaps be done with objectSubId though.)  For now, it's okay to
+	 * let those links dangle if a referenced operator is removed.
+	 */
+
+	/* Dependency on implementation function */
+	if (OidIsValid(oper->oprcode))
+	{
+		referenced.classId = RelOid_pg_proc;
+		referenced.objectId = oper->oprcode;
+		referenced.objectSubId = 0;
+		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	}
+
+	/* Dependency on restriction selectivity function */
+	if (OidIsValid(oper->oprrest))
+	{
+		referenced.classId = RelOid_pg_proc;
+		referenced.objectId = oper->oprrest;
+		referenced.objectSubId = 0;
+		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	}
+
+	/* Dependency on join selectivity function */
+	if (OidIsValid(oper->oprjoin))
+	{
+		referenced.classId = RelOid_pg_proc;
+		referenced.objectId = oper->oprjoin;
+		referenced.objectSubId = 0;
+		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	}
+}
diff --git a/src/backend/catalog/pg_proc.c b/src/backend/catalog/pg_proc.c
index a7e33270063bdf7b9388c66fd476e6a9ef3f586b..18746d9e2196d058b14c3be0990c1f9ecf9e85d2 100644
--- a/src/backend/catalog/pg_proc.c
+++ b/src/backend/catalog/pg_proc.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.76 2002/06/20 20:29:26 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/catalog/pg_proc.c,v 1.77 2002/07/16 22:12:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -16,6 +16,7 @@
 
 #include "access/heapam.h"
 #include "catalog/catname.h"
+#include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/pg_language.h"
 #include "catalog/pg_proc.h"
@@ -76,6 +77,9 @@ ProcedureCreate(const char *procedureName,
 	NameData	procname;
 	TupleDesc	tupDesc;
 	Oid			retval;
+	bool		is_update;
+	ObjectAddress	myself,
+					referenced;
 
 	/*
 	 * sanity checks
@@ -227,6 +231,7 @@ ProcedureCreate(const char *procedureName,
 		simple_heap_update(rel, &tup->t_self, tup);
 
 		ReleaseSysCache(oldtup);
+		is_update = true;
 	}
 	else
 	{
@@ -237,6 +242,7 @@ ProcedureCreate(const char *procedureName,
 
 		tup = heap_formtuple(tupDesc, values, nulls);
 		simple_heap_insert(rel, tup);
+		is_update = false;
 	}
 
 	/* Need to update indices for either the insert or update case */
@@ -250,6 +256,45 @@ ProcedureCreate(const char *procedureName,
 	}
 
 	retval = tup->t_data->t_oid;
+
+	/*
+	 * Create dependencies for the new function.  If we are updating an
+	 * existing function, first delete any existing pg_depend entries.
+	 */
+	if (is_update)
+		deleteDependencyRecordsFor(RelOid_pg_proc, retval);
+
+	myself.classId = RelOid_pg_proc;
+	myself.objectId = retval;
+	myself.objectSubId = 0;
+
+	/* dependency on implementation language */
+	referenced.classId = get_system_catalog_relid(LanguageRelationName);
+	referenced.objectId = languageObjectId;
+	referenced.objectSubId = 0;
+	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+	/* dependency on return type */
+	if (OidIsValid(returnType))
+	{
+		referenced.classId = RelOid_pg_type;
+		referenced.objectId = returnType;
+		referenced.objectSubId = 0;
+		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	}
+
+	/* dependency on input types */
+	for (i = 0; i < parameterCount; i++)
+	{
+		if (OidIsValid(typev[i]))
+		{
+			referenced.classId = RelOid_pg_type;
+			referenced.objectId = typev[i];
+			referenced.objectSubId = 0;
+			recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+		}
+	}
+
 	heap_freetuple(tup);
 
 	heap_close(rel, RowExclusiveLock);
diff --git a/src/backend/commands/proclang.c b/src/backend/commands/proclang.c
index 56dc320e2ef4416db7fce6b742ee2365c8b9de38..98b613242625b11126c5d8a4208cd0132651edab 100644
--- a/src/backend/commands/proclang.c
+++ b/src/backend/commands/proclang.c
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.35 2002/07/12 18:43:16 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/proclang.c,v 1.36 2002/07/16 22:12:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -49,6 +49,8 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 	HeapTuple	tup;
 	TupleDesc	tupDesc;
 	int			i;
+	ObjectAddress	myself,
+					referenced;
 
 	/*
 	 * Check permission
@@ -91,7 +93,7 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 				 NameListToString(stmt->plvalidator));
 	}
 	else
-		valProcOid = 0;
+		valProcOid = InvalidOid;
 
 	/*
 	 * Insert the new language into pg_language
@@ -128,6 +130,28 @@ CreateProceduralLanguage(CreatePLangStmt *stmt)
 		CatalogCloseIndices(Num_pg_language_indices, idescs);
 	}
 
+	/*
+	 * Create dependencies for language
+	 */
+	myself.classId = RelationGetRelid(rel);
+	myself.objectId = tup->t_data->t_oid;
+	myself.objectSubId = 0;
+
+	/* dependency on the PL handler function */
+	referenced.classId = RelOid_pg_proc;
+	referenced.objectId = procOid;
+	referenced.objectSubId = 0;
+	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+	/* dependency on the validator function, if any */
+	if (OidIsValid(valProcOid))
+	{
+		referenced.classId = RelOid_pg_proc;
+		referenced.objectId = valProcOid;
+		referenced.objectSubId = 0;
+		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	}
+
 	heap_close(rel, RowExclusiveLock);
 }
 
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 1d013612da43a6d6225bddd94c580c68b1ab0e64..f8a05b619de484897ddb9e88cec4e34b8ef0627d 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.82 2002/06/20 20:29:27 momjian Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/sequence.c,v 1.83 2002/07/16 22:12:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -124,11 +124,15 @@ DefineSequence(CreateSeqStmt *seq)
 		typnam->setof = FALSE;
 		typnam->arrayBounds = NIL;
 		typnam->typmod = -1;
+
 		coldef = makeNode(ColumnDef);
 		coldef->typename = typnam;
+		coldef->is_not_null = true;
 		coldef->raw_default = NULL;
 		coldef->cooked_default = NULL;
-		coldef->is_not_null = false;
+		coldef->constraints = NIL;
+		coldef->support = NULL;
+
 		null[i - 1] = ' ';
 
 		switch (i)
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 099c6351b7f5f4c5e6688aa14d9d1d057f3e2f1e..391adb042254ab7962ead36f1d25ee1f50353fc6 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.22 2002/07/16 05:53:33 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/tablecmds.c,v 1.23 2002/07/16 22:12:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -239,6 +239,10 @@ DefineRelation(CreateStmt *stmt, char relkind)
 	 * So, the transformation has to be postponed to this final step of
 	 * CREATE TABLE.
 	 *
+	 * Another task that's conveniently done at this step is to add
+	 * dependency links between columns and supporting relations (such
+	 * as SERIAL sequences).
+	 *
 	 * First, scan schema to find new column defaults.
 	 */
 	rawDefaults = NIL;
@@ -247,18 +251,35 @@ DefineRelation(CreateStmt *stmt, char relkind)
 	foreach(listptr, schema)
 	{
 		ColumnDef  *colDef = lfirst(listptr);
-		RawColumnDefault *rawEnt;
 
 		attnum++;
 
-		if (colDef->raw_default == NULL)
-			continue;
-		Assert(colDef->cooked_default == NULL);
+		if (colDef->raw_default != NULL)
+		{
+			RawColumnDefault *rawEnt;
 
-		rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
-		rawEnt->attnum = attnum;
-		rawEnt->raw_default = colDef->raw_default;
-		rawDefaults = lappend(rawDefaults, rawEnt);
+			Assert(colDef->cooked_default == NULL);
+
+			rawEnt = (RawColumnDefault *) palloc(sizeof(RawColumnDefault));
+			rawEnt->attnum = attnum;
+			rawEnt->raw_default = colDef->raw_default;
+			rawDefaults = lappend(rawDefaults, rawEnt);
+		}
+
+		if (colDef->support != NULL)
+		{
+			/* Create dependency for supporting relation for this column */
+			ObjectAddress	colobject,
+						suppobject;
+
+			colobject.classId = RelOid_pg_class;
+			colobject.objectId = relationId;
+			colobject.objectSubId = attnum;
+			suppobject.classId = RelOid_pg_class;
+			suppobject.objectId = RangeVarGetRelid(colDef->support, false);
+			suppobject.objectSubId = 0;
+			recordDependencyOn(&suppobject, &colobject, DEPENDENCY_INTERNAL);
+		}
 	}
 
 	/*
@@ -533,6 +554,7 @@ MergeAttributes(List *schema, List *supers, bool istemp,
 				def->raw_default = NULL;
 				def->cooked_default = NULL;
 				def->constraints = NIL;
+				def->support = NULL;
 				inhSchema = lappend(inhSchema, def);
 				newattno[parent_attno - 1] = ++child_attno;
 			}
@@ -1524,6 +1546,8 @@ AlterTableAddColumn(Oid myrelid,
 	HeapTuple	typeTuple;
 	Form_pg_type tform;
 	int			attndims;
+	ObjectAddress	myself,
+					referenced;
 
 	/*
 	 * Grab an exclusive lock on the target table, which we will NOT
@@ -1697,6 +1721,17 @@ AlterTableAddColumn(Oid myrelid,
 
 	heap_close(rel, NoLock);	/* close rel but keep lock! */
 
+	/*
+	 * Add datatype dependency for the new column.
+	 */
+	myself.classId = RelOid_pg_class;
+	myself.objectId = myrelid;
+	myself.objectSubId = i;
+	referenced.classId = RelOid_pg_type;
+	referenced.objectId = attribute->atttypid;
+	referenced.objectSubId = 0;
+	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
 	/*
 	 * Make our catalog updates visible for subsequent steps.
 	 */
diff --git a/src/backend/commands/typecmds.c b/src/backend/commands/typecmds.c
index f148ff658918db7401d530d87d1f4cc65f492d0e..c94b67883be030428ae32e91a543395b43dc5aa2 100644
--- a/src/backend/commands/typecmds.c
+++ b/src/backend/commands/typecmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.5 2002/07/12 18:43:16 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/commands/typecmds.c,v 1.6 2002/07/16 22:12:19 tgl Exp $
  *
  * DESCRIPTION
  *	  The "DefineFoo" routines take the parse tree and pick out the
@@ -358,15 +358,18 @@ DefineDomain(CreateDomainStmt *stmt)
 	char		typtype;
 	Datum		datum;
 	bool		isnull;
+	Node	   *defaultExpr = NULL;
 	char	   *defaultValue = NULL;
 	char	   *defaultValueBin = NULL;
 	bool		typNotNull = false;
+	bool		nullDefined = false;
 	Oid			basetypelem;
 	int32		typNDims = length(stmt->typename->arrayBounds);
 	HeapTuple	typeTup;
 	List	   *schema = stmt->constraints;
 	List	   *listptr;
 	Oid			basetypeoid;
+	Oid			domainoid;
 	Form_pg_type	baseType;
 
 	/* Convert list of names to a name and namespace */
@@ -459,8 +462,6 @@ DefineDomain(CreateDomainStmt *stmt)
 	foreach(listptr, schema)
 	{
 		Constraint *colDef = lfirst(listptr);
-		bool nullDefined = false;
-		Node	   *expr;
 		ParseState *pstate;
 
 		switch (colDef->contype)
@@ -473,47 +474,45 @@ DefineDomain(CreateDomainStmt *stmt)
 			 * don't want to cook or fiddle too much.
 			 */
 			case CONSTR_DEFAULT:
+				if (defaultExpr)
+					elog(ERROR, "CREATE DOMAIN has multiple DEFAULT expressions");
 				/* Create a dummy ParseState for transformExpr */
 				pstate = make_parsestate(NULL);
 				/*
 				 * Cook the colDef->raw_expr into an expression.
 				 * Note: Name is strictly for error message
 				 */
-				expr = cookDefault(pstate, colDef->raw_expr,
-								   basetypeoid,
-								   stmt->typename->typmod,
-								   domainName);
+				defaultExpr = cookDefault(pstate, colDef->raw_expr,
+										  basetypeoid,
+										  stmt->typename->typmod,
+										  domainName);
 				/*
 				 * Expression must be stored as a nodeToString result,
 				 * but we also require a valid textual representation
 				 * (mainly to make life easier for pg_dump).
 				 */
-				defaultValue = deparse_expression(expr,
+				defaultValue = deparse_expression(defaultExpr,
 								deparse_context_for(domainName,
 													InvalidOid),
 												   false);
-				defaultValueBin = nodeToString(expr);
+				defaultValueBin = nodeToString(defaultExpr);
 				break;
 
 			/*
 			 * Find the NULL constraint.
 			 */
 			case CONSTR_NOTNULL:
-				if (nullDefined) {
+				if (nullDefined)
 					elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint");
-				} else {
-					typNotNull = true;
-					nullDefined = true;
-				}
+				typNotNull = true;
+				nullDefined = true;
 		  		break;
 
 			case CONSTR_NULL:
-				if (nullDefined) {
+				if (nullDefined)
 					elog(ERROR, "CREATE DOMAIN has conflicting NULL / NOT NULL constraint");
-				} else {
-					typNotNull = false;
-					nullDefined = true;
-				}
+				typNotNull = false;
+				nullDefined = true;
 		  		break;
 
 		  	case CONSTR_UNIQUE:
@@ -544,28 +543,44 @@ DefineDomain(CreateDomainStmt *stmt)
 	/*
 	 * Have TypeCreate do all the real work.
 	 */
-	TypeCreate(domainName,			/* type name */
-			   domainNamespace,		/* namespace */
-			   InvalidOid,			/* preassigned type oid (none here) */
-			   InvalidOid,			/* relation oid (n/a here) */
-			   internalLength,		/* internal size */
-			   externalLength,		/* external size */
-			   'd',					/* type-type (domain type) */
-			   delimiter,			/* array element delimiter */
-			   inputProcedure,		/* input procedure */
-			   outputProcedure,		/* output procedure */
-			   receiveProcedure,	/* receive procedure */
-			   sendProcedure,		/* send procedure */
-			   basetypelem,			/* element type ID */
-			   basetypeoid,			/* base type ID */
-			   defaultValue,		/* default type value (text) */
-			   defaultValueBin,		/* default type value (binary) */
-			   byValue,				/* passed by value */
-			   alignment,			/* required alignment */
-			   storage,				/* TOAST strategy */
-			   stmt->typename->typmod, /* typeMod value */
-			   typNDims,			/* Array dimensions for base type */
-			   typNotNull);			/* Type NOT NULL */
+	domainoid =
+		TypeCreate(domainName,			/* type name */
+				   domainNamespace,		/* namespace */
+				   InvalidOid,			/* preassigned type oid (none here) */
+				   InvalidOid,			/* relation oid (n/a here) */
+				   internalLength,		/* internal size */
+				   externalLength,		/* external size */
+				   'd',					/* type-type (domain type) */
+				   delimiter,			/* array element delimiter */
+				   inputProcedure,		/* input procedure */
+				   outputProcedure,		/* output procedure */
+				   receiveProcedure,	/* receive procedure */
+				   sendProcedure,		/* send procedure */
+				   basetypelem,			/* element type ID */
+				   basetypeoid,			/* base type ID */
+				   defaultValue,		/* default type value (text) */
+				   defaultValueBin,		/* default type value (binary) */
+				   byValue,				/* passed by value */
+				   alignment,			/* required alignment */
+				   storage,				/* TOAST strategy */
+				   stmt->typename->typmod, /* typeMod value */
+				   typNDims,			/* Array dimensions for base type */
+				   typNotNull);			/* Type NOT NULL */
+
+	/*
+	 * Add any dependencies needed for the default expression.
+	 */
+	if (defaultExpr)
+	{
+		ObjectAddress	domobject;
+
+		domobject.classId = RelOid_pg_type;
+		domobject.objectId = domainoid;
+		domobject.objectSubId = 0;
+
+		recordDependencyOnExpr(&domobject, defaultExpr, NIL,
+							   DEPENDENCY_NORMAL);
+	}
 
 	/*
 	 * Now we can clean up.
diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c
index 519df157184960b1192f06be935e5db9e0393ae9..faaff48fa053fc7a0fe7ad4d707e04798b90ff98 100644
--- a/src/backend/commands/view.c
+++ b/src/backend/commands/view.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2002, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *	$Id: view.c,v 1.66 2002/07/12 18:43:16 tgl Exp $
+ *	$Id: view.c,v 1.67 2002/07/16 22:12:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -72,6 +72,7 @@ DefineVirtualRelation(const RangeVar *relation, List *tlist)
 			def->raw_default = NULL;
 			def->cooked_default = NULL;
 			def->constraints = NIL;
+			def->support = NULL;
 
 			attrList = lappend(attrList, def);
 		}
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index 4e568a3c531ba5daa9bbb13a6b55d631dfe51dd4..426180dc1111d04bbb7ece656b9bc9530d70a99d 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.193 2002/07/12 18:43:16 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/copyfuncs.c,v 1.194 2002/07/16 22:12:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1749,6 +1749,7 @@ _copyColumnDef(ColumnDef *from)
 	if (from->cooked_default)
 		newnode->cooked_default = pstrdup(from->cooked_default);
 	Node_Copy(from, newnode, constraints);
+	Node_Copy(from, newnode, support);
 
 	return newnode;
 }
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index e15870b2c800b4f4fc4534317e51a59136a4e0bb..ed5d638f0cb6b522af8e508b205512eada815ad0 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.140 2002/07/12 18:43:16 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/nodes/equalfuncs.c,v 1.141 2002/07/16 22:12:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1636,6 +1636,8 @@ _equalColumnDef(ColumnDef *a, ColumnDef *b)
 		return false;
 	if (!equal(a->constraints, b->constraints))
 		return false;
+	if (!equal(a->support, b->support))
+		return false;
 
 	return true;
 }
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index ae3139a6ea65e06f396b25ff5958b90a3b25bd5d..a9e6a8382d52807312b9b283be22ceb9254fb7af 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.162 2002/07/12 18:43:16 tgl Exp $
+ *	$Header: /cvsroot/pgsql/src/backend/nodes/outfuncs.c,v 1.163 2002/07/16 22:12:19 tgl Exp $
  *
  * NOTES
  *	  Every (plan) node in POSTGRES has an associated "out" routine which
@@ -183,6 +183,8 @@ _outColumnDef(StringInfo str, ColumnDef *node)
 	_outToken(str, node->cooked_default);
 	appendStringInfo(str, " :constraints ");
 	_outNode(str, node->constraints);
+	appendStringInfo(str, " :support ");
+	_outNode(str, node->support);
 }
 
 static void
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 2fbca505987b7b84e164d526cdb9dd717cb14e0b..6337b61f2acda5ddb1f3e5c54328cc14302e0f8d 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -6,7 +6,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/parser/analyze.c,v 1.238 2002/07/12 18:43:17 tgl Exp $
+ *	$Header: /cvsroot/pgsql/src/backend/parser/analyze.c,v 1.239 2002/07/16 22:12:19 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -847,6 +847,12 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
 
 		cxt->blist = lappend(cxt->blist, seqstmt);
 
+		/*
+		 * Mark the ColumnDef so that during execution, an appropriate
+		 * dependency will be added from the sequence to the column.
+		 */
+		column->support = makeRangeVar(snamespace, sname);
+
 		/*
 		 * Create appropriate constraints for SERIAL.  We do this in full,
 		 * rather than shortcutting, so that we will detect any
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index ef83d92a6d39b0cdd366e586eeab2bce58a48f77..9b8e52620a6879750b231741b33472eb8d3b6806 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.340 2002/07/14 23:38:13 tgl Exp $
+ *	  $Header: /cvsroot/pgsql/src/backend/parser/gram.y,v 2.341 2002/07/16 22:12:20 tgl Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -1852,10 +1852,11 @@ CreateAsElement:
 					ColumnDef *n = makeNode(ColumnDef);
 					n->colname = $1;
 					n->typename = NULL;
+					n->is_not_null = false;
 					n->raw_default = NULL;
 					n->cooked_default = NULL;
-					n->is_not_null = FALSE;
-					n->constraints = NULL;
+					n->constraints = NIL;
+					n->support = NULL;
 					$$ = (Node *)n;
 				}
 		;
diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h
index bcadaee732f2ab125b9bc1b3efbcfc5388a41ef8..b2780071ff30d345642e4c8b810d71114c77553f 100644
--- a/src/include/catalog/dependency.h
+++ b/src/include/catalog/dependency.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: dependency.h,v 1.2 2002/07/16 05:53:34 tgl Exp $
+ * $Id: dependency.h,v 1.3 2002/07/16 22:12:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -98,4 +98,6 @@ extern void recordMultipleDependencies(const ObjectAddress *depender,
 									   int nreferenced,
 									   DependencyType behavior);
 
+extern void deleteDependencyRecordsFor(Oid classId, Oid objectId);
+
 #endif   /* DEPENDENCY_H */
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index f0542990f2e5d1f9cc0e2c8777ec96f54dc5d31c..c0933f8ae7ffbbb8c5a7abfcafadf41752586a07 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.186 2002/07/14 23:38:13 tgl Exp $
+ * $Id: parsenodes.h,v 1.187 2002/07/16 22:12:20 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -269,6 +269,10 @@ typedef struct BooleanTest
  * parsetree produced by gram.y, but transformCreateStmt will remove
  * the item and set raw_default instead.  CONSTR_DEFAULT items
  * should not appear in any subsequent processing.
+ *
+ * The "support" field, if not null, denotes a supporting relation that
+ * should be linked by an internal dependency to the column.  Currently
+ * this is only used to link a SERIAL column's sequence to the column.
  */
 typedef struct ColumnDef
 {
@@ -280,6 +284,7 @@ typedef struct ColumnDef
 								 * tree) */
 	char	   *cooked_default; /* nodeToString representation */
 	List	   *constraints;	/* other constraints on column */
+	RangeVar   *support;		/* supporting relation, if any */
 } ColumnDef;
 
 /*