diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c index 7bdcbc858e3..2cfccdedcf5 100644 --- a/src/backend/access/gin/ginget.c +++ b/src/backend/access/gin/ginget.c @@ -264,24 +264,28 @@ collectMatchBitmap(GinBtreeData *btree, GinBtreeStack *stack, /* Search forward to re-find idatum */ for (;;) { - Datum newDatum; - GinNullCategory newCategory; - if (moveRightIfItNeeded(btree, stack, snapshot) == false) - elog(ERROR, "lost saved point in index"); /* must not happen !!! */ + ereport(ERROR, + (errcode(ERRCODE_INTERNAL_ERROR), + errmsg("failed to re-find tuple within index \"%s\"", + RelationGetRelationName(btree->index)))); page = BufferGetPage(stack->buffer); itup = (IndexTuple) PageGetItem(page, PageGetItemId(page, stack->off)); - if (gintuple_get_attrnum(btree->ginstate, itup) != attnum) - elog(ERROR, "lost saved point in index"); /* must not happen !!! */ - newDatum = gintuple_get_key(btree->ginstate, itup, - &newCategory); + if (gintuple_get_attrnum(btree->ginstate, itup) == attnum) + { + Datum newDatum; + GinNullCategory newCategory; - if (ginCompareEntries(btree->ginstate, attnum, - newDatum, newCategory, - idatum, icategory) == 0) - break; /* Found! */ + newDatum = gintuple_get_key(btree->ginstate, itup, + &newCategory); + + if (ginCompareEntries(btree->ginstate, attnum, + newDatum, newCategory, + idatum, icategory) == 0) + break; /* Found! */ + } stack->off++; } diff --git a/src/test/regress/expected/gin.out b/src/test/regress/expected/gin.out index 83de5220fb9..b335466fc4b 100644 --- a/src/test/regress/expected/gin.out +++ b/src/test/regress/expected/gin.out @@ -199,6 +199,71 @@ from i @> '{1}' and j @> '{10}' | 2 | 0 | t (10 rows) +reset enable_seqscan; +reset enable_bitmapscan; +-- re-purpose t_gin_test_tbl to test scans involving posting trees +insert into t_gin_test_tbl select array[1, g, g/10], array[2, g, g/10] + from generate_series(1, 20000) g; +select gin_clean_pending_list('t_gin_test_tbl_i_j_idx') is not null; + ?column? +---------- + t +(1 row) + +analyze t_gin_test_tbl; +set enable_seqscan = off; +set enable_bitmapscan = on; +explain (costs off) +select count(*) from t_gin_test_tbl where j @> array[50]; + QUERY PLAN +--------------------------------------------------------- + Aggregate + -> Bitmap Heap Scan on t_gin_test_tbl + Recheck Cond: (j @> '{50}'::integer[]) + -> Bitmap Index Scan on t_gin_test_tbl_i_j_idx + Index Cond: (j @> '{50}'::integer[]) +(5 rows) + +select count(*) from t_gin_test_tbl where j @> array[50]; + count +------- + 11 +(1 row) + +explain (costs off) +select count(*) from t_gin_test_tbl where j @> array[2]; + QUERY PLAN +--------------------------------------------------------- + Aggregate + -> Bitmap Heap Scan on t_gin_test_tbl + Recheck Cond: (j @> '{2}'::integer[]) + -> Bitmap Index Scan on t_gin_test_tbl_i_j_idx + Index Cond: (j @> '{2}'::integer[]) +(5 rows) + +select count(*) from t_gin_test_tbl where j @> array[2]; + count +------- + 20000 +(1 row) + +explain (costs off) +select count(*) from t_gin_test_tbl where j @> '{}'::int[]; + QUERY PLAN +--------------------------------------------------------- + Aggregate + -> Bitmap Heap Scan on t_gin_test_tbl + Recheck Cond: (j @> '{}'::integer[]) + -> Bitmap Index Scan on t_gin_test_tbl_i_j_idx + Index Cond: (j @> '{}'::integer[]) +(5 rows) + +select count(*) from t_gin_test_tbl where j @> '{}'::int[]; + count +------- + 20006 +(1 row) + reset enable_seqscan; reset enable_bitmapscan; drop table t_gin_test_tbl; diff --git a/src/test/regress/sql/gin.sql b/src/test/regress/sql/gin.sql index abe35752652..efb8ef3e964 100644 --- a/src/test/regress/sql/gin.sql +++ b/src/test/regress/sql/gin.sql @@ -138,4 +138,28 @@ from reset enable_seqscan; reset enable_bitmapscan; +-- re-purpose t_gin_test_tbl to test scans involving posting trees +insert into t_gin_test_tbl select array[1, g, g/10], array[2, g, g/10] + from generate_series(1, 20000) g; + +select gin_clean_pending_list('t_gin_test_tbl_i_j_idx') is not null; + +analyze t_gin_test_tbl; + +set enable_seqscan = off; +set enable_bitmapscan = on; + +explain (costs off) +select count(*) from t_gin_test_tbl where j @> array[50]; +select count(*) from t_gin_test_tbl where j @> array[50]; +explain (costs off) +select count(*) from t_gin_test_tbl where j @> array[2]; +select count(*) from t_gin_test_tbl where j @> array[2]; +explain (costs off) +select count(*) from t_gin_test_tbl where j @> '{}'::int[]; +select count(*) from t_gin_test_tbl where j @> '{}'::int[]; + +reset enable_seqscan; +reset enable_bitmapscan; + drop table t_gin_test_tbl;