diff --git a/doc/src/sgml/datatype.sgml b/doc/src/sgml/datatype.sgml
index 35e71004c182d79921bf1b460504dac04db699b4..c5ba6c4d97335ed9b8fe7832b6f3c0ead3edf160 100644
--- a/doc/src/sgml/datatype.sgml
+++ b/doc/src/sgml/datatype.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/datatype.sgml,v 1.169 2006/07/06 01:46:37 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/datatype.sgml,v 1.170 2006/08/21 00:57:23 tgl Exp $ -->
 
  <chapter id="datatype">
   <title id="datatype-title">Data Types</title>
@@ -705,17 +705,19 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (
 <programlisting>
 CREATE SEQUENCE <replaceable class="parameter">tablename</replaceable>_<replaceable class="parameter">colname</replaceable>_seq;
 CREATE TABLE <replaceable class="parameter">tablename</replaceable> (
-    <replaceable class="parameter">colname</replaceable> integer DEFAULT nextval('<replaceable class="parameter">tablename</replaceable>_<replaceable class="parameter">colname</replaceable>_seq') NOT NULL
+    <replaceable class="parameter">colname</replaceable> integer NOT NULL DEFAULT nextval('<replaceable class="parameter">tablename</replaceable>_<replaceable class="parameter">colname</replaceable>_seq')
 );
+ALTER SEQUENCE <replaceable class="parameter">tablename</replaceable>_<replaceable class="parameter">colname</replaceable>_seq OWNED BY <replaceable class="parameter">tablename</replaceable>.<replaceable class="parameter">colname</replaceable>;
 </programlisting>
 
      Thus, we have created an integer column and arranged for its default
      values to be assigned from a sequence generator.  A <literal>NOT NULL</>
      constraint is applied to ensure that a null value cannot be explicitly
-     inserted, either.  In most cases you would also want to attach a
+     inserted, either.  (In most cases you would also want to attach a
      <literal>UNIQUE</> or <literal>PRIMARY KEY</> constraint to prevent
      duplicate values from being inserted by accident, but this is
-     not automatic.
+     not automatic.)  Lastly, the sequence is marked as <quote>owned by</>
+     the column, so that it will be dropped if the column or table is dropped.
     </para>
 
     <note>
@@ -749,20 +751,9 @@ CREATE TABLE <replaceable class="parameter">tablename</replaceable> (
 
     <para>
      The sequence created for a <type>serial</type> column is
-     automatically dropped when the owning column is dropped, and
-     cannot be dropped otherwise.  (This was not true in
-     <productname>PostgreSQL</productname> releases before 7.3.  Note
-     that this automatic drop linkage will not occur for a sequence
-     created by reloading a dump from a pre-7.3 database; the dump
-     file does not contain the information needed to establish the
-     dependency link.) Furthermore, this dependency between sequence
-     and column is made only for the <type>serial</> column itself. If
-     any other columns reference the sequence (perhaps by manually
-     calling the <function>nextval</> function), they will be broken
-     if the sequence is removed. Using a <type>serial</> column's sequence
-     in such a fashion is considered bad form; if you wish to feed several
-     columns from the same sequence generator, create the sequence as an
-     independent object.
+     automatically dropped when the owning column is dropped.
+     You can drop the sequence without dropping the column, but this
+     will force removal of the column default expression.
     </para>
    </sect2>
   </sect1>
diff --git a/doc/src/sgml/func.sgml b/doc/src/sgml/func.sgml
index 113411f78b542ffaea63104975f7778ee550e199..2b2a0a0d18c8c992f0ecb40f8455523d0ec241ed 100644
--- a/doc/src/sgml/func.sgml
+++ b/doc/src/sgml/func.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.330 2006/08/17 23:04:03 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.331 2006/08/21 00:57:23 tgl Exp $ -->
 
  <chapter id="functions">
   <title>Functions and Operators</title>
@@ -9863,10 +9863,14 @@ SELECT pg_type_is_visible('myschema.widget'::regtype);
 
   <para>
    <function>pg_get_serial_sequence</function> fetches the name of the
-   sequence associated with a <type>serial</> or <type>bigserial</>
-   column.  The name is suitably formatted for passing to the sequence
-   functions (see <xref linkend="functions-sequence">).  NULL is
-   returned if the column does not have an associated sequence.
+   sequence associated with a column, or NULL if there is no sequence
+   associated with the column.  The result is suitably formatted for passing
+   to the sequence functions (see <xref linkend="functions-sequence">).
+   This association can be modified or removed with <command>ALTER SEQUENCE
+   OWNED BY</>.  (The function probably should have been called
+   <function>pg_get_owned_sequence</function>; its name reflects the fact
+   that it's typically used with <type>serial</> or <type>bigserial</>
+   columns.)
   </para>
 
   <para>
diff --git a/doc/src/sgml/ref/alter_sequence.sgml b/doc/src/sgml/ref/alter_sequence.sgml
index 3e7937e185b556a1eee8865bf1ee9c09b763882f..3d6d5caf8f68604dc4c0d361c094257554c56275 100644
--- a/doc/src/sgml/ref/alter_sequence.sgml
+++ b/doc/src/sgml/ref/alter_sequence.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/alter_sequence.sgml,v 1.13 2005/11/01 21:09:50 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/alter_sequence.sgml,v 1.14 2006/08/21 00:57:24 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -27,6 +27,7 @@ PostgreSQL documentation
 ALTER SEQUENCE <replaceable class="parameter">name</replaceable> [ INCREMENT [ BY ] <replaceable class="parameter">increment</replaceable> ]
     [ MINVALUE <replaceable class="parameter">minvalue</replaceable> | NO MINVALUE ] [ MAXVALUE <replaceable class="parameter">maxvalue</replaceable> | NO MAXVALUE ]
     [ RESTART [ WITH ] <replaceable class="parameter">start</replaceable> ] [ CACHE <replaceable class="parameter">cache</replaceable> ] [ [ NO ] CYCLE ]
+    [ OWNED BY { <replaceable class="parameter">table</replaceable>.<replaceable class="parameter">column</replaceable> | NONE } ]
 ALTER SEQUENCE <replaceable class="parameter">name</replaceable> SET SCHEMA <replaceable class="parameter">new_schema</replaceable>
   </synopsis>
  </refsynopsisdiv>
@@ -163,6 +164,24 @@ ALTER SEQUENCE <replaceable class="parameter">name</replaceable> SET SCHEMA <rep
       </listitem>
      </varlistentry>
 
+   <varlistentry>
+    <term><literal>OWNED BY</literal> <replaceable class="parameter">table</replaceable>.<replaceable class="parameter">column</replaceable></term>
+    <term><literal>OWNED BY NONE</literal></term>
+    <listitem>
+     <para>
+      The <literal>OWNED BY</literal> option causes the sequence to be
+      associated with a specific table column, such that if that column
+      (or its whole table) is dropped, the sequence will be automatically
+      dropped as well.  If specified, this association replaces any
+      previously specified association for the sequence.  The specified
+      table must have the same owner and be in the same schema as the
+      sequence.
+      Specifying <literal>OWNED BY NONE</literal> removes any existing
+      association, making the sequence <quote>free-standing</>.
+     </para>
+    </listitem>
+   </varlistentry>
+
      <varlistentry>
       <term><replaceable class="parameter">new_schema</replaceable></term>
       <listitem>
@@ -191,8 +210,11 @@ ALTER SEQUENCE serial RESTART WITH 105;
 
   <para>
    To avoid blocking of concurrent transactions that obtain numbers from the
-   same sequence, <command>ALTER SEQUENCE</command> is never rolled back;
-   the changes take effect immediately and are not reversible.
+   same sequence, <command>ALTER SEQUENCE</command>'s effects on the sequence
+   generation parameters are never rolled back;
+   those changes take effect immediately and are not reversible.  However,
+   the <literal>OWNED BY</> and <literal>SET SCHEMA</> clauses are ordinary
+   catalog updates and can be rolled back.
   </para>
 
   <para>
@@ -200,7 +222,8 @@ ALTER SEQUENCE serial RESTART WITH 105;
    <function>nextval</> results in backends,
    other than the current one, that have preallocated (cached) sequence
    values. They will use up all cached values prior to noticing the changed
-   sequence parameters.  The current backend will be affected immediately.
+   sequence generation parameters.  The current backend will be affected
+   immediately.
   </para>
 
   <para>
@@ -217,10 +240,20 @@ ALTER SEQUENCE serial RESTART WITH 105;
   <para>
    <command>ALTER SEQUENCE</command> conforms to the <acronym>SQL</acronym>
    standard,
-   except for the <literal>SET SCHEMA</literal> variant, which is a
-   <productname>PostgreSQL</productname> extension.
+   except for the <literal>OWNED BY</> and <literal>SET SCHEMA</literal>
+   clauses, which are <productname>PostgreSQL</productname> extensions.
   </para>
  </refsect1>
+
+ <refsect1>
+  <title>See Also</title>
+
+  <simplelist type="inline">
+   <member><xref linkend="sql-createsequence" endterm="sql-createsequence-title"></member>
+   <member><xref linkend="sql-dropsequence" endterm="sql-dropsequence-title"></member>
+  </simplelist>
+ </refsect1>
+
 </refentry>
 
 <!-- Keep this comment at the end of the file
diff --git a/doc/src/sgml/ref/alter_table.sgml b/doc/src/sgml/ref/alter_table.sgml
index 17b0f3667dabaa1df5c6142bb36dc7f1b483373d..d7c31064a0638ef7a57f14a80fdcc9c48049e28c 100644
--- a/doc/src/sgml/ref/alter_table.sgml
+++ b/doc/src/sgml/ref/alter_table.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/alter_table.sgml,v 1.88 2006/08/03 20:57:06 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/alter_table.sgml,v 1.89 2006/08/21 00:57:24 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -371,7 +371,7 @@ where <replaceable class="PARAMETER">action</replaceable> is one of:
     <listitem>
      <para>
       This form moves the table into another schema.  Associated indexes,
-      constraints, and SERIAL-column sequences are moved as well.
+      constraints, and sequences owned by table columns are moved as well.
      </para>
     </listitem>
    </varlistentry>
diff --git a/doc/src/sgml/ref/create_sequence.sgml b/doc/src/sgml/ref/create_sequence.sgml
index 7a094f6ef23e7baaa4f99fd01e6f28c7dcc12b53..5fa16c2a81cf14263af2a14ba773b1cb46f1346c 100644
--- a/doc/src/sgml/ref/create_sequence.sgml
+++ b/doc/src/sgml/ref/create_sequence.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/create_sequence.sgml,v 1.43 2005/11/01 21:09:50 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/create_sequence.sgml,v 1.44 2006/08/21 00:57:24 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -23,6 +23,7 @@ PostgreSQL documentation
 CREATE [ TEMPORARY | TEMP ] SEQUENCE <replaceable class="parameter">name</replaceable> [ INCREMENT [ BY ] <replaceable class="parameter">increment</replaceable> ]
     [ MINVALUE <replaceable class="parameter">minvalue</replaceable> | NO MINVALUE ] [ MAXVALUE <replaceable class="parameter">maxvalue</replaceable> | NO MAXVALUE ]
     [ START [ WITH ] <replaceable class="parameter">start</replaceable> ] [ CACHE <replaceable class="parameter">cache</replaceable> ] [ [ NO ] CYCLE ]
+    [ OWNED BY { <replaceable class="parameter">table</replaceable>.<replaceable class="parameter">column</replaceable> | NONE } ]
 </synopsis>
  </refsynopsisdiv>
 
@@ -193,6 +194,22 @@ SELECT * FROM <replaceable>name</replaceable>;
      </para>
     </listitem>
    </varlistentry>
+
+   <varlistentry>
+    <term><literal>OWNED BY</literal> <replaceable class="parameter">table</replaceable>.<replaceable class="parameter">column</replaceable></term>
+    <term><literal>OWNED BY NONE</literal></term>
+    <listitem>
+     <para>
+      The <literal>OWNED BY</literal> option causes the sequence to be
+      associated with a specific table column, such that if that column
+      (or its whole table) is dropped, the sequence will be automatically
+      dropped as well.  The specified table must have the same owner and be in
+      the same schema as the sequence.
+      <literal>OWNED BY NONE</literal>, the default, specifies that there
+      is no such association.
+     </para>
+    </listitem>
+   </varlistentry>
   </variablelist>
  </refsect1>
 
@@ -300,11 +317,38 @@ END;
    <command>CREATE SEQUENCE</command> conforms to the <acronym>SQL</acronym>
    standard, with the following exceptions:
    <itemizedlist>
-    <listitem><para>The standard's <literal>AS &lt;data type&gt;</literal> expression is not supported.</para></listitem>
-    <listitem><para>Obtaining the next value is done using the <function>nextval()</> function instead of the standard's <command>NEXT VALUE FOR</command> expression.</para></listitem>
+    <listitem>
+     <para>
+      The standard's <literal>AS &lt;data type&gt;</literal> expression is not
+      supported.
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      Obtaining the next value is done using the <function>nextval()</>
+      function instead of the standard's <command>NEXT VALUE FOR</command>
+      expression.
+     </para>
+    </listitem>
+    <listitem>
+     <para>
+      The <literal>OWNED BY</> clause is a <productname>PostgreSQL</>
+      extension. 
+     </para>
+    </listitem>
    </itemizedlist>
   </para>
  </refsect1>
+
+ <refsect1>
+  <title>See Also</title>
+
+  <simplelist type="inline">
+   <member><xref linkend="sql-altersequence" endterm="sql-altersequence-title"></member>
+   <member><xref linkend="sql-dropsequence" endterm="sql-dropsequence-title"></member>
+  </simplelist>
+ </refsect1>
+
 </refentry>
 
 <!-- Keep this comment at the end of the file
diff --git a/doc/src/sgml/ref/drop_sequence.sgml b/doc/src/sgml/ref/drop_sequence.sgml
index 074f4e7216d0600b662042e517833083ba8c2b94..d730d683d3f26834aedd26072cd7452347c5af4c 100644
--- a/doc/src/sgml/ref/drop_sequence.sgml
+++ b/doc/src/sgml/ref/drop_sequence.sgml
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/drop_sequence.sgml,v 1.24 2005/11/19 17:39:44 adunstan Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/drop_sequence.sgml,v 1.25 2006/08/21 00:57:24 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -105,6 +105,7 @@ DROP SEQUENCE serial;
 
   <simplelist type="inline">
    <member><xref linkend="sql-createsequence" endterm="sql-createsequence-title"></member>
+   <member><xref linkend="sql-altersequence" endterm="sql-altersequence-title"></member>
   </simplelist>
  </refsect1>
 
diff --git a/src/backend/catalog/pg_depend.c b/src/backend/catalog/pg_depend.c
index 5a297d4a275f539e9864ba9d515e2679bbe096a7..99cdf5e7e6ae6832d733db75d5fe67048b42c04c 100644
--- a/src/backend/catalog/pg_depend.c
+++ b/src/backend/catalog/pg_depend.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/catalog/pg_depend.c,v 1.21 2006/07/11 17:26:58 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/catalog/pg_depend.c,v 1.22 2006/08/21 00:57:24 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -162,58 +162,6 @@ deleteDependencyRecordsFor(Oid classId, Oid objectId)
 	return count;
 }
 
-/*
- * objectIsInternalDependency -- return whether the specified object
- * is listed as an internal dependency for some other object.
- *
- * This is used to implement DROP/REASSIGN OWNED.  We cannot invoke
- * performDeletion blindly, because it may try to drop or modify an internal-
- * dependent object before the "main" object, so we need to skip the first
- * object and expect it to be automatically dropped when the main object is
- * dropped.
- */
-bool
-objectIsInternalDependency(Oid classId, Oid objectId)
-{
-	Relation	depRel;
-	ScanKeyData key[2];
-	SysScanDesc scan;
-	HeapTuple	tup;
-	bool		isdep = false;
-
-	depRel = heap_open(DependRelationId, AccessShareLock);
-
-	ScanKeyInit(&key[0],
-				Anum_pg_depend_classid,
-				BTEqualStrategyNumber, F_OIDEQ,
-				ObjectIdGetDatum(classId));
-	ScanKeyInit(&key[1],
-				Anum_pg_depend_objid,
-				BTEqualStrategyNumber, F_OIDEQ,
-				ObjectIdGetDatum(objectId));
-
-	scan = systable_beginscan(depRel, DependDependerIndexId, true,
-							  SnapshotNow, 2, key);
-
-	while (HeapTupleIsValid(tup = systable_getnext(scan)))
-	{
-		Form_pg_depend depForm = (Form_pg_depend) GETSTRUCT(tup);
-
-		if (depForm->deptype == DEPENDENCY_INTERNAL)
-		{
-			/* No need to keep scanning */
-			isdep = true;
-			break;
-		}
-	}
-
-	systable_endscan(scan);
-
-	heap_close(depRel, AccessShareLock);
-
-	return isdep;
-}
-
 /*
  * Adjust dependency record(s) to point to a different object of the same type
  *
@@ -312,6 +260,105 @@ changeDependencyFor(Oid classId, Oid objectId,
 	return count;
 }
 
+/*
+ * Detect whether a sequence is marked as "owned" by a column
+ *
+ * An ownership marker is an AUTO dependency from the sequence to the
+ * column.  If we find one, store the identity of the owning column
+ * into *tableId and *colId and return TRUE; else return FALSE.
+ *
+ * Note: if there's more than one such pg_depend entry then you get
+ * a random one of them returned into the out parameters.  This should
+ * not happen, though.
+ */
+bool
+sequenceIsOwned(Oid seqId, Oid *tableId, int32 *colId)
+{
+	bool		ret = false;
+	Relation	depRel;
+	ScanKeyData key[2];
+	SysScanDesc scan;
+	HeapTuple	tup;
+
+	depRel = heap_open(DependRelationId, AccessShareLock);
+
+	ScanKeyInit(&key[0],
+				Anum_pg_depend_classid,
+				BTEqualStrategyNumber, F_OIDEQ,
+				ObjectIdGetDatum(RelationRelationId));
+	ScanKeyInit(&key[1],
+				Anum_pg_depend_objid,
+				BTEqualStrategyNumber, F_OIDEQ,
+				ObjectIdGetDatum(seqId));
+
+	scan = systable_beginscan(depRel, DependDependerIndexId, true,
+							  SnapshotNow, 2, key);
+
+	while (HeapTupleIsValid((tup = systable_getnext(scan))))
+	{
+		Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
+
+		if (depform->refclassid == RelationRelationId &&
+			depform->deptype == DEPENDENCY_AUTO)
+		{
+			*tableId = depform->refobjid;
+			*colId = depform->refobjsubid;
+			ret = true;
+			break;				/* no need to keep scanning */
+		}
+	}
+
+	systable_endscan(scan);
+
+	heap_close(depRel, AccessShareLock);
+
+	return ret;
+}
+
+/*
+ * Remove any existing "owned" markers for the specified sequence.
+ *
+ * Note: we don't provide a special function to install an "owned"
+ * marker; just use recordDependencyOn().
+ */
+void
+markSequenceUnowned(Oid seqId)
+{
+	Relation	depRel;
+	ScanKeyData key[2];
+	SysScanDesc scan;
+	HeapTuple	tup;
+
+	depRel = heap_open(DependRelationId, RowExclusiveLock);
+
+	ScanKeyInit(&key[0],
+				Anum_pg_depend_classid,
+				BTEqualStrategyNumber, F_OIDEQ,
+				ObjectIdGetDatum(RelationRelationId));
+	ScanKeyInit(&key[1],
+				Anum_pg_depend_objid,
+				BTEqualStrategyNumber, F_OIDEQ,
+				ObjectIdGetDatum(seqId));
+
+	scan = systable_beginscan(depRel, DependDependerIndexId, true,
+							  SnapshotNow, 2, key);
+
+	while (HeapTupleIsValid((tup = systable_getnext(scan))))
+	{
+		Form_pg_depend depform = (Form_pg_depend) GETSTRUCT(tup);
+
+		if (depform->refclassid == RelationRelationId &&
+			depform->deptype == DEPENDENCY_AUTO)
+		{
+			simple_heap_delete(depRel, &tup->t_self);
+		}
+	}
+
+	systable_endscan(scan);
+
+	heap_close(depRel, RowExclusiveLock);
+}
+
 /*
  * isObjectPinned()
  *
diff --git a/src/backend/catalog/pg_shdepend.c b/src/backend/catalog/pg_shdepend.c
index 31f1f654de007a80e388c9affbd0672e271d5d48..85e3d968d489a170197b8bdfd625550b988163c1 100644
--- a/src/backend/catalog/pg_shdepend.c
+++ b/src/backend/catalog/pg_shdepend.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/catalog/pg_shdepend.c,v 1.13 2006/08/20 21:56:16 alvherre Exp $
+ *	  $PostgreSQL: pgsql/src/backend/catalog/pg_shdepend.c,v 1.14 2006/08/21 00:57:24 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,6 +17,7 @@
 #include "access/genam.h"
 #include "access/heapam.h"
 #include "access/xact.h"
+#include "catalog/catalog.h"
 #include "catalog/dependency.h"
 #include "catalog/indexing.h"
 #include "catalog/pg_authid.h"
@@ -869,30 +870,17 @@ shdepDropDependency(Relation sdepRel, Oid classId, Oid objectId,
  * Get the database Id that should be used in pg_shdepend, given the OID
  * of the catalog containing the object.  For shared objects, it's 0
  * (InvalidOid); for all other objects, it's the current database Id.
- *
- * XXX it's awfully tempting to hard-wire this instead of doing a syscache
- * lookup ... but resist the temptation, unless you can prove it's a
- * bottleneck.
  */
 static Oid
 classIdGetDbId(Oid classId)
 {
 	Oid			dbId;
-	HeapTuple	tup;
-
-	tup = SearchSysCache(RELOID,
-						 ObjectIdGetDatum(classId),
-						 0, 0, 0);
-	if (!HeapTupleIsValid(tup))
-		elog(ERROR, "cache lookup failed for relation %u", classId);
 
-	if (((Form_pg_class) GETSTRUCT(tup))->relisshared)
+	if (IsSharedRelation(classId))
 		dbId = InvalidOid;
 	else
 		dbId = MyDatabaseId;
 
-	ReleaseSysCache(tup);
-
 	return dbId;
 }
 
@@ -1055,6 +1043,11 @@ isSharedObjectPinned(Oid classId, Oid objectId, Relation sdepRel)
  * Drop the objects owned by any one of the given RoleIds.	If a role has
  * access to an object, the grant will be removed as well (but the object
  * will not, of course.)
+ *
+ * We can revoke grants immediately while doing the scan, but drops are
+ * saved up and done all at once with performMultipleDeletions.  This
+ * is necessary so that we don't get failures from trying to delete
+ * interdependent objects in the wrong order.
  */
 void
 shdepDropOwned(List *roleids, DropBehavior behavior)
@@ -1113,7 +1106,7 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
 			InternalGrant	istmt;
 			Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple);
 
-			/* We only operate on objects on the current database */
+			/* We only operate on objects in the current database */
 			if (sdepForm->dbid != MyDatabaseId)
 				continue;
 
@@ -1128,24 +1121,8 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
 					switch (sdepForm->classid)
 					{
 						case RelationRelationId:
-							{
-								/* is it a sequence or non-sequence? */
-								Form_pg_class pg_class_tuple;
-								HeapTuple	tuple;
-
-								tuple = SearchSysCache(RELOID,
-													   ObjectIdGetDatum(sdepForm->objid),
-													   0, 0, 0);
-								if (!HeapTupleIsValid(tuple))
-									elog(ERROR, "cache lookup failed for relation %u",
-										 sdepForm->objid);
-								pg_class_tuple = (Form_pg_class) GETSTRUCT(tuple);
-								if (pg_class_tuple->relkind == RELKIND_SEQUENCE)
-									istmt.objtype = ACL_OBJECT_SEQUENCE;
-								else
-									istmt.objtype = ACL_OBJECT_RELATION;
-								ReleaseSysCache(tuple);
-							}
+							/* it's OK to use RELATION for a sequence */
+							istmt.objtype = ACL_OBJECT_RELATION;
 							break;
 						case DatabaseRelationId:
 							istmt.objtype = ACL_OBJECT_DATABASE;
@@ -1180,11 +1157,10 @@ shdepDropOwned(List *roleids, DropBehavior behavior)
 					ExecGrantStmt_oids(&istmt);
 					break;
 				case SHARED_DEPENDENCY_OWNER:
-					/* Save it for later deleting it */
+					/* Save it for deletion below */
 					obj.classId = sdepForm->classid;
 					obj.objectId = sdepForm->objid;
 					obj.objectSubId = 0;
-
 					add_exact_object_address(&obj, deleteobjs);
 					break;
 			}
