diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index c0f5f2074b1980b85caf10aa63bee7a9c0e7e84b..042a33a5d2bc6fd7a7109763057037b32dceeb65 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.225 2007/01/25 02:17:25 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.226 2007/02/04 20:00:37 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -1418,8 +1418,7 @@ heap_insert(Relation relation, HeapTuple tup, CommandId cid,
 	 * Note: below this point, heaptup is the data we actually intend to store
 	 * into the relation; tup is the caller's original untoasted data.
 	 */
-	if (HeapTupleHasExternal(tup) ||
-		(MAXALIGN(tup->t_len) > TOAST_TUPLE_THRESHOLD))
+	if (HeapTupleHasExternal(tup) || tup->t_len > TOAST_TUPLE_THRESHOLD)
 		heaptup = toast_insert_or_update(relation, tup, NULL, use_wal);
 	else
 		heaptup = tup;
@@ -2073,14 +2072,14 @@ l2:
 	 * We need to invoke the toaster if there are already any out-of-line
 	 * toasted values present, or if the new tuple is over-threshold.
 	 */
-	newtupsize = MAXALIGN(newtup->t_len);
-
 	need_toast = (HeapTupleHasExternal(&oldtup) ||
 				  HeapTupleHasExternal(newtup) ||
-				  newtupsize > TOAST_TUPLE_THRESHOLD);
+				  newtup->t_len > TOAST_TUPLE_THRESHOLD);
 
 	pagefree = PageGetFreeSpace((Page) dp);
 
+	newtupsize = MAXALIGN(newtup->t_len);
+
 	if (need_toast || newtupsize > pagefree)
 	{
 		oldtup.t_data->t_infomask &= ~(HEAP_XMAX_COMMITTED |
@@ -2100,7 +2099,7 @@ l2:
 		 *
 		 * Note: below this point, heaptup is the data we actually intend to
 		 * store into the relation; newtup is the caller's original untoasted
-		 * data. (We always use WAL for toast table updates.)
+		 * data.
 		 */
 		if (need_toast)
 		{
diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c
index 449c57268e12af7a44ced433c2b2fe21039d4be1..6fde18104a3be81c350deecbe7386f104a62cb86 100644
--- a/src/backend/access/heap/tuptoaster.c
+++ b/src/backend/access/heap/tuptoaster.c
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *	  $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.69 2007/01/25 02:17:26 momjian Exp $
+ *	  $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.70 2007/02/04 20:00:37 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -506,17 +506,23 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup, bool us
 	 *	4: Store attributes with attstorage 'm' external
 	 * ----------
 	 */
+
+	/* compute header overhead --- this should match heap_form_tuple() */
 	maxDataLen = offsetof(HeapTupleHeaderData, t_bits);
 	if (has_nulls)
 		maxDataLen += BITMAPLEN(numAttrs);
-	maxDataLen = TOAST_TUPLE_TARGET - MAXALIGN(maxDataLen);
+	if (newtup->t_data->t_infomask & HEAP_HASOID)
+		maxDataLen += sizeof(Oid);
+	maxDataLen = MAXALIGN(maxDataLen);
+	Assert(maxDataLen == newtup->t_data->t_hoff);
+	/* now convert to a limit on the tuple data size */
+	maxDataLen = TOAST_TUPLE_TARGET - maxDataLen;
 
 	/*
 	 * Look for attributes with attstorage 'x' to compress
 	 */
-	while (MAXALIGN(heap_compute_data_size(tupleDesc,
-										   toast_values, toast_isnull)) >
-		   maxDataLen)
+	while (heap_compute_data_size(tupleDesc,
+								  toast_values, toast_isnull) > maxDataLen)
 	{
 		int			biggest_attno = -1;
 		int32		biggest_size = MAXALIGN(sizeof(varattrib));
@@ -575,9 +581,9 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup, bool us
 	 * Second we look for attributes of attstorage 'x' or 'e' that are still
 	 * inline.
 	 */
-	while (MAXALIGN(heap_compute_data_size(tupleDesc,
-										   toast_values, toast_isnull)) >
-		   maxDataLen && rel->rd_rel->reltoastrelid != InvalidOid)
+	while (heap_compute_data_size(tupleDesc,
+								  toast_values, toast_isnull) > maxDataLen &&
+		   rel->rd_rel->reltoastrelid != InvalidOid)
 	{
 		int			biggest_attno = -1;
 		int32		biggest_size = MAXALIGN(sizeof(varattrib));
@@ -627,9 +633,8 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup, bool us
 	 * Round 3 - this time we take attributes with storage 'm' into
 	 * compression
 	 */
-	while (MAXALIGN(heap_compute_data_size(tupleDesc,
-										   toast_values, toast_isnull)) >
-		   maxDataLen)
+	while (heap_compute_data_size(tupleDesc,
+								  toast_values, toast_isnull) > maxDataLen)
 	{
 		int			biggest_attno = -1;
 		int32		biggest_size = MAXALIGN(sizeof(varattrib));
@@ -687,9 +692,9 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup, bool us
 	/*
 	 * Finally we store attributes of type 'm' external
 	 */
-	while (MAXALIGN(heap_compute_data_size(tupleDesc,
-										   toast_values, toast_isnull)) >
-		   maxDataLen && rel->rd_rel->reltoastrelid != InvalidOid)
+	while (heap_compute_data_size(tupleDesc,
+								  toast_values, toast_isnull) > maxDataLen &&
+		   rel->rd_rel->reltoastrelid != InvalidOid)
 	{
 		int			biggest_attno = -1;
 		int32		biggest_size = MAXALIGN(sizeof(varattrib));
diff --git a/src/include/access/tuptoaster.h b/src/include/access/tuptoaster.h
index ee8cfa74492ef6306256c588d9afbdcdc20b870a..49d69836dcd79e95e9606e31b5a20324a0e1d8e4 100644
--- a/src/include/access/tuptoaster.h
+++ b/src/include/access/tuptoaster.h
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 2000-2007, PostgreSQL Global Development Group
  *
- * $PostgreSQL: pgsql/src/include/access/tuptoaster.h,v 1.30 2007/01/25 02:17:26 momjian Exp $
+ * $PostgreSQL: pgsql/src/include/access/tuptoaster.h,v 1.31 2007/02/04 20:00:37 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -26,8 +26,11 @@
 /*
  * These symbols control toaster activation.  If a tuple is larger than
  * TOAST_TUPLE_THRESHOLD, we will try to toast it down to no more than
- * TOAST_TUPLE_TARGET bytes.  Both numbers include all tuple header and
- * alignment-padding overhead.
+ * TOAST_TUPLE_TARGET bytes.  Both numbers include all tuple header overhead
+ * and between-fields alignment padding, but we do *not* consider any
+ * end-of-tuple alignment padding; hence the values can be compared directly
+ * to a tuple's t_len field.  (Note that the symbol values are not
+ * necessarily MAXALIGN multiples.)
  *
  * The numbers need not be the same, though they currently are.
  */