/* A bitmap result */
BlockNumber advancePastBlk = GinItemPointerGetBlockNumber(&advancePast);
OffsetNumber advancePastOff = GinItemPointerGetOffsetNumber(&advancePast);
- bool gotitem = false;
- do
+ for (;;)
{
/*
* If we've exhausted all items on this block, move to next block
* estimate number of results on this page to support correct
* reducing of result even if it's enabled.
*/
- gotitem = true;
break;
}
/*
* First, do a quick check against the last offset on the
* page. If that's > advancePast, so are all the other
- * offsets.
+ * offsets, so just go back to the top to get the next page.
*/
if (entry->matchResult->offsets[entry->matchResult->ntuples - 1] <= advancePastOff)
{
entry->matchResult->blockno,
entry->matchResult->offsets[entry->offset]);
entry->offset++;
- gotitem = true;
- } while (!gotitem || (entry->reduceResult == true && dropItem(entry)));
+
+ /* Done unless we need to reduce the result */
+ if (!entry->reduceResult || !dropItem(entry))
+ break;
+ }
}
else if (!BufferIsValid(entry->buffer))
{
* A posting list from an entry tuple, or the last page of a posting
* tree.
*/
- do
+ for (;;)
{
if (entry->offset >= entry->nlist)
{
}
entry->curItem = entry->list[entry->offset++];
- } while (ginCompareItemPointers(&entry->curItem, &advancePast) <= 0);
- /* XXX: shouldn't we apply the fuzzy search limit here? */
+
+ /* If we're not past advancePast, keep scanning */
+ if (ginCompareItemPointers(&entry->curItem, &advancePast) <= 0)
+ continue;
+
+ /* Done unless we need to reduce the result */
+ if (!entry->reduceResult || !dropItem(entry))
+ break;
+ }
}
else
{
/* A posting tree */
- do
+ for (;;)
{
/* If we've processed the current batch, load more items */
while (entry->offset >= entry->nlist)
entry->curItem = entry->list[entry->offset++];
- } while (ginCompareItemPointers(&entry->curItem, &advancePast) <= 0 ||
- (entry->reduceResult == true && dropItem(entry)));
+ /* If we're not past advancePast, keep scanning */
+ if (ginCompareItemPointers(&entry->curItem, &advancePast) <= 0)
+ continue;
+
+ /* Done unless we need to reduce the result */
+ if (!entry->reduceResult || !dropItem(entry))
+ break;
+
+ /*
+ * Advance advancePast (so that entryLoadMoreItems will load the
+ * right data), and keep scanning
+ */
+ advancePast = entry->curItem;
+ }
}
}
insert into gin_test_tbl select array[1, 3, g] from generate_series(1, 1000) g;
delete from gin_test_tbl where i @> array[2];
vacuum gin_test_tbl;
+-- Test for "rare && frequent" searches
+explain (costs off)
+select count(*) from gin_test_tbl where i @> array[1, 999];
+ QUERY PLAN
+-------------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on gin_test_tbl
+ Recheck Cond: (i @> '{1,999}'::integer[])
+ -> Bitmap Index Scan on gin_test_idx
+ Index Cond: (i @> '{1,999}'::integer[])
+(5 rows)
+
+select count(*) from gin_test_tbl where i @> array[1, 999];
+ count
+-------
+ 3
+(1 row)
+
+-- Very weak test for gin_fuzzy_search_limit
+set gin_fuzzy_search_limit = 1000;
+explain (costs off)
+select count(*) > 0 as ok from gin_test_tbl where i @> array[1];
+ QUERY PLAN
+---------------------------------------------------
+ Aggregate
+ -> Bitmap Heap Scan on gin_test_tbl
+ Recheck Cond: (i @> '{1}'::integer[])
+ -> Bitmap Index Scan on gin_test_idx
+ Index Cond: (i @> '{1}'::integer[])
+(5 rows)
+
+select count(*) > 0 as ok from gin_test_tbl where i @> array[1];
+ ok
+----
+ t
+(1 row)
+
+reset gin_fuzzy_search_limit;
-- Test optimization of empty queries
create temp table t_gin_test_tbl(i int4[], j int4[]);
create index on t_gin_test_tbl using gin (i, j);
delete from gin_test_tbl where i @> array[2];
vacuum gin_test_tbl;
+-- Test for "rare && frequent" searches
+explain (costs off)
+select count(*) from gin_test_tbl where i @> array[1, 999];
+
+select count(*) from gin_test_tbl where i @> array[1, 999];
+
+-- Very weak test for gin_fuzzy_search_limit
+set gin_fuzzy_search_limit = 1000;
+
+explain (costs off)
+select count(*) > 0 as ok from gin_test_tbl where i @> array[1];
+
+select count(*) > 0 as ok from gin_test_tbl where i @> array[1];
+
+reset gin_fuzzy_search_limit;
+
-- Test optimization of empty queries
create temp table t_gin_test_tbl(i int4[], j int4[]);
create index on t_gin_test_tbl using gin (i, j);