aboutsummaryrefslogtreecommitdiff
path: root/src/backend/access/gin/ginentrypage.c
diff options
context:
space:
mode:
authorTom Lane <tgl@sss.pgh.pa.us>2009-10-02 21:14:04 +0000
committerTom Lane <tgl@sss.pgh.pa.us>2009-10-02 21:14:04 +0000
commite66d714386cd3040b328d6a894802d01dd1d395d (patch)
tree9971031124162948d5e1d622f9dff8f59d9049d1 /src/backend/access/gin/ginentrypage.c
parentd691cb91415542e398aa6ad015ea6a5eab53ab0d (diff)
downloadpostgresql-e66d714386cd3040b328d6a894802d01dd1d395d.tar.gz
postgresql-e66d714386cd3040b328d6a894802d01dd1d395d.zip
Make sure that GIN fast-insert and regular code paths enforce the same
tuple size limit. Improve the error message for index-tuple-too-large so that it includes the actual size, the limit, and the index name. Sync with the btree occurrences of the same error. Back-patch to 8.4 because it appears that the out-of-sync problem is occurring in the field. Teodor and Tom
Diffstat (limited to 'src/backend/access/gin/ginentrypage.c')
-rw-r--r--src/backend/access/gin/ginentrypage.c52
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..87cc407233c 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.22 2009/10/02 21:14:04 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;