Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit356eea2

Browse files
committed
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 thetuple size and posting-item count accordingly in addItemPointersToTuple().Failing to do so resulted in the effective injection of garbage TIDs into theindex contents, ie, whatever happened to be in the memory palloc'd for thenew tuple. I'm not sure that this fully explains the index corruptionreported by Tatsuo Ishii, but the test case I'm using no longer fails.
1 parent1978d7f commit356eea2

File tree

4 files changed

+62
-26
lines changed

4 files changed

+62
-26
lines changed

‎src/backend/access/gin/gindatapage.c

Lines changed: 10 additions & 4 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/gindatapage.c,v 1.14 2009/03/24 20:17:10 tgl Exp $
11+
*$PostgreSQL: pgsql/src/backend/access/gin/gindatapage.c,v 1.15 2009/06/06 02:39:40 tgl Exp $
1212
*-------------------------------------------------------------------------
1313
*/
1414

@@ -32,10 +32,14 @@ compareItemPointers(ItemPointer a, ItemPointer b)
3232
}
3333

3434
/*
35-
* Merge two ordered array of itempointer
35+
* Merge two ordered arrays of itempointers, eliminating any duplicates.
36+
* Returns the number of items in the result.
37+
* Caller is responsible that there is enough space at *dst.
3638
*/
37-
void
38-
MergeItemPointers(ItemPointerData*dst,ItemPointerData*a,uint32na,ItemPointerData*b,uint32nb)
39+
uint32
40+
MergeItemPointers(ItemPointerData*dst,
41+
ItemPointerData*a,uint32na,
42+
ItemPointerData*b,uint32nb)
3943
{
4044
ItemPointerData*dptr=dst;
4145
ItemPointerData*aptr=a,
@@ -62,6 +66,8 @@ MergeItemPointers(ItemPointerData *dst, ItemPointerData *a, uint32 na, ItemPoint
6266

6367
while (bptr-b<nb)
6468
*dptr++=*bptr++;
69+
70+
returndptr-dst;
6571
}
6672

6773
/*

‎src/backend/access/gin/ginentrypage.c

Lines changed: 40 additions & 13 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/ginentrypage.c,v 1.19 2009/01/01 17:23:34 momjian Exp $
11+
*$PostgreSQL: pgsql/src/backend/access/gin/ginentrypage.c,v 1.20 2009/06/06 02:39:40 tgl Exp $
1212
*-------------------------------------------------------------------------
1313
*/
1414

@@ -20,28 +20,33 @@
2020
#include"utils/rel.h"
2121

2222
/*
23-
* forms tuple for entry tree. On leaf page, Index tuple has
24-
* non-traditional layout. Tuple may contain posting list or
25-
* root blocknumber of posting tree. Macros GinIsPostingTre: (itup) / GinSetPostingTree(itup, blkno)
23+
* Form a tuple for entry tree.
24+
*
25+
* On leaf pages, Index tuple has non-traditional layout. Tuple may contain
26+
* posting list or root blocknumber of posting tree.
27+
* Macros: GinIsPostingTree(itup) / GinSetPostingTree(itup, blkno)
2628
* 1) Posting list
27-
*- itup->t_info & INDEX_SIZE_MASK contains size of tuple as usual
29+
*- itup->t_info & INDEX_SIZE_MASK containstotalsize of tuple as usual
2830
*- ItemPointerGetBlockNumber(&itup->t_tid) contains original
2931
* size of tuple (without posting list).
30-
*Macroses: GinGetOrigSizePosting(itup) / GinSetOrigSizePosting(itup,n)
32+
*Macros: GinGetOrigSizePosting(itup) / GinSetOrigSizePosting(itup,n)
3133
*- ItemPointerGetOffsetNumber(&itup->t_tid) contains number
32-
* of elements in posting list (number of heap itempointer)
33-
* Macroses: GinGetNPosting(itup) / GinSetNPosting(itup,n)
34-
*- After usual part of tuple there is a posting list
34+
* of elements in posting list (number of heap itempointers)
35+
* Macros: GinGetNPosting(itup) / GinSetNPosting(itup,n)
36+
*- After standard part of tuple there is a posting list, ie, array
37+
* of heap itempointers
3538
* Macros: GinGetPosting(itup)
3639
* 2) Posting tree
3740
*- itup->t_info & INDEX_SIZE_MASK contains size of tuple as usual
3841
*- ItemPointerGetBlockNumber(&itup->t_tid) contains block number of
3942
* root of posting tree
40-
*- ItemPointerGetOffsetNumber(&itup->t_tid) contains magic number GIN_TREE_POSTING
43+
*- ItemPointerGetOffsetNumber(&itup->t_tid) contains magic number
44+
* GIN_TREE_POSTING, which distinguishes this from posting-list case
4145
*
42-
* Storage of attributes of tuple are different for single and multicolumn index.
43-
* For single-column index tuple stores only value to be indexed and for
44-
* multicolumn variant it stores two attributes: column number of value and value.
46+
* Attributes of an index tuple are different for single and multicolumn index.
47+
* For single-column case, index tuple stores only value to be indexed.
48+
* For multicolumn case, it stores two attributes: column number of value
49+
* and value.
4550
*/
4651
IndexTuple
4752
GinFormTuple(GinState*ginstate,OffsetNumberattnum,Datumkey,ItemPointerData*ipd,uint32nipd)
@@ -89,6 +94,28 @@ GinFormTuple(GinState *ginstate, OffsetNumber attnum, Datum key, ItemPointerData
8994
returnitup;
9095
}
9196

97+
/*
98+
* Sometimes we reduce the number of posting list items in a tuple after
99+
* having built it with GinFormTuple. This function adjusts the size
100+
* fields to match.
101+
*/
102+
void
103+
GinShortenTuple(IndexTupleitup,uint32nipd)
104+
{
105+
uint32newsize;
106+
107+
Assert(nipd <=GinGetNPosting(itup));
108+
109+
newsize=MAXALIGN(SHORTALIGN(GinGetOrigSizePosting(itup))+sizeof(ItemPointerData)*nipd);
110+
111+
Assert(newsize <= (itup->t_info&INDEX_SIZE_MASK));
112+
113+
itup->t_info &= ~INDEX_SIZE_MASK;
114+
itup->t_info |=newsize;
115+
116+
GinSetNPosting(itup,nipd);
117+
}
118+
92119
/*
93120
* Entry tree is a "static", ie tuple never deletes from it,
94121
* so we don't use right bound, we use rightest key instead.

‎src/backend/access/gin/gininsert.c

Lines changed: 9 additions & 7 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.20 2009/03/24 22:06:03 tgl Exp $
11+
*$PostgreSQL: pgsql/src/backend/access/gin/gininsert.c,v 1.21 2009/06/06 02:39:40 tgl Exp $
1212
*-------------------------------------------------------------------------
1313
*/
1414

@@ -102,17 +102,19 @@ addItemPointersToTuple(Relation index, GinState *ginstate, GinBtreeStack *stack,
102102
{
103103
Datumkey=gin_index_getattr(ginstate,old);
104104
OffsetNumberattnum=gintuple_get_attrnum(ginstate,old);
105-
IndexTupleres=GinFormTuple(ginstate,attnum,key,NULL,nitem+GinGetNPosting(old));
105+
IndexTupleres=GinFormTuple(ginstate,attnum,key,
106+
NULL,nitem+GinGetNPosting(old));
106107

107108
if (res)
108109
{
109110
/* good, small enough */
110-
MergeItemPointers(GinGetPosting(res),
111-
GinGetPosting(old),GinGetNPosting(old),
112-
items,nitem
113-
);
111+
uint32newnitem;
114112

115-
GinSetNPosting(res,nitem+GinGetNPosting(old));
113+
newnitem=MergeItemPointers(GinGetPosting(res),
114+
GinGetPosting(old),GinGetNPosting(old),
115+
items,nitem);
116+
/* merge might have eliminated some duplicate items */
117+
GinShortenTuple(res,newnitem);
116118
}
117119
else
118120
{

‎src/include/access/gin.h

Lines changed: 3 additions & 2 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.32 2009/06/05 18:50:47 tgl Exp $
7+
*$PostgreSQL: pgsql/src/include/access/gin.h,v 1.33 2009/06/06 02:39:40 tgl Exp $
88
*--------------------------------------------------------------------------
99
*/
1010
#ifndefGIN_H
@@ -435,14 +435,15 @@ extern void findParents(GinBtree btree, GinBtreeStack *stack, BlockNumber rootBl
435435
/* ginentrypage.c */
436436
externIndexTupleGinFormTuple(GinState*ginstate,OffsetNumberattnum,Datumkey,
437437
ItemPointerData*ipd,uint32nipd);
438+
externvoidGinShortenTuple(IndexTupleitup,uint32nipd);
438439
externvoidprepareEntryScan(GinBtreebtree,Relationindex,OffsetNumberattnum,
439440
Datumvalue,GinState*ginstate);
440441
externvoidentryFillRoot(GinBtreebtree,Bufferroot,Bufferlbuf,Bufferrbuf);
441442
externIndexTupleginPageGetLinkItup(Bufferbuf);
442443

443444
/* gindatapage.c */
444445
externintcompareItemPointers(ItemPointera,ItemPointerb);
445-
externvoidMergeItemPointers(ItemPointerData*dst,
446+
externuint32MergeItemPointers(ItemPointerData*dst,
446447
ItemPointerData*a,uint32na,
447448
ItemPointerData*b,uint32nb);
448449

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp