diff --git a/doc/src/sgml/bki.sgml b/doc/src/sgml/bki.sgml
index a08119983a2eb230c31dfb0fb3fc5b8b5fad1b73..ca839e8a40e390d8a20bdb7dfa63cbb4f5ad66d9 100644
--- a/doc/src/sgml/bki.sgml
+++ b/doc/src/sgml/bki.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/bki.sgml,v 1.17 2006/03/10 19:10:46 momjian Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/bki.sgml,v 1.18 2006/07/31 01:16:36 tgl Exp $ -->
 
 <chapter id="bki">
  <title><acronym>BKI</acronym> Backend Interface</title>
@@ -209,6 +209,28 @@
     </listitem>
    </varlistentry>
 
+   <varlistentry>
+    <term>
+     <literal>declare toast</>
+     <replaceable class="parameter">toasttableoid</replaceable>
+     <replaceable class="parameter">toastindexoid</replaceable>
+     <literal>on</> <replaceable class="parameter">tablename</replaceable>
+    </term>
+
+    <listitem>
+     <para>
+      Create a TOAST table for the table named
+      <replaceable class="parameter">tablename</replaceable>.
+      The TOAST table is assigned OID
+      <replaceable class="parameter">toasttableoid</replaceable>
+      and its index is assigned OID
+      <replaceable class="parameter">toastindexoid</replaceable>.
+      As with <literal>declare index</>, filling of the index
+      is postponed.
+     </para>
+    </listitem>
+   </varlistentry>
+
    <varlistentry>
     <term><literal>build indices</></term>
 
@@ -235,6 +257,12 @@
    the created table for data insertion.
   </para>
 
+  <para>
+   Also, the <literal>declare index</> and <literal>declare toast</>
+   commands cannot be used until the system catalogs they need have been
+   created and filled in.
+  </para>
+
   <para>
    Thus, the structure of the <filename>postgres.bki</filename> file has to
    be:
@@ -286,7 +314,7 @@
     </listitem>
     <listitem>
      <para>
-      Define indexes.
+      Define indexes and toast tables.
      </para>
     </listitem>
     <listitem>
diff --git a/doc/src/sgml/keywords.sgml b/doc/src/sgml/keywords.sgml
index 71295125c4f4d9e601dea3d1792b68f6d9d7f5e7..cf55b830485adda16d4533aa1b08f3fda2f7a2d5 100644
--- a/doc/src/sgml/keywords.sgml
+++ b/doc/src/sgml/keywords.sgml
@@ -1,4 +1,4 @@
-<!-- $PostgreSQL: pgsql/doc/src/sgml/keywords.sgml,v 2.16 2005/10/12 09:45:29 petere Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/keywords.sgml,v 2.17 2006/07/31 01:16:36 tgl Exp $ -->
 
 <appendix id="sql-keywords-appendix">
  <title><acronym>SQL</acronym> Key Words</title>
@@ -4013,13 +4013,6 @@
     <entry>reserved</entry>
     <entry>reserved</entry>
    </row>
-   <row>
-    <entry><token>TOAST</token></entry>
-    <entry>non-reserved</entry>
-    <entry></entry>
-    <entry></entry>
-    <entry></entry>
-   </row>
    <row>
     <entry><token>TOP_LEVEL_COUNT</token></entry>
     <entry></entry>
diff --git a/src/backend/bootstrap/bootparse.y b/src/backend/bootstrap/bootparse.y
index 9bb8f01b1e44004285bb51431e9dfc5bc31ae2bc..b25ea11a0b52ac08cb0633bebe71c980fdbeff0f 100644
--- a/src/backend/bootstrap/bootparse.y
+++ b/src/backend/bootstrap/bootparse.y
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/bootstrap/bootparse.y,v 1.82 2006/07/03 22:45:37 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/bootstrap/bootparse.y,v 1.83 2006/07/31 01:16:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -33,6 +33,7 @@
 #include "catalog/pg_class.h"
 #include "catalog/pg_namespace.h"
 #include "catalog/pg_tablespace.h"
+#include "catalog/toasting.h"
 #include "commands/defrem.h"
 #include "miscadmin.h"
 #include "nodes/makefuncs.h"
@@ -99,7 +100,7 @@ int num_columns_read = 0;
 
 %token <ival> CONST_P ID
 %token OPEN XCLOSE XCREATE INSERT_TUPLE
-%token XDECLARE INDEX ON USING XBUILD INDICES UNIQUE
+%token XDECLARE INDEX ON USING XBUILD INDICES UNIQUE XTOAST
 %token COMMA EQUALS LPAREN RPAREN
 %token OBJ_ID XBOOTSTRAP XSHARED_RELATION XWITHOUT_OIDS NULLVAL
 %start TopLevel
@@ -126,6 +127,7 @@ Boot_Query :
 		| Boot_InsertStmt
 		| Boot_DeclareIndexStmt
 		| Boot_DeclareUniqueIndexStmt
+		| Boot_DeclareToastStmt
 		| Boot_BuildIndsStmt
 		;
 
@@ -278,6 +280,16 @@ Boot_DeclareUniqueIndexStmt:
 				}
 		;
 
+Boot_DeclareToastStmt:
+		  XDECLARE XTOAST oidspec oidspec ON boot_ident
+				{
+					do_start();
+
+					BootstrapToastTable(LexIDStr($6), $3, $4);
+					do_end();
+				}
+		;
+
 Boot_BuildIndsStmt:
 		  XBUILD INDICES
 				{
diff --git a/src/backend/bootstrap/bootscanner.l b/src/backend/bootstrap/bootscanner.l
index f75d79a8d02f1fdf7fa61fcfe47023dda6e3c8a3..b5ed234a168f79de813c56de90066ed74060a66b 100644
--- a/src/backend/bootstrap/bootscanner.l
+++ b/src/backend/bootstrap/bootscanner.l
@@ -9,7 +9,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/bootstrap/bootscanner.l,v 1.42 2006/03/07 01:03:12 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/bootstrap/bootscanner.l,v 1.43 2006/07/31 01:16:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -99,6 +99,7 @@ insert			{ return(INSERT_TUPLE); }
 "index"			{ return(INDEX); }
 "on"			{ return(ON); }
 "using"			{ return(USING); }
+"toast"			{ return(XTOAST); }
 
 {arrayid}		{
 					yylval.ival = EnterString(MapArrayTypeName((char*)yytext));
diff --git a/src/backend/bootstrap/bootstrap.c b/src/backend/bootstrap/bootstrap.c
index 150c29db3f63735b5f729cbfd6c115d2e1c42886..9399b6d052bbb38b0fcd8504c4d75760be0f001c 100644
--- a/src/backend/bootstrap/bootstrap.c
+++ b/src/backend/bootstrap/bootstrap.c
@@ -8,7 +8,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.221 2006/07/29 03:02:55 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/bootstrap/bootstrap.c,v 1.222 2006/07/31 01:16:36 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -1242,7 +1242,7 @@ build_indices(void)
 		heap = heap_open(ILHead->il_heap, NoLock);
 		ind = index_open(ILHead->il_ind);
 
-		index_build(heap, ind, ILHead->il_info, false, false);
+		index_build(heap, ind, ILHead->il_info, false);
 
 		index_close(ind);
 		heap_close(heap, NoLock);
diff --git a/src/backend/catalog/Makefile b/src/backend/catalog/Makefile
index 635b553dca911f19d4d99796346f774a7972d794..2e2d885f894da3716cefb57aa372ce1884aeb694 100644
--- a/src/backend/catalog/Makefile
+++ b/src/backend/catalog/Makefile
@@ -2,7 +2,7 @@
 #
 # Makefile for backend/catalog
 #
-# $PostgreSQL: pgsql/src/backend/catalog/Makefile,v 1.59 2006/02/12 03:22:17 momjian Exp $
+# $PostgreSQL: pgsql/src/backend/catalog/Makefile,v 1.60 2006/07/31 01:16:36 tgl Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -13,7 +13,7 @@ include $(top_builddir)/src/Makefile.global
 OBJS = catalog.o dependency.o heap.o index.o indexing.o namespace.o aclchk.o \
        pg_aggregate.o pg_constraint.o pg_conversion.o pg_depend.o \
        pg_largeobject.o pg_namespace.o pg_operator.o pg_proc.o pg_shdepend.o \
-       pg_type.o
+       pg_type.o toasting.o
 
 BKIFILES = postgres.bki postgres.description postgres.shdescription
 
@@ -24,7 +24,7 @@ SUBSYS.o: $(OBJS)
 
 # Note: there are some undocumented dependencies on the ordering in which
 # the catalog header files are assembled into postgres.bki.  In particular,
-# indexing.h had better be last.
+# indexing.h had better be last, and toasting.h just before it.
 
 POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/,\
 	pg_proc.h pg_type.h pg_attribute.h pg_class.h pg_autovacuum.h \
@@ -35,7 +35,7 @@ POSTGRES_BKI_SRCS := $(addprefix $(top_srcdir)/src/include/catalog/,\
 	pg_namespace.h pg_conversion.h pg_depend.h \
 	pg_database.h pg_tablespace.h pg_pltemplate.h \
 	pg_authid.h pg_auth_members.h pg_shdepend.h pg_shdescription.h \
-	indexing.h \
+	toasting.h indexing.h \
     )
 
 pg_includes := $(sort -I$(top_srcdir)/src/include -I$(top_builddir)/src/include)
diff --git a/src/backend/catalog/README b/src/backend/catalog/README
index 3f002add5a01e775c5b4364e843726b576989cd6..3cbcc3d45eef62b58ade01ea699f93a5f4a518b8 100644
--- a/src/backend/catalog/README
+++ b/src/backend/catalog/README
@@ -1,4 +1,4 @@
-$PostgreSQL: pgsql/src/backend/catalog/README,v 1.9 2005/04/14 01:38:15 tgl Exp $
+$PostgreSQL: pgsql/src/backend/catalog/README,v 1.10 2006/07/31 01:16:36 tgl Exp $
 
 This directory contains .c files that manipulate the system catalogs;
 src/include/catalog contains the .h files that define the structure
@@ -73,8 +73,9 @@ heap_create_with_catalog process, because it needs these tables to exist
 already.  The list of files this currently includes is:
 	pg_proc.h pg_type.h pg_attribute.h pg_class.h
 Also, indexing.h must be last, since the indexes can't be created until all
-the tables are in place.  There are reputedly some other order dependencies
-in the .bki list, too.
+the tables are in place, and toasting.h should probably be next-to-last
+(or at least after all the tables that need toast tables).  There are
+reputedly some other order dependencies in the .bki list, too.
 
 -----------------------------------------------------------------
 
diff --git a/src/backend/catalog/genbki.sh b/src/backend/catalog/genbki.sh
index 9dd4a1b7bb71e7b072b9eabd039370335a25a449..e640deebaac049e77f1b80325a286e5863b38b51 100644
--- a/src/backend/catalog/genbki.sh
+++ b/src/backend/catalog/genbki.sh
@@ -11,7 +11,7 @@
 #
 #
 # IDENTIFICATION
-#    $PostgreSQL: pgsql/src/backend/catalog/genbki.sh,v 1.39 2006/03/05 15:58:22 momjian Exp $
+#    $PostgreSQL: pgsql/src/backend/catalog/genbki.sh,v 1.40 2006/07/31 01:16:36 tgl Exp $
 #
 # NOTES
 #    non-essential whitespace is removed from the generated file.
@@ -276,6 +276,28 @@ comment_level > 0 { next; }
 	print "declare unique index " iname " " oid " " data
 }
 
+/^DECLARE_TOAST\(/ {
+# ----
+#  end any prior catalog data insertions before starting a define toast
+# ----
+	if (reln_open == 1) {
+		print "close " catalog;
+		reln_open = 0;
+	}
+
+	data = substr($0, 15, length($0) - 15);
+	pos = index(data, ",");
+	tname = substr(data, 1, pos-1);
+	data = substr(data, pos+1, length(data)-pos);
+	pos = index(data, ",");
+	toastoid = substr(data, 1, pos-1);
+	data = substr(data, pos+1, length(data)-pos);
+	# previous commands already removed the trailing );
+	indexoid = data;
+
+	print "declare toast " toastoid " " indexoid " on " tname
+}
+
 /^BUILD_INDICES/	{ print "build indices"; }
 	
 # ----------------
diff --git a/src/backend/catalog/heap.c b/src/backend/catalog/heap.c
index b6e562c110f88a8082357448430ab489d64f999e..361f68008772fe6968240985b9af73498ee4ae00 100644
--- a/src/backend/catalog/heap.c
+++ b/src/backend/catalog/heap.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.309 2006/07/14 14:52:17 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/catalog/heap.c,v 1.310 2006/07/31 01:16:36 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -2009,8 +2009,8 @@ RelationTruncateIndexes(Oid heapId)
 		RelationTruncate(currentIndex, 0);
 
 		/* Initialize the index and rebuild */
-		/* Note: we do not need to re-establish pkey or toast settings */
-		index_build(heapRelation, currentIndex, indexInfo, false, false);
+		/* Note: we do not need to re-establish pkey setting */
+		index_build(heapRelation, currentIndex, indexInfo, false);
 
 		/* We're done with this index */
 		index_close(currentIndex);
diff --git a/src/backend/catalog/index.c b/src/backend/catalog/index.c
index 829fd5e4fba2a32e428d6756f695912cae701cb6..092c9dcda1048fa4aa7df7bd642b0f5821cb1b06 100644
--- a/src/backend/catalog/index.c
+++ b/src/backend/catalog/index.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.270 2006/07/30 02:07:18 alvherre Exp $
+ *	  $PostgreSQL: pgsql/src/backend/catalog/index.c,v 1.271 2006/07/31 01:16:36 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -424,7 +424,6 @@ UpdateIndexRelation(Oid indexoid,
  * classObjectId: array of index opclass OIDs, one per index column
  * reloptions: AM-specific options
  * isprimary: index is a PRIMARY KEY
- * istoast: index is a toast table's index
  * isconstraint: index is owned by a PRIMARY KEY or UNIQUE constraint
  * allow_system_table_mods: allow table to be a system catalog
  * skip_build: true to skip the index_build() step for the moment; caller
@@ -442,7 +441,6 @@ index_create(Oid heapRelationId,
 			 Oid *classObjectId,
 			 Datum reloptions,
 			 bool isprimary,
-			 bool istoast,
 			 bool isconstraint,
 			 bool allow_system_table_mods,
 			 bool skip_build)
@@ -747,8 +745,7 @@ index_create(Oid heapRelationId,
 	}
 	else
 	{
-		index_build(heapRelation, indexRelation, indexInfo,
-					isprimary, istoast);
+		index_build(heapRelation, indexRelation, indexInfo, isprimary);
 	}
 
 	/*
@@ -1241,8 +1238,8 @@ setNewRelfilenode(Relation relation)
  * entries of the index and heap relation as needed, using statistics
  * returned by ambuild as well as data passed by the caller.
  *
- * Note: when reindexing an existing index, isprimary and istoast can be
- * false; the index is already properly marked and need not be re-marked.
+ * Note: when reindexing an existing index, isprimary can be false;
+ * the index is already properly marked and need not be re-marked.
  *
  * Note: before Postgres 8.2, the passed-in heap and index Relations
  * were automatically closed by this routine.  This is no longer the case.
@@ -1252,8 +1249,7 @@ void
 index_build(Relation heapRelation,
 			Relation indexRelation,
 			IndexInfo *indexInfo,
-			bool isprimary,
-			bool istoast)
+			bool isprimary)
 {
 	RegProcedure procedure;
 	IndexBuildResult *stats;
@@ -1283,7 +1279,8 @@ index_build(Relation heapRelation,
 	index_update_stats(heapRelation,
 					   true,
 					   isprimary,
-					   istoast ? RelationGetRelid(indexRelation) : InvalidOid,
+					   (heapRelation->rd_rel->relkind == RELKIND_TOASTVALUE) ?
+					   RelationGetRelid(indexRelation) : InvalidOid,
 					   stats->heap_tuples);
 
 	index_update_stats(indexRelation,
@@ -1618,8 +1615,8 @@ reindex_index(Oid indexId)
 		}
 
 		/* Initialize the index and rebuild */
-		/* Note: we do not need to re-establish pkey or toast settings */
-		index_build(heapRelation, iRel, indexInfo, false, false);
+		/* Note: we do not need to re-establish pkey setting */
+		index_build(heapRelation, iRel, indexInfo, false);
 	}
 	PG_CATCH();
 	{
diff --git a/src/backend/catalog/toasting.c b/src/backend/catalog/toasting.c
new file mode 100644
index 0000000000000000000000000000000000000000..eebe602ee07777117f764e56e12dd3fb4bb994e7
--- /dev/null
+++ b/src/backend/catalog/toasting.c
@@ -0,0 +1,339 @@
+/*-------------------------------------------------------------------------
+ *
+ * toasting.c
+ *	  This file contains routines to support creation of toast tables
+ *
+ *
+ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * IDENTIFICATION
+ *	  $PostgreSQL: pgsql/src/backend/catalog/toasting.c,v 1.1 2006/07/31 01:16:37 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/heapam.h"
+#include "access/tuptoaster.h"
+#include "access/xact.h"
+#include "catalog/dependency.h"
+#include "catalog/heap.h"
+#include "catalog/index.h"
+#include "catalog/indexing.h"
+#include "catalog/pg_namespace.h"
+#include "catalog/pg_opclass.h"
+#include "catalog/pg_type.h"
+#include "catalog/toasting.h"
+#include "miscadmin.h"
+#include "nodes/makefuncs.h"
+#include "utils/builtins.h"
+#include "utils/syscache.h"
+
+
+static bool create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid);
+static bool needs_toast_table(Relation rel);
+
+
+/*
+ * AlterTableCreateToastTable
+ *		If the table needs a toast table, and doesn't already have one,
+ *		then create a toast table for it.
+ *
+ * We expect the caller to have verified that the relation is a table and have
+ * already done any necessary permission checks.  Callers expect this function
+ * to end with CommandCounterIncrement if it makes any changes.
+ */
+void
+AlterTableCreateToastTable(Oid relOid)
+{
+	Relation	rel;
+
+	/*
+	 * Grab an exclusive lock on the target table, which we will NOT release
+	 * until end of transaction.  (This is probably redundant in all present
+	 * uses...)
+	 */
+	rel = heap_open(relOid, AccessExclusiveLock);
+
+	/* create_toast_table does all the work */
+	(void) create_toast_table(rel, InvalidOid, InvalidOid);
+
+	heap_close(rel, NoLock);
+}
+
+/*
+ * Create a toast table during bootstrap
+ *
+ * Here we need to prespecify the OIDs of the toast table and its index
+ */
+void
+BootstrapToastTable(char *relName, Oid toastOid, Oid toastIndexOid)
+{
+	Relation rel;
+
+	rel = heap_openrv(makeRangeVar(NULL, relName), AccessExclusiveLock);
+
+	/* Note: during bootstrap may see uncataloged relation */
+	if (rel->rd_rel->relkind != RELKIND_RELATION &&
+		rel->rd_rel->relkind != RELKIND_UNCATALOGED)
+		ereport(ERROR,
+				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+				 errmsg("\"%s\" is not a table",
+						relName)));
+
+	/* create_toast_table does all the work */
+	if (!create_toast_table(rel, toastOid, toastIndexOid))
+		elog(ERROR, "\"%s\" does not require a toast table",
+			 relName);
+
+	heap_close(rel, NoLock);
+}
+
+
+/*
+ * create_toast_table --- internal workhorse
+ *
+ * rel is already opened and exclusive-locked
+ * toastOid and toastIndexOid are normally InvalidOid, but during
+ * bootstrap they can be nonzero to specify hand-assigned OIDs
+ */
+static bool
+create_toast_table(Relation rel, Oid toastOid, Oid toastIndexOid)
+{
+	Oid			relOid = RelationGetRelid(rel);
+	HeapTuple	reltup;
+	TupleDesc	tupdesc;
+	bool		shared_relation;
+	Relation	class_rel;
+	Oid			toast_relid;
+	Oid			toast_idxid;
+	char		toast_relname[NAMEDATALEN];
+	char		toast_idxname[NAMEDATALEN];
+	IndexInfo  *indexInfo;
+	Oid			classObjectId[2];
+	ObjectAddress baseobject,
+				toastobject;
+
+	/*
+	 * Toast table is shared if and only if its parent is.
+	 *
+	 * We cannot allow toasting a shared relation after initdb (because
+	 * there's no way to mark it toasted in other databases' pg_class).
+	 */
+	shared_relation = rel->rd_rel->relisshared;
+	if (shared_relation && !IsBootstrapProcessingMode())
+		ereport(ERROR,
+				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+				 errmsg("shared tables cannot be toasted after initdb")));
+
+	/*
+	 * Is it already toasted?
+	 */
+	if (rel->rd_rel->reltoastrelid != InvalidOid)
+		return false;
+
+	/*
+	 * Check to see whether the table actually needs a TOAST table.
+	 */
+	if (!needs_toast_table(rel))
+		return false;
+
+	/*
+	 * Create the toast table and its index
+	 */
+	snprintf(toast_relname, sizeof(toast_relname),
+			 "pg_toast_%u", relOid);
+	snprintf(toast_idxname, sizeof(toast_idxname),
+			 "pg_toast_%u_index", relOid);
+
+	/* this is pretty painful...  need a tuple descriptor */
+	tupdesc = CreateTemplateTupleDesc(3, false);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 1,
+					   "chunk_id",
+					   OIDOID,
+					   -1, 0);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 2,
+					   "chunk_seq",
+					   INT4OID,
+					   -1, 0);
+	TupleDescInitEntry(tupdesc, (AttrNumber) 3,
+					   "chunk_data",
+					   BYTEAOID,
+					   -1, 0);
+
+	/*
+	 * Ensure that the toast table doesn't itself get toasted, or we'll be
+	 * toast :-(.  This is essential for chunk_data because type bytea is
+	 * toastable; hit the other two just to be sure.
+	 */
+	tupdesc->attrs[0]->attstorage = 'p';
+	tupdesc->attrs[1]->attstorage = 'p';
+	tupdesc->attrs[2]->attstorage = 'p';
+
+	/*
+	 * Note: the toast relation is placed in the regular pg_toast namespace
+	 * even if its master relation is a temp table.  There cannot be any
+	 * naming collision, and the toast rel will be destroyed when its master
+	 * is, so there's no need to handle the toast rel as temp.
+	 *
+	 * XXX would it make sense to apply the master's reloptions to the toast
+	 * table?
+	 */
+	toast_relid = heap_create_with_catalog(toast_relname,
+										   PG_TOAST_NAMESPACE,
+										   rel->rd_rel->reltablespace,
+										   toastOid,
+										   rel->rd_rel->relowner,
+										   tupdesc,
+										   RELKIND_TOASTVALUE,
+										   shared_relation,
+										   true,
+										   0,
+										   ONCOMMIT_NOOP,
+										   (Datum) 0,
+										   true);
+
+	/* make the toast relation visible, else index creation will fail */
+	CommandCounterIncrement();
+
+	/*
+	 * Create unique index on chunk_id, chunk_seq.
+	 *
+	 * NOTE: the normal TOAST access routines could actually function with a
+	 * single-column index on chunk_id only. However, the slice access
+	 * routines use both columns for faster access to an individual chunk. In
+	 * addition, we want it to be unique as a check against the possibility of
+	 * duplicate TOAST chunk OIDs. The index might also be a little more
+	 * efficient this way, since btree isn't all that happy with large numbers
+	 * of equal keys.
+	 */
+
+	indexInfo = makeNode(IndexInfo);
+	indexInfo->ii_NumIndexAttrs = 2;
+	indexInfo->ii_KeyAttrNumbers[0] = 1;
+	indexInfo->ii_KeyAttrNumbers[1] = 2;
+	indexInfo->ii_Expressions = NIL;
+	indexInfo->ii_ExpressionsState = NIL;
+	indexInfo->ii_Predicate = NIL;
+	indexInfo->ii_PredicateState = NIL;
+	indexInfo->ii_Unique = true;
+
+	classObjectId[0] = OID_BTREE_OPS_OID;
+	classObjectId[1] = INT4_BTREE_OPS_OID;
+
+	toast_idxid = index_create(toast_relid, toast_idxname, toastIndexOid,
+							   indexInfo,
+							   BTREE_AM_OID,
+							   rel->rd_rel->reltablespace,
+							   classObjectId, (Datum) 0,
+							   true, false, true, false);
+
+	/*
+	 * Store the toast table's OID in the parent relation's pg_class row
+	 */
+	class_rel = heap_open(RelationRelationId, RowExclusiveLock);
+
+	reltup = SearchSysCacheCopy(RELOID,
+								ObjectIdGetDatum(relOid),
+								0, 0, 0);
+	if (!HeapTupleIsValid(reltup))
+		elog(ERROR, "cache lookup failed for relation %u", relOid);
+
+	((Form_pg_class) GETSTRUCT(reltup))->reltoastrelid = toast_relid;
+
+	if (!IsBootstrapProcessingMode())
+	{
+		/* normal case, use a transactional update */
+		simple_heap_update(class_rel, &reltup->t_self, reltup);
+
+		/* Keep catalog indexes current */
+		CatalogUpdateIndexes(class_rel, reltup);
+	}
+	else
+	{
+		/* While bootstrapping, we cannot UPDATE, so overwrite in-place */
+		heap_inplace_update(class_rel, reltup);
+	}
+
+	heap_freetuple(reltup);
+
+	heap_close(class_rel, RowExclusiveLock);
+
+	/*
+	 * Register dependency from the toast table to the master, so that the
+	 * toast table will be deleted if the master is.  Skip this in bootstrap
+	 * mode.
+	 */
+	if (!IsBootstrapProcessingMode())
+	{
+		baseobject.classId = RelationRelationId;
+		baseobject.objectId = relOid;
+		baseobject.objectSubId = 0;
+		toastobject.classId = RelationRelationId;
+		toastobject.objectId = toast_relid;
+		toastobject.objectSubId = 0;
+
+		recordDependencyOn(&toastobject, &baseobject, DEPENDENCY_INTERNAL);
+	}
+
+	/*
+	 * Make changes visible
+	 */
+	CommandCounterIncrement();
+
+	return true;
+}
+
+/*
+ * Check to see whether the table needs a TOAST table.	It does only if
+ * (1) there are any toastable attributes, and (2) the maximum length
+ * of a tuple could exceed TOAST_TUPLE_THRESHOLD.  (We don't want to
+ * create a toast table for something like "f1 varchar(20)".)
+ */
+static bool
+needs_toast_table(Relation rel)
+{
+	int32		data_length = 0;
+	bool		maxlength_unknown = false;
+	bool		has_toastable_attrs = false;
+	TupleDesc	tupdesc;
+	Form_pg_attribute *att;
+	int32		tuple_length;
+	int			i;
+
+	tupdesc = rel->rd_att;
+	att = tupdesc->attrs;
+
+	for (i = 0; i < tupdesc->natts; i++)
+	{
+		if (att[i]->attisdropped)
+			continue;
+		data_length = att_align(data_length, att[i]->attalign);
+		if (att[i]->attlen > 0)
+		{
+			/* Fixed-length types are never toastable */
+			data_length += att[i]->attlen;
+		}
+		else
+		{
+			int32		maxlen = type_maximum_size(att[i]->atttypid,
+												   att[i]->atttypmod);
+
+			if (maxlen < 0)
+				maxlength_unknown = true;
+			else
+				data_length += maxlen;
+			if (att[i]->attstorage != 'p')
+				has_toastable_attrs = true;
+		}
+	}
+	if (!has_toastable_attrs)
+		return false;			/* nothing to toast? */
+	if (maxlength_unknown)
+		return true;			/* any unlimited-length attrs? */
+	tuple_length = MAXALIGN(offsetof(HeapTupleHeaderData, t_bits) +
+							BITMAPLEN(tupdesc->natts)) +
+		MAXALIGN(data_length);
+	return (tuple_length > TOAST_TUPLE_THRESHOLD);
+}
diff --git a/src/backend/commands/cluster.c b/src/backend/commands/cluster.c
index 37e8c63e9ae181ff24fd4b331dda09794bd753ff..e16afa0559d7e67ec8e0b9c5c9a6a9945bea49c2 100644
--- a/src/backend/commands/cluster.c
+++ b/src/backend/commands/cluster.c
@@ -11,7 +11,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.150 2006/07/13 16:49:14 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/cluster.c,v 1.151 2006/07/31 01:16:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -26,8 +26,8 @@
 #include "catalog/index.h"
 #include "catalog/indexing.h"
 #include "catalog/namespace.h"
