Skip to content

Commit 9ee4d06

Browse files
committed
Make GiST indexes on-disk compatible with 9.2 again.
The patch that turned XLogRecPtr into a uint64 inadvertently changed the on-disk format of GiST indexes, because the NSN field in the GiST page opaque is an XLogRecPtr. That breaks pg_upgrade. Revert the format of that field back to the two-field struct that XLogRecPtr was before. This is the same we did to LSNs in the page header to avoid changing on-disk format. Bump catversion, as this invalidates any existing GiST indexes built on 9.3devel.
1 parent bba486f commit 9ee4d06

File tree

7 files changed

+40
-25
lines changed

7 files changed

+40
-25
lines changed

src/backend/access/gist/gist.c

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -240,7 +240,7 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
240240
{
241241
/* save old rightlink and NSN */
242242
oldrlink = GistPageGetOpaque(page)->rightlink;
243-
oldnsn = GistPageGetOpaque(page)->nsn;
243+
oldnsn = GistPageGetNSN(page);
244244

245245
dist->buffer = buffer;
246246
dist->block.blkno = BufferGetBlockNumber(buffer);
@@ -364,7 +364,7 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
364364
* F_FOLLOW_RIGHT flags ensure that scans will follow the
365365
* rightlinks until the downlinks are inserted.
366366
*/
367-
GistPageGetOpaque(ptr->page)->nsn = oldnsn;
367+
GistPageSetNSN(ptr->page, oldnsn);
368368
}
369369