@@ -1259,7 +1235,7 @@ shdepReassignOwned(List *roleids, Oid newrole)
 		{
 			Form_pg_shdepend sdepForm = (Form_pg_shdepend) GETSTRUCT(tuple);
 
-			/* We only operate on objects on the current database */
+			/* We only operate on objects in the current database */
 			if (sdepForm->dbid != MyDatabaseId)
 				continue;
 
@@ -1271,15 +1247,7 @@ shdepReassignOwned(List *roleids, Oid newrole)
 			if (sdepForm->deptype != SHARED_DEPENDENCY_OWNER)
 				continue;
 
-			/*
-			 * If there's a regular (non-shared) dependency on this object
-			 * marked with DEPENDENCY_INTERNAL, skip this object.  We will
-			 * alter the referencer object instead.
-			 */
-			if (objectIsInternalDependency(sdepForm->classid, sdepForm->objid))
-				continue;
-
-			/* Issue the appropiate ALTER OWNER call */
+			/* Issue the appropriate ALTER OWNER call */
 			switch (sdepForm->classid)
 			{
 				case ConversionRelationId:
@@ -1299,7 +1267,12 @@ shdepReassignOwned(List *roleids, Oid newrole)
 					break;
 
 				case RelationRelationId:
-					ATExecChangeOwner(sdepForm->objid, newrole, false);
+					/*
+					 * Pass recursing = true so that we don't fail on
+					 * indexes, owned sequences, etc when we happen
+					 * to visit them before their parent table.
+					 */
+					ATExecChangeOwner(sdepForm->objid, newrole, true);
 					break;
 
 				case ProcedureRelationId:
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index 6154a4ed3da20e9ad253f49f17d187193e55a6f3..865c2f60fe5527e008fd14c74163e20eb5091d53 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.138 2006/07/31 20:09:00 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.139 2006/08/21 00:57:24 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,6 +17,7 @@
 #include "access/heapam.h"
 #include "access/transam.h"
 #include "access/xact.h"
+#include "catalog/dependency.h"
 #include "catalog/namespace.h"
 #include "catalog/pg_type.h"
 #include "commands/defrem.h"
@@ -26,6 +27,7 @@
 #include "nodes/makefuncs.h"
 #include "utils/acl.h"
 #include "utils/builtins.h"
+#include "utils/lsyscache.h"
 #include "utils/resowner.h"
 #include "utils/syscache.h"
 
@@ -82,8 +84,11 @@ static int64 nextval_internal(Oid relid);
 static Relation open_share_lock(SeqTable seq);
 static void init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel);
 static Form_pg_sequence read_info(SeqTable elm, Relation rel, Buffer *buf);
-static void init_params(List *options, Form_pg_sequence new, bool isInit);
+static void init_params(List *options, bool isInit,
+						Form_pg_sequence new, List **owned_by);
 static void do_setval(Oid relid, int64 next, bool iscalled);
+static void process_owned_by(Relation seqrel, List *owned_by);
+
 
 /*
  * DefineSequence
@@ -93,6 +98,7 @@ void
 DefineSequence(CreateSeqStmt *seq)
 {
 	FormData_pg_sequence new;
+	List	   *owned_by;
 	CreateStmt *stmt = makeNode(CreateStmt);
 	Oid			seqoid;
 	Relation	rel;
@@ -107,7 +113,7 @@ DefineSequence(CreateSeqStmt *seq)
 	NameData	name;
 
 	/* Check and set all option values */
-	init_params(seq->options, &new, true);
+	init_params(seq->options, true, &new, &owned_by);
 
 	/*
 	 * Create relation (and fill *null & *value)
@@ -123,7 +129,6 @@ DefineSequence(CreateSeqStmt *seq)
 		coldef->raw_default = NULL;
 		coldef->cooked_default = NULL;
 		coldef->constraints = NIL;
-		coldef->support = NULL;
 
 		null[i - 1] = ' ';
 
@@ -287,6 +292,10 @@ DefineSequence(CreateSeqStmt *seq)
 
 	UnlockReleaseBuffer(buf);
 
+	/* process OWNED BY if given */
+	if (owned_by)
+		process_owned_by(rel, owned_by);
+
 	heap_close(rel, NoLock);
 }
 
@@ -305,6 +314,7 @@ AlterSequence(AlterSeqStmt *stmt)
 	Page		page;
 	Form_pg_sequence seq;
 	FormData_pg_sequence new;
+	List	   *owned_by;
 
 	/* open and AccessShareLock sequence */
 	relid = RangeVarGetRelid(stmt->sequence, false);
@@ -323,7 +333,7 @@ AlterSequence(AlterSeqStmt *stmt)
 	memcpy(&new, seq, sizeof(FormData_pg_sequence));
 
 	/* Check and set new values */
-	init_params(stmt->options, &new, false);
+	init_params(stmt->options, false, &new, &owned_by);
 
 	/* Now okay to update the on-disk tuple */
 	memcpy(seq, &new, sizeof(FormData_pg_sequence));
@@ -366,6 +376,10 @@ AlterSequence(AlterSeqStmt *stmt)
 
 	UnlockReleaseBuffer(buf);
 
+	/* process OWNED BY if given */
+	if (owned_by)
+		process_owned_by(seqrel, owned_by);
+
 	relation_close(seqrel, NoLock);
 }
 
@@ -933,13 +947,15 @@ read_info(SeqTable elm, Relation rel, Buffer *buf)
 
 /*
  * init_params: process the options list of CREATE or ALTER SEQUENCE,
- * and store the values into appropriate fields of *new.
+ * and store the values into appropriate fields of *new.  Also set
+ * *owned_by to any OWNED BY option, or to NIL if there is none.
  *
  * If isInit is true, fill any unspecified options with default values;
  * otherwise, do not change existing options that aren't explicitly overridden.
  */
 static void
-init_params(List *options, Form_pg_sequence new, bool isInit)
+init_params(List *options, bool isInit,
+			Form_pg_sequence new, List **owned_by)
 {
 	DefElem    *last_value = NULL;
 	DefElem    *increment_by = NULL;
@@ -949,6 +965,8 @@ init_params(List *options, Form_pg_sequence new, bool isInit)
 	DefElem    *is_cycled = NULL;
 	ListCell   *option;
 
+	*owned_by = NIL;
+
 	foreach(option, options)
 	{
 		DefElem    *defel = (DefElem *) lfirst(option);
@@ -1006,6 +1024,14 @@ init_params(List *options, Form_pg_sequence new, bool isInit)
 						 errmsg("conflicting or redundant options")));
 			is_cycled = defel;
 		}
+		else if (strcmp(defel->defname, "owned_by") == 0)
+		{
+			if (*owned_by)
+				ereport(ERROR,
+						(errcode(ERRCODE_SYNTAX_ERROR),
+						 errmsg("conflicting or redundant options")));
+			*owned_by = defGetQualifiedName(defel);
+		}
 		else
 			elog(ERROR, "option \"%s\" not recognized",
 				 defel->defname);
@@ -1130,6 +1156,99 @@ init_params(List *options, Form_pg_sequence new, bool isInit)
 		new->cache_value = 1;
 }
 
+/*
+ * Process an OWNED BY option for CREATE/ALTER SEQUENCE
+ *
+ * Ownership permissions on the sequence are already checked,
+ * but if we are establishing a new owned-by dependency, we must
+ * enforce that the referenced table has the same owner and namespace
+ * as the sequence.
+ */
+static void
+process_owned_by(Relation seqrel, List *owned_by)
+{
+	int			nnames;
+	Relation	tablerel;
+	AttrNumber	attnum;
+
+	nnames = list_length(owned_by);
+	Assert(nnames > 0);
+	if (nnames == 1)
+	{
+		/* Must be OWNED BY NONE */
+		if (strcmp(strVal(linitial(owned_by)), "none") != 0)
+			ereport(ERROR,
+					(errcode(ERRCODE_SYNTAX_ERROR),
+					 errmsg("invalid OWNED BY option"),
+					 errhint("Specify OWNED BY table.column or OWNED BY NONE.")));
+		tablerel = NULL;
+		attnum = 0;
+	}
+	else
+	{
+		List	   *relname;
+		char	   *attrname;
+		RangeVar   *rel;
+
+		/* Separate relname and attr name */
+		relname = list_truncate(list_copy(owned_by), nnames - 1);
+		attrname = strVal(lfirst(list_tail(owned_by)));
+
+		/* Open and lock rel to ensure it won't go away meanwhile */
+		rel = makeRangeVarFromNameList(relname);
+		tablerel = relation_openrv(rel, AccessShareLock);
+
+		/* Must be a regular table */
+		if (tablerel->rd_rel->relkind != RELKIND_RELATION)
+			ereport(ERROR,
+					(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+					 errmsg("referenced relation \"%s\" is not a table",
+							RelationGetRelationName(tablerel))));
+
+		/* We insist on same owner and schema */
+		if (seqrel->rd_rel->relowner != tablerel->rd_rel->relowner)
+			ereport(ERROR,
+					(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+					 errmsg("sequence must have same owner as table it is owned by")));
+		if (RelationGetNamespace(seqrel) != RelationGetNamespace(tablerel))
+			ereport(ERROR,
+					(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+					 errmsg("sequence must be in same schema as table it is owned by")));
+
+		/* Now, fetch the attribute number from the system cache */
+		attnum = get_attnum(RelationGetRelid(tablerel), attrname);
+		if (attnum == InvalidAttrNumber)
+			ereport(ERROR,
+					(errcode(ERRCODE_UNDEFINED_COLUMN),
+					 errmsg("column \"%s\" of relation \"%s\" does not exist",
+							attrname, RelationGetRelationName(tablerel))));
+	}
+
+	/*
+	 * OK, we are ready to update pg_depend.  First remove any existing
+	 * AUTO dependencies for the sequence, then optionally add a new one.
+	 */
+	markSequenceUnowned(RelationGetRelid(seqrel));
+
+	if (tablerel)
+	{
+		ObjectAddress refobject,
+					depobject;
+
+		refobject.classId = RelationRelationId;
+		refobject.objectId = RelationGetRelid(tablerel);
+		refobject.objectSubId = attnum;
+		depobject.classId = RelationRelationId;
+		depobject.objectId = RelationGetRelid(seqrel);
+		depobject.objectSubId = 0;
+		recordDependencyOn(&depobject, &refobject, DEPENDENCY_AUTO);
+	}
+
+	/* Done, but hold lock until commit */
+	if (tablerel)
+		relation_close(tablerel, NoLock);
+}
+
 
 void
 seq_redo(XLogRecPtr lsn, XLogRecord *record)
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index cd4c4eb2304deca6a08529986e3621cc66cda322..a1f76033377acb5fb7fe9893ba0b173d786dfe9c 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.199 2006/08/03 20:57:06 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.200 2006/08/21 00:57:24 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -209,8 +209,6 @@ static void ATPrepAddColumn(List **wqueue, Relation rel, bool recurse,
 static void ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
 				ColumnDef *colDef);
 static void add_column_datatype_dependency(Oid relid, int32 attnum, Oid typid);
-static void add_column_support_dependency(Oid relid, int32 attnum,
-							  RangeVar *support);
 static void ATExecDropNotNull(Relation rel, const char *colName);
 static void ATExecSetNotNull(AlteredTableInfo *tab, Relation rel,
 				 const char *colName);
@@ -476,10 +474,6 @@ DefineRelation(CreateStmt *stmt, char relkind)
 	 * work unless we have a pre-existing relation. 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;
@@ -502,10 +496,6 @@ DefineRelation(CreateStmt *stmt, char relkind)
 			rawEnt->raw_default = colDef->raw_default;
 			rawDefaults = lappend(rawDefaults, rawEnt);
 		}
-
-		/* Create dependency for supporting relation for this column */
-		if (colDef->support != NULL)
-			add_column_support_dependency(relationId, attnum, colDef->support);
 	}
 
 	/*
@@ -944,7 +934,6 @@ 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;
 			}
@@ -1159,9 +1148,10 @@ varattnos_map(TupleDesc old, TupleDesc new)
 	return attmap;
 }
 
-/* Generate a map for change_varattnos_of_a_node from a tupledesc and a list of
- * ColumnDefs */
-
+/*
+ * Generate a map for change_varattnos_of_a_node from a tupledesc and a list of
+ * ColumnDefs
+ */
 AttrNumber *
 varattnos_map_schema(TupleDesc old, List *schema) 
 {
@@ -3017,8 +3007,6 @@ ATPrepAddColumn(List **wqueue, Relation rel, bool recurse,
 		/* Child should see column as singly inherited */
 		colDefChild->inhcount = 1;
 		colDefChild->is_local = false;
-		/* and don't make a support dependency on the child */
-		colDefChild->support = NULL;
 
 		ATOneLevelRecursion(wqueue, rel, childCmd);
 	}
@@ -3259,8 +3247,6 @@ ATExecAddColumn(AlteredTableInfo *tab, Relation rel,
 	 * Add needed dependency entries for the new column.
 	 */
 	add_column_datatype_dependency(myrelid, i, attribute->atttypid);
-	if (colDef->support != NULL)
-		add_column_support_dependency(myrelid, i, colDef->support);
 }
 
 /*
@@ -3281,24 +3267,6 @@ add_column_datatype_dependency(Oid relid, int32 attnum, Oid typid)
 	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
 }
 
-/*
- * Install a dependency for a column's supporting relation (serial sequence).
- */
-static void
-add_column_support_dependency(Oid relid, int32 attnum, RangeVar *support)
-{
-	ObjectAddress colobject,
-				suppobject;
-
-	colobject.classId = RelationRelationId;
-	colobject.objectId = relid;
-	colobject.objectSubId = attnum;
-	suppobject.classId = RelationRelationId;
-	suppobject.objectId = RangeVarGetRelid(support, false);
-	suppobject.objectSubId = 0;
-	recordDependencyOn(&suppobject, &colobject, DEPENDENCY_INTERNAL);
-}
-
 /*
  * ALTER TABLE ALTER COLUMN DROP NOT NULL
  */
@@ -5444,9 +5412,9 @@ ATPostAlterTypeParse(char *cmd, List **wqueue)
 /*
  * ALTER TABLE OWNER
  *
- * recursing is true if we are recursing from a table to its indexes or
- * toast table.  We don't allow the ownership of those things to be
- * changed separately from the parent table.  Also, we can skip permission
+ * recursing is true if we are recursing from a table to its indexes,
+ * sequences, or toast table.  We don't allow the ownership of those things to
+ * be changed separately from the parent table.  Also, we can skip permission
  * checks (this is necessary not just an optimization, else we'd fail to
  * handle toast tables properly).
  */
@@ -5479,7 +5447,6 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing)
 	{
 		case RELKIND_RELATION:
 		case RELKIND_VIEW:
-		case RELKIND_SEQUENCE:
 			/* ok to change owner */
 			break;
 		case RELKIND_INDEX:
@@ -5502,6 +5469,24 @@ ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing)
 				newOwnerId = tuple_class->relowner;
 			}
 			break;