+#include "catalog/toasting.h"
 #include "commands/cluster.h"
-#include "commands/tablecmds.h"
 #include "miscadmin.h"
 #include "utils/acl.h"
 #include "utils/fmgroids.h"
@@ -620,7 +620,7 @@ make_new_heap(Oid OIDOldHeap, const char *NewName, Oid NewTableSpace)
 	 * AlterTableCreateToastTable ends with CommandCounterIncrement(), so that
 	 * the TOAST table will be visible for insertion.
 	 */
-	AlterTableCreateToastTable(OIDNewHeap, true);
+	AlterTableCreateToastTable(OIDNewHeap);
 
 	heap_close(OldHeap, NoLock);
 
diff --git a/src/backend/commands/indexcmds.c b/src/backend/commands/indexcmds.c
index 939d18e2ce37eaa5ac855b4249531f55f7284ec2..97a5a72199ef2166ba57855f532f5ebdf5a5acde 100644
--- a/src/backend/commands/indexcmds.c
+++ b/src/backend/commands/indexcmds.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.145 2006/07/13 16:49:14 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/indexcmds.c,v 1.146 2006/07/31 01:16:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -412,7 +412,7 @@ DefineIndex(RangeVar *heapRelation,
 
 	index_create(relationId, indexRelationName, indexRelationId,
 				 indexInfo, accessMethodId, tablespaceId, classObjectId,
-				 reloptions, primary, false, isconstraint,
+				 reloptions, primary, isconstraint,
 				 allowSystemTableMods, skip_build);
 }
 
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index a33f721b1bd20c537b74aae5ae079e3c3df11eef..53382ff3d470308d9373ef53215a884ece1b3f81 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.196 2006/07/14 14:52:18 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/commands/tablecmds.c,v 1.197 2006/07/31 01:16:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -17,7 +17,6 @@
 #include "access/genam.h"
 #include "access/heapam.h"
 #include "access/reloptions.h"