370370
START_CRIT_SECTION();
@@ -473,7 +473,7 @@ gistplacetopage(Relation rel, Size freespace, GISTSTATE *giststate,
473473
{
474474
Page leftpg = BufferGetPage(leftchildbuf);
475475

476-
GistPageGetOpaque(leftpg)->nsn = recptr;
476+
GistPageSetNSN(leftpg, recptr);
477477
GistClearFollowRight(leftpg);
478478

479479
PageSetLSN(leftpg, recptr);
@@ -561,7 +561,7 @@ gistdoinsert(Relation r, IndexTuple itup, Size freespace, GISTSTATE *giststate)
561561
}
562562

563563
if (stack->blkno != GIST_ROOT_BLKNO &&
564-
stack->parent->lsn < GistPageGetOpaque(stack->page)->nsn)
564+
stack->parent->lsn < GistPageGetNSN(stack->page))
565565
{
566566
/*
567567
* Concurrent split detected. There's no guarantee that the
@@ -707,8 +707,7 @@ gistdoinsert(Relation r, IndexTuple itup, Size freespace, GISTSTATE *giststate)
707707
*/
708708
}
709709
else if (GistFollowRight(stack->page) ||
710-
stack->parent->lsn <
711-
GistPageGetOpaque(stack->page)->nsn)
710+
stack->parent->lsn < GistPageGetNSN(stack->page))
712711
{
713712
/*
714713
* The page was split while we momentarily unlocked the
@@ -793,7 +792,7 @@ gistFindPath(Relation r, BlockNumber child, OffsetNumber *downlinkoffnum)
793792
if (GistFollowRight(page))
794793
elog(ERROR, "concurrent GiST page split was incomplete");
795794

796-
if (top->parent && top->parent->lsn < GistPageGetOpaque(page)->nsn &&
795+
if (top->parent && top->parent->lsn < GistPageGetNSN(page) &&
797796
GistPageGetOpaque(page)->rightlink != InvalidBlockNumber /* sanity check */ )
798797
{
799798
/*

src/backend/access/gist/gistget.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -263,7 +263,7 @@ gistScanPage(IndexScanDesc scan, GISTSearchItem *pageItem, double *myDistances,
263263
*/
264264
if (!XLogRecPtrIsInvalid(pageItem->data.parentlsn) &&
265265
(GistFollowRight(page) ||
266-
pageItem->data.parentlsn < opaque->nsn) &&
266+
pageItem->data.parentlsn < GistPageGetNSN(page)) &&
267267
opaque->rightlink != InvalidBlockNumber /* sanity check */ )
268268
{
269269
/* There was a page split, follow right link to add pages */

src/backend/access/gist/gistvacuum.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ pushStackIfSplited(Page page, GistBDItem *stack)
114114
GISTPageOpaque opaque = GistPageGetOpaque(page);
115115

116116
if (stack->blkno != GIST_ROOT_BLKNO && !XLogRecPtrIsInvalid(stack->parentlsn) &&
117-
(GistFollowRight(page) || stack->parentlsn < opaque->nsn) &&
117+
(GistFollowRight(page) || stack->parentlsn < GistPageGetNSN(page)) &&
118118
opaque->rightlink != InvalidBlockNumber /* sanity check */ )
119119
{
120120
/* split page detected, install right link to the stack */

src/backend/access/gist/gistxlog.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -66,7 +66,7 @@ gistRedoClearFollowRight(XLogRecPtr lsn, XLogRecord *record, int block_index,
6666
*/
6767
if (lsn >= PageGetLSN(page))
6868
{
69-
GistPageGetOpaque(page)->nsn = lsn;
69+
GistPageSetNSN(page, lsn);
7070
GistClearFollowRight(page);
7171

7272
PageSetLSN(page, lsn);
@@ -271,7 +271,7 @@ gistRedoPageSplitRecord(XLogRecPtr lsn, XLogRecord *record)
271271
if (newpage->header->blkno == GIST_ROOT_BLKNO)
272272
{
273273
GistPageGetOpaque(page)->rightlink = InvalidBlockNumber;
274-
GistPageGetOpaque(page)->nsn = xldata->orignsn;
274+
GistPageSetNSN(page, xldata->orignsn);
275275
GistClearFollowRight(page);
276276
}
277277
else
@@ -280,7 +280,7 @@ gistRedoPageSplitRecord(XLogRecPtr lsn, XLogRecord *record)
280280
GistPageGetOpaque(page)->rightlink = xlrec.page[i + 1].header->blkno;
281281
else
282282
GistPageGetOpaque(page)->rightlink = xldata->origrlink;
283-
GistPageGetOpaque(page)->nsn = xldata->orignsn;
283+
GistPageSetNSN(page, xldata->orignsn);
284284
if (i < xlrec.data->npage - 1 && !isrootsplit &&
285285
xldata->markfollowright)
286286
GistMarkFollowRight(page);

src/include/access/gist.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,10 +64,15 @@
6464
#define F_FOLLOW_RIGHT (1 << 3) /* page to the right has no downlink */
6565

6666
typedef XLogRecPtr GistNSN;
67+
/*
68+
* For on-disk compatibility with pre-9.3 servers, NSN is stored as two
69+
* 32-bit fields on disk, same as LSNs.
70+
*/
71+
typedef PageXLogRecPtr PageGistNSN;
6772

6873
typedef struct GISTPageOpaqueData
6974
{
70-
GistNSN nsn; /* this value must change on page split */
75+
PageGistNSN nsn; /* this value must change on page split */
7176
BlockNumber rightlink; /* next page if any */
7277
uint16 flags; /* see bit definitions above */
7378
uint16 gist_page_id; /* for identification of GiST indexes */
@@ -137,6 +142,9 @@ typedef struct GISTENTRY
137142
#define GistMarkFollowRight(page) ( GistPageGetOpaque(page)->flags |= F_FOLLOW_RIGHT)
138143
#define GistClearFollowRight(page) ( GistPageGetOpaque(page)->flags &= ~F_FOLLOW_RIGHT)
139144

145+
#define GistPageGetNSN(page) ( PageXLogRecPtrGet(GistPageGetOpaque(page)->nsn))
146+
#define GistPageSetNSN(page, val) ( PageXLogRecPtrSet(GistPageGetOpaque(page)->nsn, val))
147+
140148
/*
141149
* Vector of GISTENTRY structs; user-defined methods union and picksplit
142150
* take it as one of their arguments

src/include/catalog/catversion.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,6 @@
5353
*/
5454

5555
/* yyyymmddN */
56-
#define CATALOG_VERSION_NO 201212081
56+
#define CATALOG_VERSION_NO 201301171
5757

5858
#endif

src/include/storage/bufpage.h

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,21 @@ typedef Pointer Page;
8282
typedef uint16 LocationIndex;
8383

8484

85+
/*
86+
* For historical reasons, the 64-bit LSN value is stored as two 32-bit
87+
* values.
88+
*/
89+
typedef struct
90+
{
91+
uint32 xlogid; /* high bits */
92+
uint32 xrecoff; /* low bits */
93+
} PageXLogRecPtr;
94+
95+
#define PageXLogRecPtrGet(val) \
96+
((uint64) (val).xlogid << 32 | (val).xrecoff)
97+
#define PageXLogRecPtrSet(ptr, lsn) \
98+
((ptr).xlogid = (uint32) ((lsn) >> 32), (ptr).xrecoff = (uint32) (lsn))
99+
85100
/*
86101
* disk page organization
87102
*
@@ -120,13 +135,6 @@ typedef uint16 LocationIndex;
120135
* are 15 bits.
121136
*/
122137

123-
/* for historical reasons, the LSN is stored as two 32-bit values. */
124-
typedef struct
125-
{
126-
uint32 xlogid; /* high bits */
127-
uint32 xrecoff; /* low bits */
128-
} PageXLogRecPtr;
129-
130138
typedef struct PageHeaderData
131139
{
132140
/* XXX LSN is member of *any* block, not only page-organized ones */
@@ -319,13 +327,13 @@ typedef PageHeaderData *PageHeader;
319327
/ sizeof(ItemIdData)))
320328

321329
/*
322-
* Additional macros for access to page headers
330+
* Additional macros for access to page headers. (Beware multiple evaluation
331+
* of the arguments!)
323332
*/
324333
#define PageGetLSN(page) \
325-
((uint64) ((PageHeader) (page))->pd_lsn.xlogid << 32 | ((PageHeader) (page))->pd_lsn.xrecoff)
334+
PageXLogRecPtrGet(((PageHeader) (page))->pd_lsn)
326335
#define PageSetLSN(page, lsn) \
327-
(((PageHeader) (page))->pd_lsn.xlogid = (uint32) ((lsn) >> 32), \
328-
((PageHeader) (page))->pd_lsn.xrecoff = (uint32) (lsn))
336+
PageXLogRecPtrSet(((PageHeader) (page))->pd_lsn, lsn)
329337

330338
/* NOTE: only the 16 least significant bits are stored */
331339
#define PageGetTLI(page) \

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