+		case RELKIND_SEQUENCE:
+			if (!recursing &&
+				tuple_class->relowner != newOwnerId)
+			{
+				/* if it's an owned sequence, disallow changing it by itself */
+				Oid		tableId;
+				int32	colId;
+
+				if (sequenceIsOwned(relationOid, &tableId, &colId))
+					ereport(ERROR,
+							(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+							 errmsg("cannot change owner of sequence \"%s\"",
+									NameStr(tuple_class->relname)),
+							 errdetail("Sequence \"%s\" is linked to table \"%s\".",
+									   NameStr(tuple_class->relname),
+									   get_rel_name(tableId))));
+			}
+			break;
 		case RELKIND_TOASTVALUE:
 			if (recursing)
 				break;
@@ -5644,7 +5629,7 @@ change_owner_recurse_to_sequences(Oid relationOid, Oid newOwnerId)
 	HeapTuple	tup;
 
 	/*
-	 * SERIAL sequences are those having an internal dependency on one of the
+	 * SERIAL sequences are those having an auto dependency on one of the
 	 * table's columns (we don't care *which* column, exactly).
 	 */
 	depRel = heap_open(DependRelationId, AccessShareLock);
@@ -5667,11 +5652,11 @@ change_owner_recurse_to_sequences(Oid relationOid, Oid newOwnerId)
 		Form_pg_depend depForm = (Form_pg_depend) GETSTRUCT(tup);
 		Relation	seqRel;
 
-		/* skip dependencies other than internal dependencies on columns */
+		/* skip dependencies other than auto dependencies on columns */
 		if (depForm->refobjsubid == 0 ||
 			depForm->classid != RelationRelationId ||
 			depForm->objsubid != 0 ||
-			depForm->deptype != DEPENDENCY_INTERNAL)
+			depForm->deptype != DEPENDENCY_AUTO)
 			continue;
 
 		/* Use relation_open just in case it's an index */
@@ -5686,7 +5671,7 @@ change_owner_recurse_to_sequences(Oid relationOid, Oid newOwnerId)
 		}
 
 		/* We don't need to close the sequence while we alter it. */
-		ATExecChangeOwner(depForm->objid, newOwnerId, false);
+		ATExecChangeOwner(depForm->objid, newOwnerId, true);
 
 		/* Now we can close it.  Keep the lock till end of transaction. */
 		relation_close(seqRel, NoLock);
@@ -6549,6 +6534,9 @@ AlterTableNamespace(RangeVar *relation, const char *newschema)
 
 	rel = heap_openrv(relation, AccessExclusiveLock);
 
+	relid = RelationGetRelid(rel);
+	oldNspOid = RelationGetNamespace(rel);
+
 	/* heap_openrv allows TOAST, but we don't want to */
 	if (rel->rd_rel->relkind == RELKIND_TOASTVALUE)
 		ereport(ERROR,
@@ -6556,8 +6544,20 @@ AlterTableNamespace(RangeVar *relation, const char *newschema)
 				 errmsg("\"%s\" is a TOAST relation",
 						RelationGetRelationName(rel))));
 
-	relid = RelationGetRelid(rel);
-	oldNspOid = RelationGetNamespace(rel);
+	/* if it's an owned sequence, disallow moving it by itself */
+	if (rel->rd_rel->relkind == RELKIND_SEQUENCE)
+	{
+		Oid		tableId;
+		int32	colId;
+
+		if (sequenceIsOwned(relid, &tableId, &colId))
+			ereport(ERROR,
+					(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+					 errmsg("cannot move an owned sequence into another schema"),
+					 errdetail("Sequence \"%s\" is linked to table \"%s\".",
+							   RelationGetRelationName(rel),
+							   get_rel_name(tableId))));
+	}
 
 	/* get schema OID and check its permissions */
 	nspOid = LookupCreationNamespace(newschema);
@@ -6699,7 +6699,7 @@ AlterSeqNamespaces(Relation classRel, Relation rel,
 	HeapTuple	tup;
 
 	/*
-	 * SERIAL sequences are those having an internal dependency on one of the
+	 * SERIAL sequences are those having an auto dependency on one of the
 	 * table's columns (we don't care *which* column, exactly).
 	 */
 	depRel = heap_open(DependRelationId, AccessShareLock);
@@ -6722,11 +6722,11 @@ AlterSeqNamespaces(Relation classRel, Relation rel,
 		Form_pg_depend depForm = (Form_pg_depend) GETSTRUCT(tup);
 		Relation	seqRel;
 
-		/* skip dependencies other than internal dependencies on columns */
+		/* skip dependencies other than auto dependencies on columns */
 		if (depForm->refobjsubid == 0 ||
 			depForm->classid != RelationRelationId ||
 			depForm->objsubid != 0 ||
-			depForm->deptype != DEPENDENCY_INTERNAL)
+			depForm->deptype != DEPENDENCY_AUTO)
 			continue;
 
 		/* Use relation_open just in case it's an index */
diff --git a/src/backend/commands/view.c b/src/backend/commands/view.c
index 63850cbeae7317aa1eabfb3191c3d6ff139c8a28..df7f479f3162643775705443a83cfdfaa003e22c 100644
--- a/src/backend/commands/view.c
+++ b/src/backend/commands/view.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.96 2006/07/13 16:49:14 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/view.c,v 1.97 2006/08/21 00:57:24 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -126,7 +126,6 @@ DefineVirtualRelation(const RangeVar *relation, List *tlist, bool replace)
 			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 2b8f3af09b96a229a0b20b5ea062b17358bd2b04..40e35a379668fce9d5d2216f4b1d7f30df652e68 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
- *	  $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.347 2006/08/12 02:52:04 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/nodes/copyfuncs.c,v 1.348 2006/08/21 00:57:24 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1641,7 +1641,6 @@ _copyColumnDef(ColumnDef *from)
 	COPY_NODE_FIELD(raw_default);
 	COPY_STRING_FIELD(cooked_default);
 	COPY_NODE_FIELD(constraints);
-	COPY_NODE_FIELD(support);
 
 	return newnode;
 }
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 665d4833be3619a80c88b9cf3abbf91075014e3f..b4d0632c03745a720876c5a980f3de71ec5d3eb8 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -18,7 +18,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.281 2006/08/12 02:52:04 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/nodes/equalfuncs.c,v 1.282 2006/08/21 00:57:24 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1665,7 +1665,6 @@ _equalColumnDef(ColumnDef *a, ColumnDef *b)
 	COMPARE_NODE_FIELD(raw_default);
 	COMPARE_STRING_FIELD(cooked_default);
 	COMPARE_NODE_FIELD(constraints);
-	COMPARE_NODE_FIELD(support);
 
 	return true;
 }
diff --git a/src/backend/nodes/makefuncs.c b/src/backend/nodes/makefuncs.c
index 784dd57831d6102c26537ec2abadc2a604db218d..7555cbd0dd032cc8d2d1074d4bcbe88929ddcde5 100644
--- a/src/backend/nodes/makefuncs.c
+++ b/src/backend/nodes/makefuncs.c
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/nodes/makefuncs.c,v 1.50 2006/03/14 22:48:19 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/nodes/makefuncs.c,v 1.51 2006/08/21 00:57:24 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -322,3 +322,17 @@ makeFuncExpr(Oid funcid, Oid rettype, List *args, CoercionForm fformat)
 
 	return funcexpr;
 }
+
+/*
+ * makeDefElem -
+ *	build a DefElem node
+ */
+DefElem *
+makeDefElem(char *name, Node *arg)
+{
+	DefElem *res = makeNode(DefElem);
+
+	res->defname = name;
+	res->arg = arg;
+	return res;
+}
diff --git a/src/backend/nodes/outfuncs.c b/src/backend/nodes/outfuncs.c
index a1ed403d79bda2e7b5449e7276cb1439967dc2fc..a4b4044385db645e892907919abeac184f73ffd5 100644
--- a/src/backend/nodes/outfuncs.c
+++ b/src/backend/nodes/outfuncs.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.282 2006/08/12 02:52:04 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/nodes/outfuncs.c,v 1.283 2006/08/21 00:57:24 tgl Exp $
  *
  * NOTES
  *	  Every node type that can appear in stored rules' parsetrees *must*
@@ -1444,7 +1444,6 @@ _outColumnDef(StringInfo str, ColumnDef *node)
 	WRITE_NODE_FIELD(raw_default);
 	WRITE_STRING_FIELD(cooked_default);
 	WRITE_NODE_FIELD(constraints);
-	WRITE_NODE_FIELD(support);
 }
 
 static void
diff --git a/src/backend/parser/analyze.c b/src/backend/parser/analyze.c
index 39c7372733f3b4dae970620670f4275f56231267..8eb50fb573eeaf9f74549fdf612e17daf9ae6856 100644
--- a/src/backend/parser/analyze.c
+++ b/src/backend/parser/analyze.c
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- *	$PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.346 2006/08/12 20:05:55 tgl Exp $
+ *	$PostgreSQL: pgsql/src/backend/parser/analyze.c,v 1.347 2006/08/21 00:57:24 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -980,6 +980,14 @@ transformCreateStmt(ParseState *pstate, CreateStmt *stmt,
 		}
 	}
 
+	/*
+	 * transformIndexConstraints wants cxt.alist to contain only index
+	 * statements, so transfer anything we already have into extras_after
+	 * immediately.
+	 */
+	*extras_after = list_concat(cxt.alist, *extras_after);
+	cxt.alist = NIL;
+
 	Assert(stmt->constraints == NIL);
 
 	/*
@@ -1052,6 +1060,8 @@ transformColumnDefinition(ParseState *pstate, CreateStmtContext *cxt,
 		A_Const    *snamenode;
 		FuncCall   *funccallnode;
 		CreateSeqStmt *seqstmt;
+		AlterSeqStmt *altseqstmt;
+		List	   *attnamelist;
 
 		/*
 		 * Determine namespace and name to use for the sequence.
@@ -1088,10 +1098,19 @@ 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.
+		 * Build an ALTER SEQUENCE ... OWNED BY command to mark the sequence
+		 * as owned by this column, and add it to the list of things to be
+		 * done after this CREATE/ALTER TABLE.
 		 */
-		column->support = makeRangeVar(snamespace, sname);
+		altseqstmt = makeNode(AlterSeqStmt);
+		altseqstmt->sequence = makeRangeVar(snamespace, sname);
+		attnamelist = list_make3(makeString(snamespace),
+								 makeString(cxt->relation->relname),
+								 makeString(column->colname));
+		altseqstmt->options = list_make1(makeDefElem("owned_by",
+													 (Node *) attnamelist));
+
+		cxt->alist = lappend(cxt->alist, altseqstmt);
 
 		/*
 		 * Create appropriate constraints for SERIAL.  We do this in full,
@@ -1349,7 +1368,6 @@ transformInhRelation(ParseState *pstate, CreateStmtContext *cxt,
 		def->raw_default = NULL;
 		def->cooked_default = NULL;
 		def->constraints = NIL;
-		def->support = NULL;
 
 		/*
 		 * Add to column list
@@ -1604,7 +1622,7 @@ transformIndexConstraints(ParseState *pstate, CreateStmtContext *cxt)
 	 * XXX in ALTER TABLE case, it'd be nice to look for duplicate
 	 * pre-existing indexes, too.
 	 */
-	cxt->alist = NIL;
+	Assert(cxt->alist == NIL);
 	if (cxt->pkey != NULL)
 	{
 		/* Make sure we keep the PKEY index in preference to others... */
@@ -3041,6 +3059,14 @@ transformAlterTableStmt(ParseState *pstate, AlterTableStmt *stmt,
 		}
 	}
 
+	/*
+	 * transformIndexConstraints wants cxt.alist to contain only index
+	 * statements, so transfer anything we already have into extras_after
+	 * immediately.
+	 */
+	*extras_after = list_concat(cxt.alist, *extras_after);
+	cxt.alist = NIL;
+
 	/* Postprocess index and FK constraints */
 	transformIndexConstraints(pstate, &cxt);
 
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index c0744a74a42d206a101c45028d2a6128cc9d962e..60761ae6bca286282f892f0c1ca7416c3be048dc 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.556 2006/08/12 18:58:54 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.557 2006/08/21 00:57:25 tgl Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -95,7 +95,6 @@ static Node *makeIntConst(int val);
 static Node *makeFloatConst(char *str);
 static Node *makeAConst(Value *v);
 static Node *makeRowNullTest(NullTestType test, RowExpr *row);
-static DefElem *makeDefElem(char *name, Node *arg);
 static A_Const *makeBoolAConst(bool state);
 static FuncCall *makeOverlaps(List *largs, List *rargs, int location);
 static void check_qualified_name(List *names);
@@ -2275,7 +2274,6 @@ CreateAsElement:
 					n->raw_default = NULL;
 					n->cooked_default = NULL;
 					n->constraints = NIL;
-					n->support = NULL;
 					$$ = (Node *)n;
 				}
 		;
@@ -2346,6 +2344,10 @@ OptSeqElem: CACHE NumericOnly
 				{
 					$$ = makeDefElem("minvalue", NULL);
 				}
+			| OWNED BY any_name
+				{
+					$$ = makeDefElem("owned_by", (Node *)$3);
+				}
 			| START opt_with NumericOnly
 				{
 					$$ = makeDefElem("start", (Node *)$3);
@@ -8977,19 +8979,6 @@ makeAConst(Value *v)
 	return n;
 }
 
-/* makeDefElem()
- * Create a DefElem node and set contents.
- * Could be moved to nodes/makefuncs.c if this is useful elsewhere.
- */
-static DefElem *
-makeDefElem(char *name, Node *arg)
-{
-	DefElem *f = makeNode(DefElem);
-	f->defname = name;
-	f->arg = arg;
-	return f;
-}
-
 /* makeBoolAConst()
  * Create an A_Const node and initialize to a boolean constant.
  */
diff --git a/src/backend/utils/adt/ruleutils.c b/src/backend/utils/adt/ruleutils.c
index e814310120a1b57cda37764fcc989c7305d688db..a88f5ef93c6b41b5bca191608a0e318c7f5f992e 100644
--- a/src/backend/utils/adt/ruleutils.c
+++ b/src/backend/utils/adt/ruleutils.c
@@ -2,7 +2,7 @@
  * ruleutils.c	- Functions to convert stored expressions/querytrees
  *				back to source text
  *
- *	  $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.231 2006/08/12 02:52:05 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/utils/adt/ruleutils.c,v 1.232 2006/08/21 00:57:25 tgl Exp $
  **********************************************************************/
 
 #include "postgres.h"
