Index: src/backend/access/heap/tuptoaster.c
===================================================================
RCS file: /projects/cvsroot/pgsql/src/backend/access/heap/tuptoaster.c,v
retrieving revision 1.93
diff -c -r1.93 tuptoaster.c
*** src/backend/access/heap/tuptoaster.c	11 Jun 2009 14:48:54 -0000	1.93
--- src/backend/access/heap/tuptoaster.c	15 Jun 2009 16:26:58 -0000
***************
*** 798,803 ****
--- 798,804 ----
  	/*
  	 * Finally we store attributes of type 'm' external, if possible.
  	 */
+ 	maxDataLen = TOAST_TUPLE_TARGET_MAIN - hoff;
  	while (heap_compute_data_size(tupleDesc,
  								  toast_values, toast_isnull) > maxDataLen &&
  		   rel->rd_rel->reltoastrelid != InvalidOid)
Index: src/include/access/tuptoaster.h
===================================================================
RCS file: /projects/cvsroot/pgsql/src/include/access/tuptoaster.h,v
retrieving revision 1.43
diff -c -r1.43 tuptoaster.h
*** src/include/access/tuptoaster.h	1 Jan 2009 17:23:56 -0000	1.43
--- src/include/access/tuptoaster.h	15 Jun 2009 16:26:58 -0000
***************
*** 25,36 ****
  
  
  /*
!  * 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 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.
   *
   * The numbers need not be the same, though they currently are.  It doesn't
   * make sense for TARGET to exceed THRESHOLD, but it could be useful to make
--- 25,46 ----
  
  
  /*
!  * Find the maximum size of a tuple which allows "n" tuples per page.
!  * 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.
+  */
+ #define MaximumBytesPerTuple(tuplesPerPage)	\
+ 	MAXALIGN_DOWN((BLCKSZ - \
+ 				   MAXALIGN(SizeOfPageHeaderData + (tuplesPerPage) * sizeof(ItemIdData))) \
+ 				  / (tuplesPerPage))
+ 
+ /*
+  * 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 through compressing compressible fields and
+  * moving moving EXTENDED and EXTERNAL data out-of-line.
   *
   * The numbers need not be the same, though they currently are.  It doesn't
   * make sense for TARGET to exceed THRESHOLD, but it could be useful to make
***************
*** 39,44 ****
--- 49,60 ----
   * Currently we choose both values to match the largest tuple size for which
   * TOAST_TUPLES_PER_PAGE tuples can fit on a disk page.
   *
+  * We set a separate target for MAIN fields, which we will try to reach by
+  * moving MAIN fields out-of-line only if the above has not already done so.
+  * Since the user is trying to keep the data in-line, it makes sense to set
+  * TOAST_TUPLES_PER_PAGE_MAIN to a lower number (currently 1), which will
+  * result in a larger TOAST_TUPLE_TARGET_MAIN value.
+  *
   * XXX while these can be modified without initdb, some thought needs to be
   * given to needs_toast_table() in toasting.c before unleashing random
   * changes.  Also see LOBLKSIZE in large_object.h, which can *not* be
***************
*** 46,58 ****
   */
  #define TOAST_TUPLES_PER_PAGE	4
  
! #define TOAST_TUPLE_THRESHOLD	\
! 	MAXALIGN_DOWN((BLCKSZ - \
! 				   MAXALIGN(SizeOfPageHeaderData + TOAST_TUPLES_PER_PAGE * sizeof(ItemIdData))) \
! 				  / TOAST_TUPLES_PER_PAGE)
  
  #define TOAST_TUPLE_TARGET		TOAST_TUPLE_THRESHOLD
  
  /*
   * If an index value is larger than TOAST_INDEX_TARGET, we will try to
   * compress it (we can't move it out-of-line, however).  Note that this
--- 62,75 ----
   */
  #define TOAST_TUPLES_PER_PAGE	4
  
! #define TOAST_TUPLE_THRESHOLD	MaximumBytesPerTuple(TOAST_TUPLES_PER_PAGE)
  
  #define TOAST_TUPLE_TARGET		TOAST_TUPLE_THRESHOLD
  
+ #define TOAST_TUPLES_PER_PAGE_MAIN	1
+ 
+ #define TOAST_TUPLE_TARGET_MAIN	MaximumBytesPerTuple(TOAST_TUPLES_PER_PAGE_MAIN)
+ 
  /*
   * If an index value is larger than TOAST_INDEX_TARGET, we will try to
   * compress it (we can't move it out-of-line, however).  Note that this
***************
*** 72,81 ****
   */
  #define EXTERN_TUPLES_PER_PAGE	4		/* tweak only this */
  
! #define EXTERN_TUPLE_MAX_SIZE	\
! 	MAXALIGN_DOWN((BLCKSZ - \
! 				   MAXALIGN(SizeOfPageHeaderData + EXTERN_TUPLES_PER_PAGE * sizeof(ItemIdData))) \
! 				  / EXTERN_TUPLES_PER_PAGE)
  
  #define TOAST_MAX_CHUNK_SIZE	\
  	(EXTERN_TUPLE_MAX_SIZE -							\
--- 89,95 ----
   */
  #define EXTERN_TUPLES_PER_PAGE	4		/* tweak only this */
  
! #define EXTERN_TUPLE_MAX_SIZE	MaximumBytesPerTuple(EXTERN_TUPLES_PER_PAGE)
  
  #define TOAST_MAX_CHUNK_SIZE	\
  	(EXTERN_TUPLE_MAX_SIZE -							\
