diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2009-06-06 02:39:40 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2009-06-06 02:39:40 +0000 |
commit | 356eea24ce6f5e0875b85e938230cfd01ed75ae3 (patch) | |
tree | 36d3e14da16b0ef91998fda4587b750308251149 /src/backend/access/gin/ginentrypage.c | |
parent | 1978d7f13fc2c46c74bf60ee84a5a8557391e53b (diff) | |
download | postgresql-356eea24ce6f5e0875b85e938230cfd01ed75ae3.tar.gz postgresql-356eea24ce6f5e0875b85e938230cfd01ed75ae3.zip |
Fix a serious bug introduced into GIN in 8.4: now that MergeItemPointers()
is supposed to remove duplicate heap TIDs, we have to be sure to reduce the
tuple size and posting-item count accordingly in addItemPointersToTuple().
Failing to do so resulted in the effective injection of garbage TIDs into the
index contents, ie, whatever happened to be in the memory palloc'd for the
new tuple. I'm not sure that this fully explains the index corruption
reported by Tatsuo Ishii, but the test case I'm using no longer fails.
Diffstat (limited to 'src/backend/access/gin/ginentrypage.c')
-rw-r--r-- | src/backend/access/gin/ginentrypage.c | 53 |
1 files changed, 40 insertions, 13 deletions
diff --git a/src/backend/access/gin/ginentrypage.c b/src/backend/access/gin/ginentrypage.c index e16575bc813..f35994db953 100644 --- a/src/backend/access/gin/ginentrypage.c +++ b/src/backend/access/gin/ginentrypage.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/gin/ginentrypage.c,v 1.19 2009/01/01 17:23:34 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/gin/ginentrypage.c,v 1.20 2009/06/06 02:39:40 tgl Exp $ *------------------------------------------------------------------------- */ @@ -20,28 +20,33 @@ #include "utils/rel.h" /* - * forms tuple for entry tree. On leaf page, Index tuple has - * non-traditional layout. Tuple may contain posting list or - * root blocknumber of posting tree. Macros GinIsPostingTre: (itup) / GinSetPostingTree(itup, blkno) + * Form a tuple for entry tree. + * + * 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) * 1) Posting list - * - itup->t_info & INDEX_SIZE_MASK contains size of tuple as usual + * - itup->t_info & INDEX_SIZE_MASK contains total size of tuple as usual * - ItemPointerGetBlockNumber(&itup->t_tid) contains original * size of tuple (without posting list). - * Macroses: GinGetOrigSizePosting(itup) / GinSetOrigSizePosting(itup,n) + * Macros: GinGetOrigSizePosting(itup) / GinSetOrigSizePosting(itup,n) * - ItemPointerGetOffsetNumber(&itup->t_tid) contains number - * of elements in posting list (number of heap itempointer) - * Macroses: GinGetNPosting(itup) / GinSetNPosting(itup,n) - * - After usual part of tuple there is a posting list + * of elements in posting list (number of heap itempointers) + * Macros: GinGetNPosting(itup) / GinSetNPosting(itup,n) + * - After standard part of tuple there is a posting list, ie, array + * of heap itempointers * Macros: GinGetPosting(itup) * 2) Posting tree * - itup->t_info & INDEX_SIZE_MASK contains size of tuple as usual * - ItemPointerGetBlockNumber(&itup->t_tid) contains block number of * root of posting tree - * - ItemPointerGetOffsetNumber(&itup->t_tid) contains magic number GIN_TREE_POSTING + * - ItemPointerGetOffsetNumber(&itup->t_tid) contains magic number + * GIN_TREE_POSTING, which distinguishes this from posting-list case * - * Storage of attributes of tuple are different for single and multicolumn index. - * For single-column index tuple stores only value to be indexed and for - * multicolumn variant it stores two attributes: column number of value and value. + * Attributes of an index tuple are different for single and multicolumn index. + * For single-column case, index tuple stores only value to be indexed. + * For multicolumn case, it stores two attributes: column number of value + * and value. */ IndexTuple GinFormTuple(GinState *ginstate, OffsetNumber attnum, Datum key, ItemPointerData *ipd, uint32 nipd) @@ -90,6 +95,28 @@ GinFormTuple(GinState *ginstate, OffsetNumber attnum, Datum key, ItemPointerData } /* + * Sometimes we reduce the number of posting list items in a tuple after + * having built it with GinFormTuple. This function adjusts the size + * fields to match. + */ +void +GinShortenTuple(IndexTuple itup, uint32 nipd) +{ + uint32 newsize; + + Assert(nipd <= GinGetNPosting(itup)); + + newsize = MAXALIGN(SHORTALIGN(GinGetOrigSizePosting(itup)) + sizeof(ItemPointerData) * nipd); + + Assert(newsize <= (itup->t_info & INDEX_SIZE_MASK)); + + itup->t_info &= ~INDEX_SIZE_MASK; + itup->t_info |= newsize; + + GinSetNPosting(itup, nipd); +} + +/* * Entry tree is a "static", ie tuple never deletes from it, * so we don't use right bound, we use rightest key instead. */ |