-#include "access/tuptoaster.h"
 #include "access/xact.h"
 #include "catalog/catalog.h"
 #include "catalog/dependency.h"
@@ -29,9 +28,9 @@
 #include "catalog/pg_depend.h"
 #include "catalog/pg_inherits.h"
 #include "catalog/pg_namespace.h"
-#include "catalog/pg_opclass.h"
 #include "catalog/pg_trigger.h"
 #include "catalog/pg_type.h"
+#include "catalog/toasting.h"
 #include "commands/cluster.h"
 #include "commands/defrem.h"
 #include "commands/tablecmds.h"
@@ -170,7 +169,6 @@ static void StoreCatalogInheritance1(Oid relationId, Oid parentOid,
 					int16 seqNumber, Relation catalogRelation);
 static int	findAttrByName(const char *attributeName, List *schema);
 static void setRelhassubclassInRelation(Oid relationId, bool relhassubclass);
-static bool needs_toast_table(Relation rel);
 static void AlterIndexNamespaces(Relation classRel, Relation rel,
 					 Oid oldNspOid, Oid newNspOid);
 static void AlterSeqNamespaces(Relation classRel, Relation rel,
@@ -2073,12 +2071,6 @@ ATPrepCmd(List **wqueue, Relation rel, AlterTableCmd *cmd,
 			ATPrepAlterColumnType(wqueue, tab, rel, recurse, recursing, cmd);
 			pass = AT_PASS_ALTER_TYPE;
 			break;
-		case AT_ToastTable:		/* CREATE TOAST TABLE */
-			ATSimplePermissions(rel, false);
-			/* This command never recurses */
-			/* No command-specific prep needed */
-			pass = AT_PASS_MISC;
-			break;
 		case AT_ChangeOwner:	/* ALTER OWNER */
 			/* This command never recurses */
 			/* No command-specific prep needed */
@@ -2196,8 +2188,8 @@ ATRewriteCatalogs(List **wqueue)
 	}
 
 	/*
-	 * Do an implicit CREATE TOAST TABLE if we executed any subcommands that
-	 * might have added a column or changed column storage.
+	 * Check to see if a toast table must be added, if we executed any
+	 * subcommands that might have added a column or changed column storage.
 	 */
 	foreach(ltab, *wqueue)
 	{
@@ -2207,7 +2199,7 @@ ATRewriteCatalogs(List **wqueue)
 			(tab->subcmds[AT_PASS_ADD_COL] ||
 			 tab->subcmds[AT_PASS_ALTER_TYPE] ||
 			 tab->subcmds[AT_PASS_COL_ATTRS]))
-			AlterTableCreateToastTable(tab->relid, true);
+			AlterTableCreateToastTable(tab->relid);
 	}
 }
 
@@ -2261,9 +2253,6 @@ ATExecCmd(AlteredTableInfo *tab, Relation rel, AlterTableCmd *cmd)
 		case AT_AlterColumnType:		/* ALTER COLUMN TYPE */
 			ATExecAlterColumnType(tab, rel, cmd->name, (TypeName *) cmd->def);
 			break;
-		case AT_ToastTable:		/* CREATE TOAST TABLE */
-			AlterTableCreateToastTable(RelationGetRelid(rel), false);
-			break;
 		case AT_ChangeOwner:	/* ALTER OWNER */
 			ATExecChangeOwner(RelationGetRelid(rel),
 							  get_roleid_checked(cmd->name),
@@ -6541,275 +6530,6 @@ ATExecDropInherits(Relation rel, RangeVar *parent)
 }
 
 
-/*
- * ALTER TABLE CREATE TOAST TABLE
- *
- * Note: this is also invoked from outside this module; in such cases we
- * expect the caller to have verified that the relation is a table and we
- * have all the right permissions.	Callers expect this function
- * to end with CommandCounterIncrement if it makes any changes.
- */
-void
-AlterTableCreateToastTable(Oid relOid, bool silent)
-{
-	Relation	rel;
-	HeapTuple	reltup;
-	TupleDesc	tupdesc;
-	bool		shared_relation;
-	Relation	class_rel;
-	Oid			toast_relid;
-	Oid			toast_idxid;
-	char		toast_relname[NAMEDATALEN];
-	char		toast_idxname[NAMEDATALEN];
-	IndexInfo  *indexInfo;
-	Oid			classObjectId[2];
-	ObjectAddress baseobject,
-				toastobject;
-
-	/*
-	 * Grab an exclusive lock on the target table, which we will NOT release
-	 * until end of transaction.  (This is probably redundant in all present
-	 * uses...)
-	 */
-	rel = heap_open(relOid, AccessExclusiveLock);
-
-	/*
-	 * Toast table is shared if and only if its parent is.
-	 *
-	 * We cannot allow toasting a shared relation after initdb (because
-	 * there's no way to mark it toasted in other databases' pg_class).
-	 * Unfortunately we can't distinguish initdb from a manually started
-	 * standalone backend (toasting happens after the bootstrap phase, so
-	 * checking IsBootstrapProcessingMode() won't work).  However, we can at
-	 * least prevent this mistake under normal multi-user operation.
-	 */
-	shared_relation = rel->rd_rel->relisshared;
-	if (shared_relation && IsUnderPostmaster)
-		ereport(ERROR,
-				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
-				 errmsg("shared tables cannot be toasted after initdb")));
-
-	/*
-	 * Is it already toasted?
-	 */
-	if (rel->rd_rel->reltoastrelid != InvalidOid)
-	{
-		if (silent)
-		{
-			heap_close(rel, NoLock);
-			return;
-		}
-
-		ereport(ERROR,
-				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
-				 errmsg("table \"%s\" already has a TOAST table",
-						RelationGetRelationName(rel))));
-	}
-
-	/*
-	 * Check to see whether the table actually needs a TOAST table.
-	 */
-	if (!needs_toast_table(rel))
-	{
-		if (silent)
-		{
-			heap_close(rel, NoLock);
-			return;
-		}
-
-		ereport(ERROR,
-				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
-				 errmsg("table \"%s\" does not need a TOAST table",
-						RelationGetRelationName(rel))));
-	}
-
-	/*
-	 * Create the toast table and its index
-	 */
-	snprintf(toast_relname, sizeof(toast_relname),
-			 "pg_toast_%u", relOid);
-	snprintf(toast_idxname, sizeof(toast_idxname),
-			 "pg_toast_%u_index", relOid);
-
-	/* this is pretty painful...  need a tuple descriptor */
-	tupdesc = CreateTemplateTupleDesc(3, false);
-	TupleDescInitEntry(tupdesc, (AttrNumber) 1,
-					   "chunk_id",
-					   OIDOID,
-					   -1, 0);
-	TupleDescInitEntry(tupdesc, (AttrNumber) 2,
-					   "chunk_seq",
-					   INT4OID,
-					   -1, 0);
-	TupleDescInitEntry(tupdesc, (AttrNumber) 3,
-					   "chunk_data",
-					   BYTEAOID,
-					   -1, 0);
-
-	/*
-	 * Ensure that the toast table doesn't itself get toasted, or we'll be
-	 * toast :-(.  This is essential for chunk_data because type bytea is
-	 * toastable; hit the other two just to be sure.
-	 */
-	tupdesc->attrs[0]->attstorage = 'p';
-	tupdesc->attrs[1]->attstorage = 'p';
-	tupdesc->attrs[2]->attstorage = 'p';
-
-	/*
-	 * Note: the toast relation is placed in the regular pg_toast namespace
-	 * even if its master relation is a temp table.  There cannot be any
-	 * naming collision, and the toast rel will be destroyed when its master
-	 * is, so there's no need to handle the toast rel as temp.
-	 *
-	 * XXX would it make sense to apply the master's reloptions to the toast
-	 * table?
-	 */
-	toast_relid = heap_create_with_catalog(toast_relname,
-										   PG_TOAST_NAMESPACE,
-										   rel->rd_rel->reltablespace,
-										   InvalidOid,
-										   rel->rd_rel->relowner,
-										   tupdesc,
-										   RELKIND_TOASTVALUE,
-										   shared_relation,
-										   true,
-										   0,
-										   ONCOMMIT_NOOP,
-										   (Datum) 0,
-										   true);
-
-	/* make the toast relation visible, else index creation will fail */
-	CommandCounterIncrement();
-
-	/*
-	 * Create unique index on chunk_id, chunk_seq.
-	 *
-	 * NOTE: the normal TOAST access routines could actually function with a
-	 * single-column index on chunk_id only. However, the slice access
-	 * routines use both columns for faster access to an individual chunk. In
-	 * addition, we want it to be unique as a check against the possibility of
-	 * duplicate TOAST chunk OIDs. The index might also be a little more
-	 * efficient this way, since btree isn't all that happy with large numbers
-	 * of equal keys.
-	 */
-
-	indexInfo = makeNode(IndexInfo);
-	indexInfo->ii_NumIndexAttrs = 2;
-	indexInfo->ii_KeyAttrNumbers[0] = 1;
-	indexInfo->ii_KeyAttrNumbers[1] = 2;
-	indexInfo->ii_Expressions = NIL;
-	indexInfo->ii_ExpressionsState = NIL;
-	indexInfo->ii_Predicate = NIL;
-	indexInfo->ii_PredicateState = NIL;
-	indexInfo->ii_Unique = true;
-
-	classObjectId[0] = OID_BTREE_OPS_OID;
-	classObjectId[1] = INT4_BTREE_OPS_OID;
-
-	toast_idxid = index_create(toast_relid, toast_idxname, InvalidOid,
-							   indexInfo,
-							   BTREE_AM_OID,
-							   rel->rd_rel->reltablespace,
-							   classObjectId, (Datum) 0,
-							   true, true, false, true, false);
-
-	/*
-	 * Store the toast table's OID in the parent relation's pg_class row
-	 */
-	class_rel = heap_open(RelationRelationId, RowExclusiveLock);
-
-	reltup = SearchSysCacheCopy(RELOID,
-								ObjectIdGetDatum(relOid),
-								0, 0, 0);
-	if (!HeapTupleIsValid(reltup))
-		elog(ERROR, "cache lookup failed for relation %u", relOid);
-
-	((Form_pg_class) GETSTRUCT(reltup))->reltoastrelid = toast_relid;
-
-	simple_heap_update(class_rel, &reltup->t_self, reltup);
-
-	/* Keep catalog indexes current */
-	CatalogUpdateIndexes(class_rel, reltup);
-
-	heap_freetuple(reltup);
-
-	heap_close(class_rel, RowExclusiveLock);
-
-	/*
-	 * Register dependency from the toast table to the master, so that the
-	 * toast table will be deleted if the master is.
-	 */
-	baseobject.classId = RelationRelationId;
-	baseobject.objectId = relOid;
-	baseobject.objectSubId = 0;
-	toastobject.classId = RelationRelationId;
-	toastobject.objectId = toast_relid;
-	toastobject.objectSubId = 0;
-
-	recordDependencyOn(&toastobject, &baseobject, DEPENDENCY_INTERNAL);
-
-	/*
-	 * Clean up and make changes visible
-	 */
-	heap_close(rel, NoLock);
-
-	CommandCounterIncrement();
-}
-
-/*
- * Check to see whether the table needs a TOAST table.	It does only if
- * (1) there are any toastable attributes, and (2) the maximum length
- * of a tuple could exceed TOAST_TUPLE_THRESHOLD.  (We don't want to
- * create a toast table for something like "f1 varchar(20)".)
- */
-static bool
-needs_toast_table(Relation rel)
-{
-	int32		data_length = 0;
-	bool		maxlength_unknown = false;
-	bool		has_toastable_attrs = false;
-	TupleDesc	tupdesc;
-	Form_pg_attribute *att;
-	int32		tuple_length;
-	int			i;
-
-	tupdesc = rel->rd_att;
-	att = tupdesc->attrs;
-
-	for (i = 0; i < tupdesc->natts; i++)
-	{
-		if (att[i]->attisdropped)
-			continue;
-		data_length = att_align(data_length, att[i]->attalign);
-		if (att[i]->attlen > 0)
-		{
-			/* Fixed-length types are never toastable */
-			data_length += att[i]->attlen;
-		}
-		else
-		{
-			int32		maxlen = type_maximum_size(att[i]->atttypid,
-												   att[i]->atttypmod);
-
-			if (maxlen < 0)
-				maxlength_unknown = true;
-			else
-				data_length += maxlen;
-			if (att[i]->attstorage != 'p')
-				has_toastable_attrs = true;
-		}
-	}
-	if (!has_toastable_attrs)
-		return false;			/* nothing to toast? */
-	if (maxlength_unknown)
-		return true;			/* any unlimited-length attrs? */
-	tuple_length = MAXALIGN(offsetof(HeapTupleHeaderData, t_bits) +
-							BITMAPLEN(tupdesc->natts)) +
-		MAXALIGN(data_length);
-	return (tuple_length > TOAST_TUPLE_THRESHOLD);
-}
-
-
 /*
  * Execute ALTER TABLE SET SCHEMA
  *
diff --git a/src/backend/executor/execMain.c b/src/backend/executor/execMain.c
index b0d0fa115a70fdf201b9c978be728ba6d8f5c2fe..efc5d54fe9e25f7044cf5fc19afefe898625ef4d 100644
--- a/src/backend/executor/execMain.c
+++ b/src/backend/executor/execMain.c
@@ -26,7 +26,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.276 2006/07/14 14:52:18 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/executor/execMain.c,v 1.277 2006/07/31 01:16:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -38,7 +38,7 @@
 #include "access/xact.h"
 #include "catalog/heap.h"
 #include "catalog/namespace.h"
-#include "commands/tablecmds.h"
+#include "catalog/toasting.h"
 #include "commands/tablespace.h"
 #include "commands/trigger.h"
 #include "executor/execdebug.h"
@@ -821,7 +821,7 @@ InitPlan(QueryDesc *queryDesc, int eflags)
 		 * AlterTableCreateToastTable ends with CommandCounterIncrement(), so
 		 * that the TOAST table will be visible for insertion.
 		 */
-		AlterTableCreateToastTable(intoRelationId, true);
+		AlterTableCreateToastTable(intoRelationId);
 
 		/*
 		 * And open the constructed table for writing.
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index afd88e8125bdfbb38b32682ed5812fa6ffd62597..434f05bc4d83b59e6b47cc131fbd16072bab0b28 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.552 2006/07/27 19:52:05 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/parser/gram.y,v 2.553 2006/07/31 01:16:37 tgl Exp $
  *
  * HISTORY
  *	  AUTHOR			DATE			MAJOR EVENT
@@ -422,7 +422,7 @@ static void doNegateFloat(Value *v);
 	SYSID SYSTEM_P
 
 	TABLE TABLESPACE TEMP TEMPLATE TEMPORARY THEN TIME TIMESTAMP
-	TO TOAST TRAILING TRANSACTION TREAT TRIGGER TRIM TRUE_P
+	TO TRAILING TRANSACTION TREAT TRIGGER TRIM TRUE_P
 	TRUNCATE TRUSTED TYPE_P
 
 	UNCOMMITTED UNENCRYPTED UNION UNIQUE UNKNOWN UNLISTEN UNTIL
@@ -1446,13 +1446,6 @@ alter_table_cmd:
 					n->subtype = AT_DropOids;
 					$$ = (Node *)n;
 				}
-			/* ALTER TABLE <name> CREATE TOAST TABLE -- ONLY */
-			| CREATE TOAST TABLE
-				{
-					AlterTableCmd *n = makeNode(AlterTableCmd);
-					n->subtype = AT_ToastTable;
-					$$ = (Node *)n;
-				}
 			/* ALTER TABLE <name> CLUSTER ON <indexname> */
 			| CLUSTER ON name
 				{
@@ -8649,7 +8642,6 @@ unreserved_keyword:
 			| TEMP
 			| TEMPLATE
 			| TEMPORARY
-			| TOAST
 			| TRANSACTION
 			| TRIGGER
 			| TRUNCATE
diff --git a/src/backend/parser/keywords.c b/src/backend/parser/keywords.c
index 78dd531a56ed06b5d940eba85f20a9ee051587d2..37686873f6292ec2a2dcefecea8264389575a43b 100644
--- a/src/backend/parser/keywords.c
+++ b/src/backend/parser/keywords.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.173 2006/07/15 03:35:21 tgl Exp $
+ *	  $PostgreSQL: pgsql/src/backend/parser/keywords.c,v 1.174 2006/07/31 01:16:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -332,7 +332,6 @@ static const ScanKeyword ScanKeywords[] = {
 	{"time", TIME},
 	{"timestamp", TIMESTAMP},
 	{"to", TO},
-	{"toast", TOAST},
 	{"trailing", TRAILING},
 	{"transaction", TRANSACTION},
 	{"treat", TREAT},
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index 2ebf616835d40b64b00d8e6082800eb3f0543c1d..cdebf9a63b9f584b2a6d568f09515cc67b92466f 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -10,7 +10,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.262 2006/07/14 14:52:23 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/tcop/utility.c,v 1.263 2006/07/31 01:16:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -20,6 +20,7 @@
 #include "access/xact.h"
 #include "catalog/catalog.h"
 #include "catalog/namespace.h"
+#include "catalog/toasting.h"
 #include "commands/alter.h"
 #include "commands/async.h"
 #include "commands/cluster.h"
@@ -526,7 +527,7 @@ ProcessUtility(Node *parsetree,
 				 * secondary relation too.
 				 */
 				CommandCounterIncrement();
-				AlterTableCreateToastTable(relOid, true);
+				AlterTableCreateToastTable(relOid);
 			}
 			break;
 
diff --git a/src/bin/initdb/initdb.c b/src/bin/initdb/initdb.c
index 63bed4e91951b6bcf49c6dd2d2ec97ff9943c9f2..643e9f192574937a0464684c2e72369bb54a2bdd 100644
--- a/src/bin/initdb/initdb.c
+++ b/src/bin/initdb/initdb.c
@@ -42,7 +42,7 @@
  * Portions Copyright (c) 1994, Regents of the University of California
  * Portions taken from FreeBSD.
  *
- * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.119 2006/07/27 08:30:41 petere Exp $
+ * $PostgreSQL: pgsql/src/bin/initdb/initdb.c,v 1.120 2006/07/31 01:16:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -174,7 +174,6 @@ static void setup_config(void);
 static void bootstrap_template1(char *short_version);
 static void setup_auth(void);
 static void get_set_pwd(void);
-static void unlimit_systables(void);
 static void setup_depend(void);
 static void setup_sysviews(void);
 static void setup_description(void);
@@ -1559,45 +1558,6 @@ get_set_pwd(void)
 	}
 }
 
