diff options
Diffstat (limited to 'src/backend/access/gin/ginentrypage.c')
-rw-r--r-- | src/backend/access/gin/ginentrypage.c | 52 |
1 files changed, 43 insertions, 9 deletions
diff --git a/src/backend/access/gin/ginentrypage.c b/src/backend/access/gin/ginentrypage.c index c4659cde1f0..41f20f72dc3 100644 --- a/src/backend/access/gin/ginentrypage.c +++ b/src/backend/access/gin/ginentrypage.c @@ -8,20 +8,22 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/gin/ginentrypage.c,v 1.21 2009/06/11 14:48:53 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/gin/ginentrypage.c,v 1.21.2.1 2009/10/02 21:14:11 tgl Exp $ *------------------------------------------------------------------------- */ #include "postgres.h" #include "access/gin.h" -#include "access/tuptoaster.h" #include "storage/bufmgr.h" #include "utils/rel.h" /* * Form a tuple for entry tree. * + * If the tuple would be too big to be stored, function throws a suitable + * error if errorTooBig is TRUE, or returns NULL if errorTooBig is FALSE. + * * On leaf pages, Index tuple has non-traditional layout. Tuple may contain * posting list or root blocknumber of posting tree. * Macros: GinIsPostingTree(itup) / GinSetPostingTree(itup, blkno) @@ -49,10 +51,13 @@ * and value. */ IndexTuple -GinFormTuple(GinState *ginstate, OffsetNumber attnum, Datum key, ItemPointerData *ipd, uint32 nipd) +GinFormTuple(Relation index, GinState *ginstate, + OffsetNumber attnum, Datum key, + ItemPointerData *ipd, uint32 nipd, bool errorTooBig) { bool isnull[2] = {FALSE, FALSE}; IndexTuple itup; + uint32 newsize; if (ginstate->oneCol) itup = index_form_tuple(ginstate->origTupdesc, &key, isnull); @@ -69,13 +74,19 @@ GinFormTuple(GinState *ginstate, OffsetNumber attnum, Datum key, ItemPointerData if (nipd > 0) { - uint32 newsize = MAXALIGN(SHORTALIGN(IndexTupleSize(itup)) + sizeof(ItemPointerData) * nipd); - - if (newsize >= INDEX_SIZE_MASK) - return NULL; - - if (newsize > TOAST_INDEX_TARGET && nipd > 1) + newsize = MAXALIGN(SHORTALIGN(IndexTupleSize(itup)) + sizeof(ItemPointerData) * nipd); + if (newsize > Min(INDEX_SIZE_MASK, GinMaxItemSize)) + { + if (errorTooBig) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("index row size %lu exceeds maximum %lu for index \"%s\"", + (unsigned long) newsize, + (unsigned long) Min(INDEX_SIZE_MASK, + GinMaxItemSize), + RelationGetRelationName(index)))); return NULL; + } itup = repalloc(itup, newsize); @@ -89,6 +100,29 @@ GinFormTuple(GinState *ginstate, OffsetNumber attnum, Datum key, ItemPointerData } else { + /* + * Gin tuple without any ItemPointers should be large enough to keep + * one ItemPointer, to prevent inconsistency between + * ginHeapTupleFastCollect and ginEntryInsert called by + * ginHeapTupleInsert. ginHeapTupleFastCollect forms tuple without + * extra pointer to heap, but ginEntryInsert (called for pending list + * cleanup during vacuum) will form the same tuple with one + * ItemPointer. + */ + newsize = MAXALIGN(SHORTALIGN(IndexTupleSize(itup)) + sizeof(ItemPointerData)); + if (newsize > Min(INDEX_SIZE_MASK, GinMaxItemSize)) + { + if (errorTooBig) + ereport(ERROR, + (errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED), + errmsg("index row size %lu exceeds maximum %lu for index \"%s\"", + (unsigned long) newsize, + (unsigned long) Min(INDEX_SIZE_MASK, + GinMaxItemSize), + RelationGetRelationName(index)))); + return NULL; + } + GinSetNPosting(itup, 0); } return itup; |