@@ -1287,12 +1287,12 @@ pg_get_serial_sequence(PG_FUNCTION_ARGS)
 		Form_pg_depend deprec = (Form_pg_depend) GETSTRUCT(tup);
 
 		/*
-		 * We assume any internal dependency of a relation on a column must be
+		 * We assume any auto dependency of a relation on a column must be
 		 * what we are looking for.
 		 */
 		if (deprec->classid == RelationRelationId &&
 			deprec->objsubid == 0 &&
-			deprec->deptype == DEPENDENCY_INTERNAL)
+			deprec->deptype == DEPENDENCY_AUTO)
 		{
 			sequenceId = deprec->objid;
 			break;
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index d48cd255c77543b685e035feddf67ab2721ab6dd..78a653fb48c0e40cff40aa819d48e0f82deed8bd 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -12,7 +12,7 @@
  *	by PostgreSQL
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.446 2006/08/04 18:32:15 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.c,v 1.447 2006/08/21 00:57:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -2833,14 +2833,14 @@ getTables(int *numTables)
 	 * Note: in this phase we should collect only a minimal amount of
 	 * information about each table, basically just enough to decide if it is
 	 * interesting. We must fetch all tables in this phase because otherwise
-	 * we cannot correctly identify inherited columns, serial columns, etc.
+	 * we cannot correctly identify inherited columns, owned sequences, etc.
 	 */
 
 	if (g_fout->remoteVersion >= 80200)
 	{
 		/*
 		 * Left join to pick up dependency info linking sequences to their
-		 * serial column, if any
+		 * owning column, if any (note this dependency is AUTO as of 8.2)
 		 */
 		appendPQExpBuffer(query,
 						  "SELECT c.tableoid, c.oid, relname, "
@@ -2857,7 +2857,7 @@ getTables(int *numTables)
 						  "(c.relkind = '%c' and "
 						  "d.classid = c.tableoid and d.objid = c.oid and "
 						  "d.objsubid = 0 and "
-						  "d.refclassid = c.tableoid and d.deptype = 'i') "
+						  "d.refclassid = c.tableoid and d.deptype = 'a') "
 						  "where relkind in ('%c', '%c', '%c', '%c') "
 						  "order by c.oid",
 						  username_subquery,
@@ -2869,7 +2869,7 @@ getTables(int *numTables)
 	{
 		/*
 		 * Left join to pick up dependency info linking sequences to their
-		 * serial column, if any
+		 * owning column, if any
 		 */
 		appendPQExpBuffer(query,
 						  "SELECT c.tableoid, c.oid, relname, "
@@ -2898,7 +2898,7 @@ getTables(int *numTables)
 	{
 		/*
 		 * Left join to pick up dependency info linking sequences to their
-		 * serial column, if any
+		 * owning column, if any
 		 */
 		appendPQExpBuffer(query,
 						  "SELECT c.tableoid, c.oid, relname, "
@@ -3061,14 +3061,10 @@ getTables(int *numTables)
 		/* other fields were zeroed above */
 
 		/*
-		 * Decide whether we want to dump this table.  Sequences owned by
-		 * serial columns are never dumpable on their own; we will transpose
-		 * their owning table's dump flag to them below.
+		 * Decide whether we want to dump this table.
 		 */
 		if (tblinfo[i].relkind == RELKIND_COMPOSITE_TYPE)
 			tblinfo[i].dobj.dump = false;
-		else if (OidIsValid(tblinfo[i].owning_tab))
-			tblinfo[i].dobj.dump = false;
 		else
 			selectDumpableTable(&tblinfo[i]);
 		tblinfo[i].interesting = tblinfo[i].dobj.dump;
@@ -3101,6 +3097,36 @@ getTables(int *numTables)
 	}
 
 	PQclear(res);
+
+	/*
+	 * Force sequences that are "owned" by table columns to be dumped
+	 * whenever their owning table is being dumped.
+	 */
+	for (i = 0; i < ntups; i++)
+	{
+		TableInfo  *seqinfo = &tblinfo[i];
+		int		j;
+
+		if (!OidIsValid(seqinfo->owning_tab))
+			continue;			/* not an owned sequence */
+		if (seqinfo->dobj.dump)
+			continue;			/* no need to search */
+
+		/* can't use findTableByOid yet, unfortunately */
+		for (j = 0; j < ntups; j++)
+		{
+			if (tblinfo[j].dobj.catId.oid == seqinfo->owning_tab)
+			{
+				if (tblinfo[j].dobj.dump)
+				{
+					seqinfo->interesting = true;
+					seqinfo->dobj.dump = true;
+				}
+				break;
+			}
+		}
+	}
+
 	destroyPQExpBuffer(query);
 	destroyPQExpBuffer(delqry);
 	destroyPQExpBuffer(lockquery);
@@ -4161,8 +4187,7 @@ void
 getTableAttrs(TableInfo *tblinfo, int numTables)
 {
 	int			i,
-				j,
-				k;
+				j;
 	PQExpBuffer q = createPQExpBuffer();
 	int			i_attnum;
 	int			i_attname;
@@ -4281,7 +4306,6 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 		tbinfo->typstorage = (char *) malloc(ntups * sizeof(char));
 		tbinfo->attisdropped = (bool *) malloc(ntups * sizeof(bool));
 		tbinfo->attislocal = (bool *) malloc(ntups * sizeof(bool));
-		tbinfo->attisserial = (bool *) malloc(ntups * sizeof(bool));
 		tbinfo->notnull = (bool *) malloc(ntups * sizeof(bool));
 		tbinfo->attrdefs = (AttrDefInfo **) malloc(ntups * sizeof(AttrDefInfo *));
 		tbinfo->inhAttrs = (bool *) malloc(ntups * sizeof(bool));
@@ -4305,7 +4329,6 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 			tbinfo->typstorage[j] = *(PQgetvalue(res, j, i_typstorage));
 			tbinfo->attisdropped[j] = (PQgetvalue(res, j, i_attisdropped)[0] == 't');
 			tbinfo->attislocal[j] = (PQgetvalue(res, j, i_attislocal)[0] == 't');
-			tbinfo->attisserial[j] = false;		/* fix below */
 			tbinfo->notnull[j] = (PQgetvalue(res, j, i_attnotnull)[0] == 't');
 			tbinfo->attrdefs[j] = NULL; /* fix below */
 			if (PQgetvalue(res, j, i_atthasdef)[0] == 't')
@@ -4538,44 +4561,6 @@ getTableAttrs(TableInfo *tblinfo, int numTables)
 			}
 			PQclear(res);
 		}
-
-		/*
-		 * Check to see if any columns are serial columns.	Our first quick
-		 * filter is that it must be integer or bigint with a default.	If so,
-		 * we scan to see if we found a sequence linked to this column. If we
-		 * did, mark the column and sequence appropriately.
-		 */
-		for (j = 0; j < ntups; j++)
-		{
-			/*
-			 * Note assumption that format_type will show these types as
-			 * exactly "integer" and "bigint" regardless of schema path. This
-			 * is correct in 7.3 but needs to be watched.
-			 */
-			if (strcmp(tbinfo->atttypnames[j], "integer") != 0 &&
-				strcmp(tbinfo->atttypnames[j], "bigint") != 0)
-				continue;
-			if (tbinfo->attrdefs[j] == NULL)
-				continue;
-			for (k = 0; k < numTables; k++)
-			{
-				TableInfo  *seqinfo = &tblinfo[k];
-
-				if (OidIsValid(seqinfo->owning_tab) &&
-					seqinfo->owning_tab == tbinfo->dobj.catId.oid &&
-					seqinfo->owning_col == j + 1)
-				{
-					/*
-					 * Found a match.  Copy the table's interesting and
-					 * dumpable flags to the sequence.
-					 */
-					tbinfo->attisserial[j] = true;
-					seqinfo->interesting = tbinfo->interesting;
-					seqinfo->dobj.dump = tbinfo->dobj.dump;
-					break;
-				}
-			}
-		}
 	}
 
 	destroyPQExpBuffer(q);
@@ -7403,16 +7388,8 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
 				/* Attribute type */
 				if (g_fout->remoteVersion >= 70100)
 				{
-					char	   *typname = tbinfo->atttypnames[j];
-
-					if (tbinfo->attisserial[j])
-					{
-						if (strcmp(typname, "integer") == 0)
-							typname = "serial";
-						else if (strcmp(typname, "bigint") == 0)
-							typname = "bigserial";
-					}
-					appendPQExpBuffer(q, "%s", typname);
+					appendPQExpBuffer(q, "%s",
+									  tbinfo->atttypnames[j]);
 				}
 				else
 				{
@@ -7423,24 +7400,17 @@ dumpTableSchema(Archive *fout, TableInfo *tbinfo)
 				}
 
 				/*
-				 * Default value --- suppress if inherited, serial, or to be
+				 * Default value --- suppress if inherited or to be
 				 * printed separately.
 				 */
 				if (tbinfo->attrdefs[j] != NULL &&
 					!tbinfo->inhAttrDef[j] &&
-					!tbinfo->attisserial[j] &&
 					!tbinfo->attrdefs[j]->separate)
 					appendPQExpBuffer(q, " DEFAULT %s",
 									  tbinfo->attrdefs[j]->adef_expr);
 
 				/*
 				 * Not Null constraint --- suppress if inherited
-				 *
-				 * Note: we could suppress this for serial columns since
-				 * SERIAL implies NOT NULL.  We choose not to for forward
-				 * compatibility, since there has been some talk of making
-				 * SERIAL not imply NOT NULL, in which case the explicit
-				 * specification would be needed.
 				 */
 				if (tbinfo->notnull[j] && !tbinfo->inhNotNull[j])
 					appendPQExpBuffer(q, " NOT NULL");
@@ -7597,8 +7567,8 @@ dumpAttrDef(Archive *fout, AttrDefInfo *adinfo)
 	if (!tbinfo->dobj.dump || !adinfo->separate || dataOnly)
 		return;
 
-	/* Don't print inherited or serial defaults, either */
-	if (tbinfo->inhAttrDef[adnum - 1] || tbinfo->attisserial[adnum - 1])
+	/* Don't print inherited defaults, either */
+	if (tbinfo->inhAttrDef[adnum - 1])
 		return;
 
 	q = createPQExpBuffer();
@@ -8111,15 +8081,14 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
 	/*
 	 * The logic we use for restoring sequences is as follows:
 	 *
-	 * Add a basic CREATE SEQUENCE statement (use last_val for start if called
-	 * is false, else use min_val for start_val).  Skip this if the sequence
-	 * came from a SERIAL column.
+	 * Add a CREATE SEQUENCE statement as part of a "schema" dump
+	 * (use last_val for start if called is false, else use min_val for
+	 * start_val).  Also, if the sequence is owned by a column, add an
+	 * ALTER SEQUENCE SET OWNED command for it.
 	 *
-	 * Add a 'SETVAL(seq, last_val, iscalled)' at restore-time iff we load
-	 * data. We do this for serial sequences too.
+	 * Add a 'SETVAL(seq, last_val, iscalled)' as part of a "data" dump.
 	 */
-
-	if (!dataOnly && !OidIsValid(tbinfo->owning_tab))
+	if (!dataOnly)
 	{
 		resetPQExpBuffer(delqry);
 
@@ -8166,32 +8135,57 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
 					 false, "SEQUENCE", query->data, delqry->data, NULL,
 					 tbinfo->dobj.dependencies, tbinfo->dobj.nDeps,
 					 NULL, NULL);
+
+		/*
+		 * If the sequence is owned by a table column, emit the ALTER for it
+		 * as a separate TOC entry immediately following the sequence's own
+		 * entry.  It's OK to do this rather than using full sorting logic,
+		 * because the dependency that tells us it's owned will have forced
+		 * the table to be created first.  We can't just include the ALTER
+		 * in the TOC entry because it will fail if we haven't reassigned
+		 * the sequence owner to match the table's owner.
+		 *
+		 * We need not schema-qualify the table reference because both
+		 * sequence and table must be in the same schema.
+		 */
+		if (OidIsValid(tbinfo->owning_tab))
+		{
+			TableInfo  *owning_tab = findTableByOid(tbinfo->owning_tab);
+
+			if (owning_tab)
+			{
+				resetPQExpBuffer(query);
+				appendPQExpBuffer(query, "ALTER SEQUENCE %s",
+								  fmtId(tbinfo->dobj.name));
+				appendPQExpBuffer(query, " OWNED BY %s",
+								  fmtId(owning_tab->dobj.name));
+				appendPQExpBuffer(query, ".%s;\n",
+								  fmtId(owning_tab->attnames[tbinfo->owning_col - 1]));
+
+				ArchiveEntry(fout, nilCatalogId, createDumpId(),
+							 tbinfo->dobj.name,
+							 tbinfo->dobj.namespace->dobj.name,
+							 NULL,
+							 tbinfo->rolname,
+							 false, "SEQUENCE OWNED BY", query->data, "", NULL,
+							 &(tbinfo->dobj.dumpId), 1,
+							 NULL, NULL);
+			}
+		}
+
+		/* Dump Sequence Comments */
+		resetPQExpBuffer(query);
+		appendPQExpBuffer(query, "SEQUENCE %s", fmtId(tbinfo->dobj.name));
+		dumpComment(fout, query->data,
+					tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
+					tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId);
 	}
 
 	if (!schemaOnly)
 	{
-		TableInfo  *owning_tab;
-
 		resetPQExpBuffer(query);
 		appendPQExpBuffer(query, "SELECT pg_catalog.setval(");
-
-		/*
-		 * If this is a SERIAL sequence, then use the pg_get_serial_sequence
-		 * function to avoid hard-coding the sequence name.  Note that this
-		 * implicitly assumes that the sequence and its owning table are in
-		 * the same schema, because we don't schema-qualify the reference.
-		 */
-		if (OidIsValid(tbinfo->owning_tab) &&
-			(owning_tab = findTableByOid(tbinfo->owning_tab)) != NULL)
-		{
-			appendPQExpBuffer(query, "pg_catalog.pg_get_serial_sequence(");
-			appendStringLiteralAH(query, fmtId(owning_tab->dobj.name), fout);
-			appendPQExpBuffer(query, ", ");
-			appendStringLiteralAH(query, owning_tab->attnames[tbinfo->owning_col - 1], fout);
-			appendPQExpBuffer(query, ")");
-		}
-		else
-			appendStringLiteralAH(query, fmtId(tbinfo->dobj.name), fout);
+		appendStringLiteralAH(query, fmtId(tbinfo->dobj.name), fout);
 		appendPQExpBuffer(query, ", %s, %s);\n",
 						  last, (called ? "true" : "false"));
 
@@ -8205,16 +8199,6 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
 					 NULL, NULL);
 	}
 
-	if (!dataOnly)
-	{
-		/* Dump Sequence Comments */
-		resetPQExpBuffer(query);
-		appendPQExpBuffer(query, "SEQUENCE %s", fmtId(tbinfo->dobj.name));
-		dumpComment(fout, query->data,
-					tbinfo->dobj.namespace->dobj.name, tbinfo->rolname,
-					tbinfo->dobj.catId, 0, tbinfo->dobj.dumpId);
-	}
-
 	PQclear(res);
 
 	destroyPQExpBuffer(query);
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index 3650ae50de2d19dd4c365c7d8016866c7a93edb8..65f5e84c4164e95969a3d6f6379f16c7d3a5a054 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -6,7 +6,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.128 2006/08/01 18:05:04 momjian Exp $
+ * $PostgreSQL: pgsql/src/bin/pg_dump/pg_dump.h,v 1.129 2006/08/21 00:57:25 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -185,7 +185,7 @@ typedef struct _tableInfo
 	bool		hasoids;		/* does it have OIDs? */
 	int			ncheck;			/* # of CHECK expressions */
 	int			ntrig;			/* # of triggers */
-	/* these two are set only if table is a SERIAL column's sequence: */
+	/* these two are set only if table is a sequence owned by a column: */
 	Oid			owning_tab;		/* OID of table owning sequence */
 	int			owning_col;		/* attr # of column owning sequence */
 
@@ -204,7 +204,6 @@ typedef struct _tableInfo
 	char	   *typstorage;		/* type storage scheme */
 	bool	   *attisdropped;	/* true if attr is dropped; don't dump it */
 	bool	   *attislocal;		/* true if attr has local definition */
-	bool	   *attisserial;	/* true if attr is serial or bigserial */
 
 	/*
 	 * Note: we need to store per-attribute notnull, default, and constraint
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index b27acf5f8599ba5574b1c7642f3edd8ec352a153..448f9e4ecfd22c3f1a3096f2f19621d61356765c 100644
--- a/src/include/catalog/catversion.h
+++ b/src/include/catalog/catversion.h
@@ -37,7 +37,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.351 2006/08/19 01:36:29 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.352 2006/08/21 00:57:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	200608181
+#define CATALOG_VERSION_NO	200608191
 
 #endif
diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h
index 04dc3ac7f3a908adbde70a758bbc0d640b347646..da7d7ac8e4eb1c830b77d64159cebd7f9225e774 100644
--- a/src/include/catalog/dependency.h
+++ b/src/include/catalog/dependency.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/catalog/dependency.h,v 1.26 2006/08/20 21:56:16 alvherre Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/dependency.h,v 1.27 2006/08/21 00:57:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -112,7 +112,7 @@ typedef struct ObjectAddress
 	int32		objectSubId;	/* Subitem within the object (column of table) */
 } ObjectAddress;
 
-/* expansible list of ObjectAddresses */
+/* expansible list of ObjectAddresses (private in dependency.c) */
 typedef struct ObjectAddresses ObjectAddresses;
 
 /*
@@ -192,7 +192,9 @@ extern long changeDependencyFor(Oid classId, Oid objectId,
 					Oid refClassId, Oid oldRefObjectId,
 					Oid newRefObjectId);
 
-extern bool objectIsInternalDependency(Oid classId, Oid objectId);
+extern bool sequenceIsOwned(Oid seqId, Oid *tableId, int32 *colId);
+
+extern void markSequenceUnowned(Oid seqId);
 
 /* in pg_shdepend.c */
 
diff --git a/src/include/nodes/makefuncs.h b/src/include/nodes/makefuncs.h
index 23cb0029c0da47716869ff840c4acc2dd293406b..3118cfb8f11ee1d650752d3782999902b02fe98b 100644
--- a/src/include/nodes/makefuncs.h
+++ b/src/include/nodes/makefuncs.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/makefuncs.h,v 1.55 2006/03/14 22:48:22 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/makefuncs.h,v 1.56 2006/08/21 00:57:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -62,4 +62,6 @@ extern TypeName *makeTypeNameFromOid(Oid typeid, int32 typmod);
 extern FuncExpr *makeFuncExpr(Oid funcid, Oid rettype,
 			 List *args, CoercionForm fformat);
 
+extern DefElem *makeDefElem(char *name, Node *arg);
+
 #endif   /* MAKEFUNC_H */
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 222f5d26cc3800c8ba37297382c52ad6e29345c9..a3ae58d17b3f4be437d72f360bdb8a83d0a081cc 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -7,7 +7,7 @@
  * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
  * Portions Copyright (c) 1994, Regents of the University of California
  *
- * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.323 2006/08/12 20:05:56 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.324 2006/08/21 00:57:26 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -393,10 +393,6 @@ typedef struct RangeFunction
  * 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
 {
@@ -409,7 +405,6 @@ typedef struct ColumnDef
 	Node	   *raw_default;	/* default value (untransformed parse tree) */
 	char	   *cooked_default; /* nodeToString representation */
 	List	   *constraints;	/* other constraints on column */
-	RangeVar   *support;		/* supporting relation, if any */
 } ColumnDef;
 
 /*
diff --git a/src/test/regress/expected/alter_table.out b/src/test/regress/expected/alter_table.out
index 3e1522879260dd4256a50d2012d90e5c4d4c408c..e664a1520b9d15f062b84cc2922cdc9727fe68d5 100644
--- a/src/test/regress/expected/alter_table.out
+++ b/src/test/regress/expected/alter_table.out
@@ -1443,6 +1443,6 @@ NOTICE:  drop cascades to function alter2.plus1(integer)
 NOTICE:  drop cascades to view alter2.v1
 NOTICE:  drop cascades to rule _RETURN on view alter2.v1
 NOTICE:  drop cascades to sequence alter2.t1_f1_seq
-NOTICE:  drop cascades to table alter2.t1 column f1
+NOTICE:  drop cascades to default for table alter2.t1 column f1
 NOTICE:  drop cascades to table alter2.t1
 NOTICE:  drop cascades to constraint t1_f2_check on table alter2.t1
diff --git a/src/test/regress/expected/dependency.out b/src/test/regress/expected/dependency.out
index 4781b5f9f29841abe3b82f175ffb75244dce8d61..ba65a351bc8c41cd74d2452d3739a2ee6499014d 100644
--- a/src/test/regress/expected/dependency.out
+++ b/src/test/regress/expected/dependency.out
@@ -58,7 +58,8 @@ REASSIGN OWNED BY regression_user1 TO regression_user0;
 ERROR:  permission denied to reassign objects
 -- this one is allowed
 DROP OWNED BY regression_user0;
-CREATE TABLE deptest1 ();
+CREATE TABLE deptest1 (f1 int unique);
+NOTICE:  CREATE TABLE / UNIQUE will create implicit index "deptest1_f1_key" for table "deptest1"
 GRANT ALL ON deptest1 TO regression_user1 WITH GRANT OPTION;
 SET SESSION AUTHORIZATION regression_user1;
 CREATE TABLE deptest (a serial primary key, b text);
@@ -90,6 +91,11 @@ SET SESSION AUTHORIZATION regression_user1;
 CREATE TABLE deptest (a serial primary key, b text);
 NOTICE:  CREATE TABLE will create implicit sequence "deptest_a_seq" for serial column "deptest.a"
 NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "deptest_pkey" for table "deptest"
+CREATE TABLE deptest2 (f1 int);
+-- make a serial column the hard way
+CREATE SEQUENCE ss1;
+ALTER TABLE deptest2 ALTER f1 SET DEFAULT nextval('ss1');
+ALTER SEQUENCE ss1 OWNED BY deptest2.f1;
 RESET SESSION AUTHORIZATION;
 REASSIGN OWNED BY regression_user1 TO regression_user2;
 \dt deptest
diff --git a/src/test/regress/expected/namespace.out b/src/test/regress/expected/namespace.out
index 646bb639798e777615b41273bd64b8382c10a3ad..a9f3e4ab92e7aac3754cc3795c27fe5183b1f36e 100644
--- a/src/test/regress/expected/namespace.out
+++ b/src/test/regress/expected/namespace.out
@@ -42,6 +42,7 @@ DROP SCHEMA test_schema_1 CASCADE;
 NOTICE:  drop cascades to view test_schema_1.abc_view
 NOTICE:  drop cascades to rule _RETURN on view test_schema_1.abc_view
 NOTICE:  drop cascades to table test_schema_1.abc
+NOTICE:  drop cascades to default for table test_schema_1.abc column a
 -- verify that the objects were dropped
 SELECT COUNT(*) FROM pg_class WHERE relnamespace =
     (SELECT oid FROM pg_namespace WHERE nspname = 'test_schema_1');
diff --git a/src/test/regress/expected/sequence.out b/src/test/regress/expected/sequence.out
index ca9ece284b080744eb5af3a39abd1500b89b6609..0576b575ee680a7b559ae0f494183888f0444821 100644
--- a/src/test/regress/expected/sequence.out
+++ b/src/test/regress/expected/sequence.out
@@ -130,8 +130,9 @@ CREATE TEMP TABLE t1 (
 NOTICE:  CREATE TABLE will create implicit sequence "t1_f1_seq" for serial column "t1.f1"
 -- Both drops should fail, but with different error messages:
 DROP SEQUENCE t1_f1_seq;
-ERROR:  cannot drop sequence t1_f1_seq because table t1 column f1 requires it
-HINT:  You may drop table t1 column f1 instead.
+NOTICE:  default for table t1 column f1 depends on sequence t1_f1_seq
+ERROR:  cannot drop sequence t1_f1_seq because other objects depend on it
+HINT:  Use DROP ... CASCADE to drop the dependent objects too.
 DROP SEQUENCE myseq2;
 NOTICE:  default for table t1 column f2 depends on sequence myseq2
 ERROR:  cannot drop sequence myseq2 because other objects depend on it
diff --git a/src/test/regress/sql/dependency.sql b/src/test/regress/sql/dependency.sql
index c1b189f527894d77e32631710ec9b9d01dc90a75..6f8e0e84d51929dd7def53f236ef29cea14b5575 100644
--- a/src/test/regress/sql/dependency.sql
+++ b/src/test/regress/sql/dependency.sql
@@ -57,7 +57,7 @@ REASSIGN OWNED BY regression_user1 TO regression_user0;
 -- this one is allowed
 DROP OWNED BY regression_user0;
 
-CREATE TABLE deptest1 ();
+CREATE TABLE deptest1 (f1 int unique);
 GRANT ALL ON deptest1 TO regression_user1 WITH GRANT OPTION;
 
 SET SESSION AUTHORIZATION regression_user1;
@@ -77,10 +77,17 @@ GRANT ALL ON deptest1 TO regression_user1;
 
 SET SESSION AUTHORIZATION regression_user1;
 CREATE TABLE deptest (a serial primary key, b text);
+
+CREATE TABLE deptest2 (f1 int);
+-- make a serial column the hard way
+CREATE SEQUENCE ss1;
+ALTER TABLE deptest2 ALTER f1 SET DEFAULT nextval('ss1');
+ALTER SEQUENCE ss1 OWNED BY deptest2.f1;
 RESET SESSION AUTHORIZATION;
 
 REASSIGN OWNED BY regression_user1 TO regression_user2;
 \dt deptest
+
 -- doesn't work: grant still exists
 DROP USER regression_user1;
 DROP OWNED BY regression_user1;