-/*
- * toast sys tables
- */
-static void
-unlimit_systables(void)
-{
-	PG_CMD_DECL;
-	char	  **line;
-	static char *systables_setup[] = {
-		"ALTER TABLE pg_attrdef CREATE TOAST TABLE;\n",
-		"ALTER TABLE pg_authid CREATE TOAST TABLE;\n",
-		"ALTER TABLE pg_constraint CREATE TOAST TABLE;\n",
-		"ALTER TABLE pg_database CREATE TOAST TABLE;\n",
-		"ALTER TABLE pg_description CREATE TOAST TABLE;\n",
-		"ALTER TABLE pg_proc CREATE TOAST TABLE;\n",
-		"ALTER TABLE pg_rewrite CREATE TOAST TABLE;\n",
-		"ALTER TABLE pg_shdescription CREATE TOAST TABLE;\n",
-		"ALTER TABLE pg_statistic CREATE TOAST TABLE;\n",
-		NULL
-	};
-
-	fputs(_("enabling unlimited row size for system tables ... "), stdout);
-	fflush(stdout);
-
-	snprintf(cmd, sizeof(cmd),
-			 "\"%s\" %s template1 >%s",
-			 backend_exec, backend_options,
-			 DEVNULL);
-
-	PG_CMD_OPEN;
-
-	for (line = systables_setup; *line != NULL; line++)
-		PG_CMD_PUTS(*line);
-
-	PG_CMD_CLOSE;
-
-	check_ok();
-}
-
 /*
  * set up pg_depend
  */
@@ -2935,8 +2895,6 @@ main(int argc, char *argv[])
 	if (pwprompt || pwfilename)
 		get_set_pwd();
 
-	unlimit_systables();
-
 	setup_depend();
 
 	setup_sysviews();
diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h
index 7386e91eaf6af74072872344b0adc99c01bf135f..052d2a19cfd7c10f9159cc7d532650639172dcc0 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.343 2006/07/28 18:33:04 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.344 2006/07/31 01:16:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -53,6 +53,6 @@
  */
 
 /*							yyyymmddN */
-#define CATALOG_VERSION_NO	200607281
+#define CATALOG_VERSION_NO	200607301
 
 #endif
diff --git a/src/include/catalog/duplicate_oids b/src/include/catalog/duplicate_oids
index 1964faabe3d22af2942cc59e18723970c24a4fcb..ea58f4a0252ffbe009fac4eec0d281819c7ded4b 100755
--- a/src/include/catalog/duplicate_oids
+++ b/src/include/catalog/duplicate_oids
@@ -2,7 +2,7 @@
 #
 # duplicate_oids
 #
-# $PostgreSQL: pgsql/src/include/catalog/duplicate_oids,v 1.7 2005/04/14 01:38:20 tgl Exp $
+# $PostgreSQL: pgsql/src/include/catalog/duplicate_oids,v 1.8 2006/07/31 01:16:37 tgl Exp $
 #
 # finds manually-assigned oids that are duplicated in the system tables.
 #
@@ -12,12 +12,14 @@
 # note: we exclude BKI_BOOTSTRAP relations since they are expected to have
 # matching DATA lines in pg_class.h
 
-cat pg_*.h indexing.h | \
+cat pg_*.h toasting.h indexing.h | \
 egrep -v -e '^CATALOG\(.*BKI_BOOTSTRAP' | \
 sed -n	-e 's/^DATA(insert *OID *= *\([0-9][0-9]*\).*$/\1/p' \
 	-e 's/^CATALOG([^,]*, *\([0-9][0-9]*\).*$/\1/p' \
 	-e 's/^DECLARE_INDEX([^,]*, *\([0-9][0-9]*\).*$/\1/p' \
-	-e 's/^DECLARE_UNIQUE_INDEX([^,]*, *\([0-9][0-9]*\).*$/\1/p' | \
+	-e 's/^DECLARE_UNIQUE_INDEX([^,]*, *\([0-9][0-9]*\).*$/\1/p' \
+	-e 's/^DECLARE_TOAST([^,]*, *\([0-9][0-9]*\), *\([0-9][0-9]*\).*$/\1,\2/p' | \
+tr ',' '\n' | \
 sort -n | \
 uniq -d
 
