Skip to content

Commit e66d714

Browse files
committed
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
1 parent d691cb9 commit e66d714

File tree

7 files changed

+72
-41
lines changed

7 files changed

+72
-41
lines changed

src/backend/access/gin/ginentrypage.c

Lines changed: 43 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -8,20 +8,22 @@
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/gin/ginentrypage.c,v 1.21 2009/06/11 14:48:53 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/gin/ginentrypage.c,v 1.22 2009/10/02 21:14:04 tgl Exp $
1212
*-------------------------------------------------------------------------
1313
*/
1414

1515
#include "postgres.h"
1616

1717
#include "access/gin.h"
18-
#include "access/tuptoaster.h"
1918
#include "storage/bufmgr.h"
2019
#include "utils/rel.h"
2120

2221
/*
2322
* Form a tuple for entry tree.
2423
*
24+
* If the tuple would be too big to be stored, function throws a suitable
25+
* error if errorTooBig is TRUE, or returns NULL if errorTooBig is FALSE.
26+
*
2527
* On leaf pages, Index tuple has non-traditional layout. Tuple may contain
2628
* posting list or root blocknumber of posting tree.
2729
* Macros: GinIsPostingTree(itup) / GinSetPostingTree(itup, blkno)
@@ -49,10 +51,13 @@
4951
* and value.
5052
*/
5153
IndexTuple
52-
GinFormTuple(GinState *ginstate, OffsetNumber attnum, Datum key, ItemPointerData *ipd, uint32 nipd)
54+
GinFormTuple(Relation index, GinState *ginstate,
55+
OffsetNumber attnum, Datum key,
56+
ItemPointerData *ipd, uint32 nipd, bool errorTooBig)
5357
{
5458
bool isnull[2] = {FALSE, FALSE};
5559
IndexTuple itup;
60+
uint32 newsize;
5661

5762
if (ginstate->oneCol)
5863
itup = index_form_tuple(ginstate->origTupdesc, &key, isnull);
@@ -69,13 +74,19 @@ GinFormTuple(GinState *ginstate, OffsetNumber attnum, Datum key, ItemPointerData
6974

7075
if (nipd > 0)
7176
{
72-
uint32 newsize = MAXALIGN(SHORTALIGN(IndexTupleSize(itup)) + sizeof(ItemPointerData) * nipd);
73-
74-
if (newsize >= INDEX_SIZE_MASK)
75-
return NULL;
76-
77-
if (newsize > TOAST_INDEX_TARGET && nipd > 1)
77+
newsize = MAXALIGN(SHORTALIGN(IndexTupleSize(itup)) + sizeof(ItemPointerData) * nipd);
78+
if (newsize > Min(INDEX_SIZE_MASK, GinMaxItemSize))
79+
{
80+
if (errorTooBig)
81+
ereport(ERROR,
82+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
83+
errmsg("index row size %lu exceeds maximum %lu for index \"%s\"",
84+
(unsigned long) newsize,
85+
(unsigned long) Min(INDEX_SIZE_MASK,
86+
GinMaxItemSize),
87+
RelationGetRelationName(index))));
7888
return NULL;
89+
}
7990

8091
itup = repalloc(itup, newsize);
8192

@@ -89,6 +100,29 @@ GinFormTuple(GinState *ginstate, OffsetNumber attnum, Datum key, ItemPointerData
89100
}
90101
else
91102
{
103+
/*
104+
* Gin tuple without any ItemPointers should be large enough to keep
105+
* one ItemPointer, to prevent inconsistency between
106+
* ginHeapTupleFastCollect and ginEntryInsert called by
107+
* ginHeapTupleInsert. ginHeapTupleFastCollect forms tuple without
108+
* extra pointer to heap, but ginEntryInsert (called for pending list
109+
* cleanup during vacuum) will form the same tuple with one
110+
* ItemPointer.
111+
*/
112+
newsize = MAXALIGN(SHORTALIGN(IndexTupleSize(itup)) + sizeof(ItemPointerData));
113+
if (newsize > Min(INDEX_SIZE_MASK, GinMaxItemSize))
114+
{
115+
if (errorTooBig)
116+
ereport(ERROR,
117+
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
118+
errmsg("index row size %lu exceeds maximum %lu for index \"%s\"",
119+
(unsigned long) newsize,
120+
(unsigned long) Min(INDEX_SIZE_MASK,
121+
GinMaxItemSize),
122+
RelationGetRelationName(index))));
123+
return NULL;
124+
}
125+
92126
GinSetNPosting(itup, 0);
93127
}
94128
return itup;

src/backend/access/gin/ginfast.c

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
* Portions Copyright (c) 1994, Regents of the University of California
1212
*
1313
* IDENTIFICATION
14-
* $PostgreSQL: pgsql/src/backend/access/gin/ginfast.c,v 1.4 2009/09/15 20:31:30 tgl Exp $
14+
* $PostgreSQL: pgsql/src/backend/access/gin/ginfast.c,v 1.5 2009/10/02 21:14:04 tgl Exp $
1515
*
1616
*-------------------------------------------------------------------------
1717
*/
@@ -20,7 +20,6 @@
2020

2121
#include "access/genam.h"
2222
#include "access/gin.h"
23-
#include "access/tuptoaster.h"
2423
#include "catalog/index.h"
2524
#include "commands/vacuum.h"
2625
#include "miscadmin.h"
@@ -465,16 +464,10 @@ ginHeapTupleFastCollect(Relation index, GinState *ginstate,
465464
*/
466465
for (i = 0; i < nentries; i++)
467466
{
468-
int32 tupsize;
469-
470-
collector->tuples[collector->ntuples + i] = GinFormTuple(ginstate, attnum, entries[i], NULL, 0);
467+
collector->tuples[collector->ntuples + i] =
468+
GinFormTuple(index, ginstate, attnum, entries[i], NULL, 0, true);
471469
collector->tuples[collector->ntuples + i]->t_tid = *item;
472-
tupsize = IndexTupleSize(collector->tuples[collector->ntuples + i]);
473-
474-
if (tupsize > TOAST_INDEX_TARGET || tupsize >= GinMaxItemSize)
475-
elog(ERROR, "huge tuple");
476-
477-
collector->sumsize += tupsize;
470+
collector->sumsize += IndexTupleSize(collector->tuples[collector->ntuples + i]);
478471
}
479472

480473
collector->ntuples += nentries;

src/backend/access/gin/gininsert.c

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/gin/gininsert.c,v 1.23 2009/07/29 20:56:17 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/gin/gininsert.c,v 1.24 2009/10/02 21:14:04 tgl Exp $
1212
*-------------------------------------------------------------------------
1313
*/
1414

@@ -102,8 +102,9 @@ addItemPointersToTuple(Relation index, GinState *ginstate, GinBtreeStack *stack,
102102
{
103103
Datum key = gin_index_getattr(ginstate, old);
104104
OffsetNumber attnum = gintuple_get_attrnum(ginstate, old);
105-
IndexTuple res = GinFormTuple(ginstate, attnum, key,
106-
NULL, nitem + GinGetNPosting(old));
105+
IndexTuple res = GinFormTuple(index, ginstate, attnum, key,
106+
NULL, nitem + GinGetNPosting(old),
107+
false);
107108

108109
if (res)
109110
{
@@ -122,7 +123,7 @@ addItemPointersToTuple(Relation index, GinState *ginstate, GinBtreeStack *stack,
122123
GinPostingTreeScan *gdi;
123124

124125
/* posting list becomes big, so we need to make posting's tree */
125-
res = GinFormTuple(ginstate, attnum, key, NULL, 0);
126+
res = GinFormTuple(index, ginstate, attnum, key, NULL, 0, true);
126127
postingRoot = createPostingTree(index, GinGetPosting(old), GinGetNPosting(old));
127128
GinSetPostingTree(res, postingRoot);
128129

@@ -185,13 +186,12 @@ ginEntryInsert(Relation index, GinState *ginstate,
185186
}
186187
else
187188
{
188-
/* We suppose, that tuple can store at list one itempointer */
189-
itup = GinFormTuple(ginstate, attnum, value, items, 1);
190-
if (itup == NULL || IndexTupleSize(itup) >= GinMaxItemSize)
191-
elog(ERROR, "huge tuple");
189+
/* We suppose that tuple can store at least one itempointer */
190+
itup = GinFormTuple(index, ginstate, attnum, value, items, 1, true);
192191

193192
if (nitem > 1)
194193
{
194+
/* Add the rest, making a posting tree if necessary */
195195
IndexTuple previtup = itup;
196196

197197
itup = addItemPointersToTuple(index, ginstate, stack, previtup, items + 1, nitem - 1, isBuild);

src/backend/access/gin/ginvacuum.c

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
* Portions Copyright (c) 1994, Regents of the University of California
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/gin/ginvacuum.c,v 1.30 2009/06/11 14:48:53 momjian Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/gin/ginvacuum.c,v 1.31 2009/10/02 21:14:04 tgl Exp $
1212
*-------------------------------------------------------------------------
1313
*/
1414

@@ -564,7 +564,8 @@ ginVacuumEntryPage(GinVacuumState *gvs, Buffer buffer, BlockNumber *roots, uint3
564564

565565
value = gin_index_getattr(&gvs->ginstate, itup);
566566
attnum = gintuple_get_attrnum(&gvs->ginstate, itup);
567-
itup = GinFormTuple(&gvs->ginstate, attnum, value, GinGetPosting(itup), newN);
567+
itup = GinFormTuple(gvs->index, &gvs->ginstate, attnum, value,
568+
GinGetPosting(itup), newN, true);
568569
PageIndexTupleDelete(tmppage, i);
569570

570571
if (PageAddItem(tmppage, (Item) itup, IndexTupleSize(itup), i, false, false) != i)

src/backend/access/nbtree/nbtinsert.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.173 2009/08/01 20:59:17 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtinsert.c,v 1.174 2009/10/02 21:14:04 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -518,9 +518,10 @@ _bt_findinsertloc(Relation rel,
518518
if (itemsz > BTMaxItemSize(page))
519519
ereport(ERROR,
520520
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
521-
errmsg("index row size %lu exceeds btree maximum, %lu",
521+
errmsg("index row size %lu exceeds maximum %lu for index \"%s\"",
522522
(unsigned long) itemsz,
523-
(unsigned long) BTMaxItemSize(page)),
523+
(unsigned long) BTMaxItemSize(page),
524+
RelationGetRelationName(rel)),
524525
errhint("Values larger than 1/3 of a buffer page cannot be indexed.\n"
525526
"Consider a function index of an MD5 hash of the value, "
526527
"or use full text indexing.")));

src/backend/access/nbtree/nbtsort.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@
5959
* Portions Copyright (c) 1994, Regents of the University of California
6060
*
6161
* IDENTIFICATION
62-
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsort.c,v 1.119 2009/01/01 17:23:36 momjian Exp $
62+
* $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsort.c,v 1.120 2009/10/02 21:14:04 tgl Exp $
6363
*
6464
*-------------------------------------------------------------------------
6565
*/
@@ -480,9 +480,10 @@ _bt_buildadd(BTWriteState *wstate, BTPageState *state, IndexTuple itup)
480480
if (itupsz > BTMaxItemSize(npage))
481481
ereport(ERROR,
482482
(errcode(ERRCODE_PROGRAM_LIMIT_EXCEEDED),
483-
errmsg("index row size %lu exceeds btree maximum, %lu",
483+
errmsg("index row size %lu exceeds maximum %lu for index \"%s\"",
484484
(unsigned long) itupsz,
485-
(unsigned long) BTMaxItemSize(npage)),
485+
(unsigned long) BTMaxItemSize(npage),
486+
RelationGetRelationName(wstate->index)),
486487
errhint("Values larger than 1/3 of a buffer page cannot be indexed.\n"
487488
"Consider a function index of an MD5 hash of the value, "
488489
"or use full text indexing.")));

src/include/access/gin.h

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
*
55
* Copyright (c) 2006-2009, PostgreSQL Global Development Group
66
*
7-
* $PostgreSQL: pgsql/src/include/access/gin.h,v 1.34 2009/06/11 14:49:08 momjian Exp $
7+
* $PostgreSQL: pgsql/src/include/access/gin.h,v 1.35 2009/10/02 21:14:04 tgl Exp $
88
*--------------------------------------------------------------------------
99
*/
1010
#ifndef GIN_H
@@ -165,8 +165,8 @@ typedef struct
165165
#define GinGetPosting(itup) ( (ItemPointer)(( ((char*)(itup)) + SHORTALIGN(GinGetOrigSizePosting(itup)) )) )
166166

167167
#define GinMaxItemSize \
168-
((BLCKSZ - SizeOfPageHeaderData - \
169-
MAXALIGN(sizeof(GinPageOpaqueData))) / 3 - sizeof(ItemIdData))
168+
MAXALIGN_DOWN(((BLCKSZ - SizeOfPageHeaderData - \
169+
MAXALIGN(sizeof(GinPageOpaqueData))) / 3 - sizeof(ItemIdData)))
170170

171171

172172
/*
@@ -434,8 +434,9 @@ extern void ginInsertValue(GinBtree btree, GinBtreeStack *stack);
434434
extern void findParents(GinBtree btree, GinBtreeStack *stack, BlockNumber rootBlkno);
435435

436436
/* ginentrypage.c */
437-
extern IndexTuple GinFormTuple(GinState *ginstate, OffsetNumber attnum, Datum key,
438-
ItemPointerData *ipd, uint32 nipd);
437+
extern IndexTuple GinFormTuple(Relation index, GinState *ginstate,
438+
OffsetNumber attnum, Datum key,
439+
ItemPointerData *ipd, uint32 nipd, bool errorTooBig);
439440
extern void GinShortenTuple(IndexTuple itup, uint32 nipd);
440441
extern void prepareEntryScan(GinBtree btree, Relation index, OffsetNumber attnum,
441442
Datum value, GinState *ginstate);

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy