diff options
Diffstat (limited to 'src/backend')
-rw-r--r-- | src/backend/access/heap/heapam.c | 31 | ||||
-rw-r--r-- | src/backend/access/heap/tuptoaster.c | 31 | ||||
-rw-r--r-- | src/backend/access/transam/xlog.c | 12 |
3 files changed, 58 insertions, 16 deletions
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c index a99aa4ced0a..f561e351f22 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.230 2007/03/29 00:15:37 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.231 2007/04/03 04:14:26 tgl Exp $ * * * INTERFACE ROUTINES @@ -1420,7 +1420,13 @@ 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) || tup->t_len > TOAST_TUPLE_THRESHOLD) + if (relation->rd_rel->relkind == RELKIND_TOASTVALUE) + { + /* toast table entries should never be recursively toasted */ + Assert(!HeapTupleHasExternal(tup)); + heaptup = tup; + } + else if (HeapTupleHasExternal(tup) || tup->t_len > TOAST_TUPLE_THRESHOLD) heaptup = toast_insert_or_update(relation, tup, NULL, use_wal, use_fsm); else @@ -1777,7 +1783,12 @@ l1: * because we need to look at the contents of the tuple, but it's OK to * release the content lock on the buffer first. */ - if (HeapTupleHasExternal(&tp)) + if (relation->rd_rel->relkind == RELKIND_TOASTVALUE) + { + /* toast table entries should never be recursively toasted */ + Assert(!HeapTupleHasExternal(&tp)); + } + else if (HeapTupleHasExternal(&tp)) toast_delete(relation, &tp); /* @@ -2075,9 +2086,17 @@ 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. */ - need_toast = (HeapTupleHasExternal(&oldtup) || - HeapTupleHasExternal(newtup) || - newtup->t_len > TOAST_TUPLE_THRESHOLD); + if (relation->rd_rel->relkind == RELKIND_TOASTVALUE) + { + /* toast table entries should never be recursively toasted */ + Assert(!HeapTupleHasExternal(&oldtup)); + Assert(!HeapTupleHasExternal(newtup)); + need_toast = false; + } + else + need_toast = (HeapTupleHasExternal(&oldtup) || + HeapTupleHasExternal(newtup) || + newtup->t_len > TOAST_TUPLE_THRESHOLD); pagefree = PageGetFreeSpace((Page) dp); diff --git a/src/backend/access/heap/tuptoaster.c b/src/backend/access/heap/tuptoaster.c index b1e02e13755..334d6700423 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.72 2007/03/29 00:15:37 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/heap/tuptoaster.c,v 1.73 2007/04/03 04:14:26 tgl Exp $ * * * INTERFACE ROUTINES @@ -292,6 +292,12 @@ toast_delete(Relation rel, HeapTuple oldtup) bool toast_isnull[MaxHeapAttributeNumber]; /* + * We should only ever be called for tuples of plain relations --- + * recursing on a toast rel is bad news. + */ + Assert(rel->rd_rel->relkind == RELKIND_RELATION); + + /* * Get the tuple descriptor and break down the tuple into fields. * * NOTE: it's debatable whether to use heap_deformtuple() here or just @@ -360,6 +366,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup, bool has_nulls = false; Size maxDataLen; + Size hoff; char toast_action[MaxHeapAttributeNumber]; bool toast_isnull[MaxHeapAttributeNumber]; @@ -371,6 +378,12 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup, bool toast_delold[MaxHeapAttributeNumber]; /* + * We should only ever be called for tuples of plain relations --- + * recursing on a toast rel is bad news. + */ + Assert(rel->rd_rel->relkind == RELKIND_RELATION); + + /* * Get the tuple descriptor and break down the tuple(s) into fields. */ tupleDesc = rel->rd_att; @@ -512,15 +525,15 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup, */ /* compute header overhead --- this should match heap_form_tuple() */ - maxDataLen = offsetof(HeapTupleHeaderData, t_bits); + hoff = offsetof(HeapTupleHeaderData, t_bits); if (has_nulls) - maxDataLen += BITMAPLEN(numAttrs); + hoff += BITMAPLEN(numAttrs); if (newtup->t_data->t_infomask & HEAP_HASOID) - maxDataLen += sizeof(Oid); - maxDataLen = MAXALIGN(maxDataLen); - Assert(maxDataLen == newtup->t_data->t_hoff); + hoff += sizeof(Oid); + hoff = MAXALIGN(hoff); + Assert(hoff == newtup->t_data->t_hoff); /* now convert to a limit on the tuple data size */ - maxDataLen = TOAST_TUPLE_TARGET - maxDataLen; + maxDataLen = TOAST_TUPLE_TARGET - hoff; /* * Look for attributes with attstorage 'x' to compress @@ -583,7 +596,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup, /* * Second we look for attributes of attstorage 'x' or 'e' that are still - * inline. + * inline. But skip this if there's no toast table to push them to. */ while (heap_compute_data_size(tupleDesc, toast_values, toast_isnull) > maxDataLen && @@ -695,7 +708,7 @@ toast_insert_or_update(Relation rel, HeapTuple newtup, HeapTuple oldtup, } /* - * Finally we store attributes of type 'm' external + * Finally we store attributes of type 'm' external, if possible. */ while (heap_compute_data_size(tupleDesc, toast_values, toast_isnull) > maxDataLen && diff --git a/src/backend/access/transam/xlog.c b/src/backend/access/transam/xlog.c index 07e95057d0e..f3e02dd6316 100644 --- a/src/backend/access/transam/xlog.c +++ b/src/backend/access/transam/xlog.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.265 2007/03/03 20:02:26 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/transam/xlog.c,v 1.266 2007/04/03 04:14:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -28,6 +28,7 @@ #include "access/multixact.h" #include "access/subtrans.h" #include "access/transam.h" +#include "access/tuptoaster.h" #include "access/twophase.h" #include "access/xact.h" #include "access/xlog_internal.h" @@ -3634,6 +3635,8 @@ WriteControlFile(void) ControlFile->nameDataLen = NAMEDATALEN; ControlFile->indexMaxKeys = INDEX_MAX_KEYS; + ControlFile->toast_max_chunk_size = TOAST_MAX_CHUNK_SIZE; + #ifdef HAVE_INT64_TIMESTAMP ControlFile->enableIntTimes = TRUE; #else @@ -3824,6 +3827,13 @@ ReadControlFile(void) " but the server was compiled with INDEX_MAX_KEYS %d.", ControlFile->indexMaxKeys, INDEX_MAX_KEYS), errhint("It looks like you need to recompile or initdb."))); + if (ControlFile->toast_max_chunk_size != TOAST_MAX_CHUNK_SIZE) + ereport(FATAL, + (errmsg("database files are incompatible with server"), + errdetail("The database cluster was initialized with TOAST_MAX_CHUNK_SIZE %d," + " but the server was compiled with TOAST_MAX_CHUNK_SIZE %d.", + ControlFile->toast_max_chunk_size, (int) TOAST_MAX_CHUNK_SIZE), + errhint("It looks like you need to recompile or initdb."))); #ifdef HAVE_INT64_TIMESTAMP if (ControlFile->enableIntTimes != TRUE) |