diff --git a/src/include/catalog/index.h b/src/include/catalog/index.h
index 7d2059ed03b476de02575133c3aab23f846b9bb1..f54508fb5b4053998cab66981dde7ce99b61e413 100644
--- a/src/include/catalog/index.h
+++ b/src/include/catalog/index.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/index.h,v 1.69 2006/07/13 16:49:19 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/catalog/index.h,v 1.70 2006/07/31 01:16:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -37,7 +37,6 @@ extern Oid index_create(Oid heapRelationId,
 			 Oid *classObjectId,
 			 Datum reloptions,
 			 bool isprimary,
-			 bool istoast,
 			 bool isconstraint,
 			 bool allow_system_table_mods,
 			 bool skip_build);
@@ -57,8 +56,7 @@ extern void setNewRelfilenode(Relation relation);
 extern void index_build(Relation heapRelation,
 			Relation indexRelation,
 			IndexInfo *indexInfo,
-			bool isprimary,
-			bool istoast);
+			bool isprimary);
 
 extern double IndexBuildHeapScan(Relation heapRelation,
 				   Relation indexRelation,
diff --git a/src/include/catalog/toasting.h b/src/include/catalog/toasting.h
new file mode 100644
index 0000000000000000000000000000000000000000..25a84b3f8801d92f1deeda7c872b0463c47d38a9
--- /dev/null
+++ b/src/include/catalog/toasting.h
@@ -0,0 +1,61 @@
+/*-------------------------------------------------------------------------
+ *
+ * toasting.h
+ *	  This file provides some definitions to support creation of toast tables
+ *
+ *
+ * Portions Copyright (c) 1996-2006, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * $PostgreSQL: pgsql/src/include/catalog/toasting.h,v 1.1 2006/07/31 01:16:37 tgl Exp $
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TOASTING_H
+#define TOASTING_H
+
+/*
+ * toasting.c prototypes
+ */
+extern void AlterTableCreateToastTable(Oid relOid);
+extern void BootstrapToastTable(char *relName,
+								Oid toastOid, Oid toastIndexOid);
+
+
+/*
+ * This macro is just to keep the C compiler from spitting up on the
+ * upcoming commands for genbki.sh.
+ */
+#define DECLARE_TOAST(name,toastoid,indexoid) extern int no_such_variable
+
+
+/*
+ * What follows are lines processed by genbki.sh to create the statements
+ * the bootstrap parser will turn into BootstrapToastTable commands.
+ * Each line specifies the system catalog that needs a toast table,
+ * the OID to assign to the toast table, and the OID to assign to the
+ * toast table's index.  The reason we hard-wire these OIDs is that we
+ * need stable OIDs for shared relations, and that includes toast tables
+ * of shared relations.
+ */
+
+/* normal catalogs */
+DECLARE_TOAST(pg_attrdef,2830,2831);
+DECLARE_TOAST(pg_constraint,2832,2833);
+DECLARE_TOAST(pg_description,2834,2835);
+DECLARE_TOAST(pg_proc,2836,2837);
+DECLARE_TOAST(pg_rewrite,2838,2839);
+DECLARE_TOAST(pg_statistic,2840,2841);
+
+/* shared catalogs */
+DECLARE_TOAST(pg_authid,2842,2843);
+#define PgAuthidToastTable 2842
+#define PgAuthidToastIndex 2843
+DECLARE_TOAST(pg_database,2844,2845);
+#define PgDatabaseToastTable 2844
+#define PgDatabaseToastIndex 2845
+DECLARE_TOAST(pg_shdescription,2846,2847);
+#define PgShdescriptionToastTable 2846
+#define PgShdescriptionToastIndex 2847
+
+#endif   /* TOASTING_H */
diff --git a/src/include/catalog/unused_oids b/src/include/catalog/unused_oids
index c83a637196aed076f92c3627af774e5528fb6d02..4003beef5323ffefc1ab6f30c4d59988cef9faf4 100755
--- a/src/include/catalog/unused_oids
+++ b/src/include/catalog/unused_oids
@@ -2,7 +2,7 @@
 #
 # unused_oids
 #
-# $PostgreSQL: pgsql/src/include/catalog/unused_oids,v 1.7 2005/04/14 01:38:21 tgl Exp $
+# $PostgreSQL: pgsql/src/include/catalog/unused_oids,v 1.8 2006/07/31 01:16:38 tgl Exp $
 #
 #	finds blocks of manually-assignable oids that have not already been
 #	claimed by post_hackers.  primarily useful for finding available
@@ -23,16 +23,18 @@ AWK="awk"
 FIRSTOBJECTID=`grep '#define[ 	]*FirstBootstrapObjectId' ../access/transam.h | $AWK '{ print $3 }'`
 export FIRSTOBJECTID
 
-# this part (down to the uniq step) should match the unused_oids script
+# this part (down to the uniq step) should match the duplicate_oids script
 # note: we exclude BKI_BOOTSTRAP relations since they are expected to have
 # matching DATA lines in pg_class.h
 
-cat pg_*.h indexing.h | \
+cat pg_*.h toasting.h indexing.h | \
 egrep -v -e '^CATALOG\(.*BKI_BOOTSTRAP' | \
 sed -n	-e 's/^DATA(insert *OID *= *\([0-9][0-9]*\).*$/\1/p' \
 	-e 's/^CATALOG([^,]*, *\([0-9][0-9]*\).*$/\1/p' \
 	-e 's/^DECLARE_INDEX([^,]*, *\([0-9][0-9]*\).*$/\1/p' \
-	-e 's/^DECLARE_UNIQUE_INDEX([^,]*, *\([0-9][0-9]*\).*$/\1/p' | \
+	-e 's/^DECLARE_UNIQUE_INDEX([^,]*, *\([0-9][0-9]*\).*$/\1/p' \
+	-e 's/^DECLARE_TOAST([^,]*, *\([0-9][0-9]*\), *\([0-9][0-9]*\).*$/\1,\2/p' | \
+tr ',' '\n' | \
 sort -n | \
 uniq | \
 $AWK '
diff --git a/src/include/commands/tablecmds.h b/src/include/commands/tablecmds.h
index 41c1fd9f14d9f22c5f9f96c60be9d2bf2dd2abf3..4c9063f13ca853816f4aabdd4472a8433904b6c6 100644
--- a/src/include/commands/tablecmds.h
+++ b/src/include/commands/tablecmds.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/commands/tablecmds.h,v 1.29 2006/07/13 16:49:19 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/commands/tablecmds.h,v 1.30 2006/07/31 01:16:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -28,8 +28,6 @@ extern void ATExecChangeOwner(Oid relationOid, Oid newOwnerId, bool recursing);
 
 extern void AlterTableInternal(Oid relid, List *cmds, bool recurse);
 
-extern void AlterTableCreateToastTable(Oid relOid, bool silent);
-
 extern void AlterTableNamespace(RangeVar *relation, const char *newschema);
 
 extern void AlterRelationNamespaceInternal(Relation classRel, Oid relOid,
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index c44ba954d8446dc0dd38314c11486b89abfee1b1..5c227156f064f4d8edc49395290e4b16ce3c02aa 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.318 2006/07/26 19:31:51 tgl Exp $
+ * $PostgreSQL: pgsql/src/include/nodes/parsenodes.h,v 1.319 2006/07/31 01:16:38 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -854,7 +854,6 @@ typedef enum AlterTableType
 	AT_DropConstraintQuietly,	/* drop constraint, no error/warning (local in
 								 * commands/tablecmds.c) */
 	AT_AlterColumnType,			/* alter column type */
-	AT_ToastTable,				/* create toast table */
 	AT_ChangeOwner,				/* change owner */
 	AT_ClusterOn,				/* CLUSTER ON */
 	AT_DropCluster,				/* SET WITHOUT CLUSTER */