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

Commit614167c

Browse files
committed
Fix bugs in GIN "fast scan" with partial match.
There were a couple of bugs here. First, if the fuzzy limit was exceeded,the loop in entryGetItem might drop out too soon if a whole block needs tobe skipped because it's < advancePast ("continue" in a while-loop checks theloop condition too). Secondly, the loop checked when stepping to a new pagethat there is at least one offset on the page < advancePast, but we cannotrely on that on subsequent calls of entryGetItem, because advancePast mightchange in between. That caused the skipping loop to read bogus items in theTbmIterateResult's offset array.First item and fix by Alexander Korotkov, second bug pointed out by Fabríziode Royes Mello, by a small variation of Alexander's test query.
1 parentef29a88 commit614167c

File tree

1 file changed

+32
-23
lines changed

1 file changed

+32
-23
lines changed

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

Lines changed: 32 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -729,11 +729,18 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
729729
/* A bitmap result */
730730
BlockNumberadvancePastBlk=GinItemPointerGetBlockNumber(&advancePast);
731731
OffsetNumberadvancePastOff=GinItemPointerGetOffsetNumber(&advancePast);
732+
boolgotitem= false;
732733

733734
do
734735
{
735-
if (entry->matchResult==NULL||
736-
entry->offset >=entry->matchResult->ntuples)
736+
/*
737+
* If we've exhausted all items on this block, move to next block
738+
* in the bitmap.
739+
*/
740+
while (entry->matchResult==NULL||
741+
(entry->matchResult->ntuples >=0&&
742+
entry->offset >=entry->matchResult->ntuples)||
743+
entry->matchResult->blockno<advancePastBlk)
737744
{
738745
entry->matchResult=tbm_iterate(entry->matchIterator);
739746

@@ -746,18 +753,6 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
746753
break;
747754
}
748755

749-
/*
750-
* If all the matches on this page are <= advancePast, skip
751-
* to next page.
752-
*/
753-
if (entry->matchResult->blockno<advancePastBlk||
754-
(entry->matchResult->blockno==advancePastBlk&&
755-
entry->matchResult->offsets[entry->offset] <=advancePastOff))
756-
{
757-
entry->offset=entry->matchResult->ntuples;
758-
continue;
759-
}
760-
761756
/*
762757
* Reset counter to the beginning of entry->matchResult. Note:
763758
* entry->offset is still greater than matchResult->ntuples if
@@ -766,30 +761,43 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
766761
*/
767762
entry->offset=0;
768763
}
764+
if (entry->isFinished)
765+
break;
769766

767+
/*
768+
* We're now on the first page after advancePast which has any
769+
* items on it. If it's a lossy result, return that.
770+
*/
770771
if (entry->matchResult->ntuples<0)
771772
{
772-
/*
773-
* lossy result, so we need to check the whole page
774-
*/
775773
ItemPointerSetLossyPage(&entry->curItem,
776774
entry->matchResult->blockno);
777775

778776
/*
779777
* We might as well fall out of the loop; we could not
780778
* estimate number of results on this page to support correct
781-
* reducing of result even if it's enabled
779+
* reducing of result even if it's enabled.
782780
*/
781+
gotitem= true;
783782
break;
784783
}
785-
784+
/*
785+
* Not a lossy page. Skip over any offsets <= advancePast, and
786+
* return that.
787+
*/
786788
if (entry->matchResult->blockno==advancePastBlk)
787789
{
788790
/*
789-
* Skip to the right offset on this page. We already checked
790-
* in above loop that there is at least one item > advancePast
791-
* on the page.
791+
* First, do a quick check against the last offset on the page.
792+
* If that's > advancePast, so are all the other offsets.
792793
*/
794+
if (entry->matchResult->offsets[entry->matchResult->ntuples-1] <=advancePastOff)
795+
{
796+
entry->offset=entry->matchResult->ntuples;
797+
continue;
798+
}
799+
800+
/* Otherwise scan to find the first item > advancePast */
793801
while (entry->matchResult->offsets[entry->offset] <=advancePastOff)
794802
entry->offset++;
795803
}
@@ -798,7 +806,8 @@ entryGetItem(GinState *ginstate, GinScanEntry entry,
798806
entry->matchResult->blockno,
799807
entry->matchResult->offsets[entry->offset]);
800808
entry->offset++;
801-
}while (entry->reduceResult== TRUE&&dropItem(entry));
809+
gotitem= true;
810+
}while (!gotitem|| (entry->reduceResult== TRUE&&dropItem(entry)));
802811
}
803812
elseif (!BufferIsValid(entry->buffer))
804813
{

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp