diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index 581f5194c4..1889d09784 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.222 2006/11/17 18:00:14 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.222.2.1 2007/02/04 20:00:49 tgl Exp $ * * * INTERFACE ROUTINES @@ -1416,8 +1416,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); else heaptup = tup; @@ -2059,14 +2058,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 | diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c index 49ae91f406..0f1d2a9e7d 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.66 2006/10/05 23:33:33 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.66.2.1 2007/02/04 20:00:49 tgl Exp $ * * * INTERFACE ROUTINES @@ -506,17 +506,23 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup) * 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) * 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) * 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) /* * 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 53f6f90268..6f2686106f 100644 --- a/src/include/access/tuptoaster.h +++ b/src/include/access/tuptoaster.h @@ -6,7 +6,7 @@ * * Copyright (c) 2000-2006, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/include/access/tuptoaster.h,v 1.28 2006/07/13 17:47:01 momjian Exp $ + * $PostgreSQL: pgsql/src/include/access/tuptoaster.h,v 1.28.2.1 2007/02/04 20:00:49 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. */