Skip to content

Commit ffbba6e

Browse files
committed
Fix another palloc in critical section.
Also add a regression test for a GIN index with enough items with the same key, so that a GIN posting tree gets created. Apparently none of the existing GIN tests were large enough for that. This code is new, no backpatching required.
1 parent 6862ca6 commit ffbba6e

File tree

3 files changed

+48
-15
lines changed

3 files changed

+48
-15
lines changed

src/backend/access/gin/gindatapage.c

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1706,30 +1706,24 @@ createPostingTree(Relation index, ItemPointerData *items, uint32 nitems,
17061706
{
17071707
BlockNumber blkno;
17081708
Buffer buffer;
1709+
Page tmppage;
17091710
Page page;
17101711
Pointer ptr;
17111712
int nrootitems;
17121713
int rootsize;
17131714

1714-
/*
1715-
* Create the root page.
1716-
*/
1717-
buffer = GinNewBuffer(index);
1718-
page = BufferGetPage(buffer);
1719-
blkno = BufferGetBlockNumber(buffer);
1720-
1721-
START_CRIT_SECTION();
1722-
1723-
GinInitPage(page, GIN_DATA | GIN_LEAF | GIN_COMPRESSED, BLCKSZ);
1724-
GinPageGetOpaque(page)->rightlink = InvalidBlockNumber;
1715+
/* Construct the new root page in memory first. */
1716+
tmppage = (Page) palloc(BLCKSZ);
1717+
GinInitPage(tmppage, GIN_DATA | GIN_LEAF | GIN_COMPRESSED, BLCKSZ);
1718+
GinPageGetOpaque(tmppage)->rightlink = InvalidBlockNumber;
17251719

17261720
/*
17271721
* Write as many of the items to the root page as fit. In segments
17281722
* of max GinPostingListSegmentMaxSize bytes each.
17291723
*/
17301724
nrootitems = 0;
17311725
rootsize = 0;
1732-
ptr = (Pointer) GinDataLeafPageGetPostingList(page);
1726+
ptr = (Pointer) GinDataLeafPageGetPostingList(tmppage);
17331727
while (nrootitems < nitems)
17341728
{
17351729
GinPostingList *segment;
@@ -1750,10 +1744,19 @@ createPostingTree(Relation index, ItemPointerData *items, uint32 nitems,
17501744
nrootitems += npacked;
17511745
pfree(segment);
17521746
}
1753-
GinDataLeafPageSetPostingListSize(page, rootsize);
1754-
MarkBufferDirty(buffer);
1747+
GinDataLeafPageSetPostingListSize(tmppage, rootsize);
17551748

1756-
elog(DEBUG2, "created GIN posting tree with %d items", nrootitems);
1749+
/*
1750+
* All set. Get a new physical page, and copy the in-memory page to it.
1751+
*/
1752+
buffer = GinNewBuffer(index);
1753+
page = BufferGetPage(buffer);
1754+
blkno = BufferGetBlockNumber(buffer);
1755+
1756+
START_CRIT_SECTION();
1757+
1758+
PageRestoreTempPage(tmppage, page);
1759+
MarkBufferDirty(buffer);
17571760

17581761
if (RelationNeedsWAL(index))
17591762
{
@@ -1787,6 +1790,8 @@ createPostingTree(Relation index, ItemPointerData *items, uint32 nitems,
17871790
if (buildStats)
17881791
buildStats->nDataPages++;
17891792

1793+
elog(DEBUG2, "created GIN posting tree with %d items", nrootitems);
1794+
17901795
/*
17911796
* Add any remaining TIDs to the newly-created posting tree.
17921797
*/

src/test/regress/expected/create_index.out

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2221,6 +2221,20 @@ RESET enable_seqscan;
22212221
RESET enable_indexscan;
22222222
RESET enable_bitmapscan;
22232223
--
2224+
-- Try a GIN index with a lot of items with same key. (GIN creates a posting
2225+
-- tree when there are enough duplicates)
2226+
--
2227+
CREATE TABLE array_gin_test (a int[]);
2228+
INSERT INTO array_gin_test SELECT ARRAY[1, g%5, g] FROM generate_series(1, 10000) g;
2229+
CREATE INDEX array_gin_test_idx ON array_gin_test USING gin (a);
2230+
SELECT COUNT(*) FROM array_gin_test WHERE a @> '{2}';
2231+
count
2232+
-------
2233+
2000
2234+
(1 row)
2235+
2236+
DROP TABLE array_gin_test;
2237+
--
22242238
-- HASH
22252239
--
22262240
CREATE INDEX hash_i4_index ON hash_i4_heap USING hash (random int4_ops);

src/test/regress/sql/create_index.sql

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -636,6 +636,20 @@ RESET enable_seqscan;
636636
RESET enable_indexscan;
637637
RESET enable_bitmapscan;
638638

639+
--
640+
-- Try a GIN index with a lot of items with same key. (GIN creates a posting
641+
-- tree when there are enough duplicates)
642+
--
643+
CREATE TABLE array_gin_test (a int[]);
644+
645+
INSERT INTO array_gin_test SELECT ARRAY[1, g%5, g] FROM generate_series(1, 10000) g;
646+
647+
CREATE INDEX array_gin_test_idx ON array_gin_test USING gin (a);
648+
649+
SELECT COUNT(*) FROM array_gin_test WHERE a @> '{2}';
650+
651+
DROP TABLE array_gin_test;
652+
639653
--
640654
-- HASH
641655
--

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