diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml index 4c92c2c77a5d90bdf4b73ee04868268af1946bcb..a6aaa4fd5a8519c01c069259de1d70b3ef0d5e08 100644 --- a/doc/src/sgml/catalogs.sgml +++ b/doc/src/sgml/catalogs.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.163 2008/03/10 12:55:13 mha Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/catalogs.sgml,v 2.164 2008/04/10 22:25:25 tgl Exp $ --> <!-- Documentation of the system catalogs, directed toward PostgreSQL developers --> @@ -473,10 +473,10 @@ </row> <row> - <entry><structfield>amgetmulti</structfield></entry> + <entry><structfield>amgetbitmap</structfield></entry> <entry><type>regproc</type></entry> <entry><literal><link linkend="catalog-pg-proc"><structname>pg_proc</structname></link>.oid</literal></entry> - <entry><quote>Fetch multiple tuples</quote> function</entry> + <entry><quote>Fetch all valid tuples</quote> function</entry> </row> <row> diff --git a/doc/src/sgml/indexam.sgml b/doc/src/sgml/indexam.sgml index 8b246719ccfcc08687e2028772706ba45c393a25..65da721de47d3a7998e1e15db7635abe263c4265 100644 --- a/doc/src/sgml/indexam.sgml +++ b/doc/src/sgml/indexam.sgml @@ -1,4 +1,4 @@ -<!-- $PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.23 2007/04/06 22:33:41 tgl Exp $ --> +<!-- $PostgreSQL: pgsql/doc/src/sgml/indexam.sgml,v 2.24 2008/04/10 22:25:25 tgl Exp $ --> <chapter id="indexam"> <title>Index Access Method Interface Definition</title> @@ -320,23 +320,16 @@ amgettuple (IndexScanDesc scan, <para> <programlisting> -boolean -amgetmulti (IndexScanDesc scan, - ItemPointer tids, - int32 max_tids, - int32 *returned_tids); +int64 +amgetbitmap (IndexScanDesc scan, + TIDBitmap *tbm); </programlisting> - Fetch multiple tuples in the given scan. Returns TRUE if the scan should - continue, FALSE if no matching tuples remain. <literal>tids</> points to - a caller-supplied array of <literal>max_tids</> - <structname>ItemPointerData</> records, which the call fills with TIDs of - matching tuples. <literal>*returned_tids</> is set to the number of TIDs - actually returned. This can be less than <literal>max_tids</>, or even - zero, even when the return value is TRUE. (This provision allows the - access method to choose the most efficient stopping points in its scan, - for example index page boundaries.) <function>amgetmulti</> and + Fetch all tuples in the given scan and add them to the caller-supplied + TIDBitmap (that is, OR the set of tuple IDs into whatever set is already + in the bitmap). The number of tuples fetched is returned. + <function>amgetbitmap</> and <function>amgettuple</> cannot be used in the same index scan; there - are other restrictions too when using <function>amgetmulti</>, as explained + are other restrictions too when using <function>amgetbitmap</>, as explained in <xref linkend="index-scanning">. </para> @@ -491,20 +484,17 @@ amrestrpos (IndexScanDesc scan); <para> Instead of using <function>amgettuple</>, an index scan can be done with - <function>amgetmulti</> to fetch multiple tuples per call. This can be + <function>amgetbitmap</> to fetch all tuples in one call. This can be noticeably more efficient than <function>amgettuple</> because it allows avoiding lock/unlock cycles within the access method. In principle - <function>amgetmulti</> should have the same effects as repeated + <function>amgetbitmap</> should have the same effects as repeated <function>amgettuple</> calls, but we impose several restrictions to - simplify matters. In the first place, <function>amgetmulti</> does not - take a <literal>direction</> argument, and therefore it does not support - backwards scan nor intrascan reversal of direction. The access method - need not support marking or restoring scan positions during an - <function>amgetmulti</> scan, either. (These restrictions cost little - since it would be difficult to use these features in an - <function>amgetmulti</> scan anyway: adjusting the caller's buffered - list of TIDs would be complex.) Finally, <function>amgetmulti</> does - not guarantee any locking of the returned tuples, with implications + simplify matters. First of all, <function>amgetbitmap</> returns all + tuples at once and marking or restoring scan positions isn't + supported. Secondly, the tuples are returned in a bitmap which doesn't + have any specific ordering, which is why <function>amgetbitmap</> doesn't + take a <literal>direction</> argument. Finally, <function>amgetbitmap</> + does not guarantee any locking of the returned tuples, with implications spelled out in <xref linkend="index-locking">. </para> @@ -605,9 +595,8 @@ amrestrpos (IndexScanDesc scan); </para> <para> - In an <function>amgetmulti</> index scan, the access method need not - guarantee to keep an index pin on any of the returned tuples. (It would be - impractical to pin more than the last one anyway.) Therefore + In an <function>amgetbitmap</> index scan, the access method does not + keep an index pin on any of the returned tuples. Therefore it is only safe to use such scans with MVCC-compliant snapshots. </para> diff --git a/src/backend/access/gin/ginget.c b/src/backend/access/gin/ginget.c index 31464ab2bc3010a99fce07fdae306bec722d6fac..4fb5ee556c5dc45fa956d1787bf2219cbe558d25 100644 --- a/src/backend/access/gin/ginget.c +++ b/src/backend/access/gin/ginget.c @@ -8,13 +8,15 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/gin/ginget.c,v 1.10 2008/01/01 19:45:46 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/gin/ginget.c,v 1.11 2008/04/10 22:25:25 tgl Exp $ *------------------------------------------------------------------------- */ #include "postgres.h" + #include "access/gin.h" #include "catalog/index.h" +#include "miscadmin.h" #include "utils/memutils.h" static bool @@ -476,34 +478,37 @@ scanGetItem(IndexScanDesc scan, ItemPointerData *item) #define GinIsVoidRes(s) ( ((GinScanOpaque) scan->opaque)->isVoidRes == true ) Datum -gingetmulti(PG_FUNCTION_ARGS) +gingetbitmap(PG_FUNCTION_ARGS) { IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); - ItemPointer tids = (ItemPointer) PG_GETARG_POINTER(1); - int32 max_tids = PG_GETARG_INT32(2); - int32 *returned_tids = (int32 *) PG_GETARG_POINTER(3); + TIDBitmap *tbm = (TIDBitmap *) PG_GETARG_POINTER(1); + int64 ntids; if (GinIsNewKey(scan)) newScanKey(scan); - *returned_tids = 0; - if (GinIsVoidRes(scan)) - PG_RETURN_BOOL(false); + PG_RETURN_INT64(0); startScan(scan); - do + ntids = 0; + for (;;) { - if (scanGetItem(scan, tids + *returned_tids)) - (*returned_tids)++; - else + ItemPointerData iptr; + + CHECK_FOR_INTERRUPTS(); + + if (!scanGetItem(scan, &iptr)) break; - } while (*returned_tids < max_tids); + + tbm_add_tuples(tbm, &iptr, 1, false); + ntids++; + } stopScan(scan); - PG_RETURN_BOOL(*returned_tids == max_tids); + PG_RETURN_INT64(ntids); } Datum diff --git a/src/backend/access/gist/gistget.c b/src/backend/access/gist/gistget.c index 22a7d0ceae6700b71bb65d8f533dedb4ebac1726..4533ff8c85f9997232afac5369aad109b6825589 100644 --- a/src/backend/access/gist/gistget.c +++ b/src/backend/access/gist/gistget.c @@ -8,7 +8,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.69 2008/01/01 19:45:46 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.70 2008/04/10 22:25:25 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -16,13 +16,16 @@ #include "access/gist_private.h" #include "executor/execdebug.h" +#include "miscadmin.h" #include "pgstat.h" #include "utils/memutils.h" static OffsetNumber gistfindnext(IndexScanDesc scan, OffsetNumber n, ScanDirection dir); -static int gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, bool ignore_killed_tuples); +static int64 gistnext(IndexScanDesc scan, ScanDirection dir, + ItemPointer tid, TIDBitmap *tbm, + bool ignore_killed_tuples); static bool gistindex_keytest(IndexTuple tuple, IndexScanDesc scan, OffsetNumber offset); @@ -114,32 +117,37 @@ gistgettuple(PG_FUNCTION_ARGS) * tuples, continue looping until we find a non-killed tuple that matches * the search key. */ - res = (gistnext(scan, dir, &tid, 1, scan->ignore_killed_tuples)) ? true : false; + res = (gistnext(scan, dir, &tid, NULL, scan->ignore_killed_tuples) > 0) ? true : false; PG_RETURN_BOOL(res); } Datum -gistgetmulti(PG_FUNCTION_ARGS) +gistgetbitmap(PG_FUNCTION_ARGS) { IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); - ItemPointer tids = (ItemPointer) PG_GETARG_POINTER(1); - int32 max_tids = PG_GETARG_INT32(2); - int32 *returned_tids = (int32 *) PG_GETARG_POINTER(3); + TIDBitmap *tbm = (TIDBitmap *) PG_GETARG_POINTER(1); + int64 ntids; - *returned_tids = gistnext(scan, ForwardScanDirection, tids, max_tids, false); + ntids = gistnext(scan, ForwardScanDirection, NULL, tbm, false); - PG_RETURN_BOOL(*returned_tids == max_tids); + PG_RETURN_INT64(ntids); } /* - * Fetch a tuples that matchs the search key; this can be invoked - * either to fetch the first such tuple or subsequent matching - * tuples. Returns true iff a matching tuple was found. + * Fetch tuple(s) that match the search key; this can be invoked + * either to fetch the first such tuple or subsequent matching tuples. + * + * This function is used by both gistgettuple and gistgetbitmap. When + * invoked from gistgettuple, tbm is null and the next matching tuple + * is returned in *tid. When invoked from getbitmap, tid is null and + * all matching tuples are added to tbm. In both cases, the function + * result is the number of returned tuples. */ -static int -gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, - int maxtids, bool ignore_killed_tuples) +static int64 +gistnext(IndexScanDesc scan, ScanDirection dir, + ItemPointer tid, TIDBitmap *tbm, + bool ignore_killed_tuples) { Page p; OffsetNumber n; @@ -148,7 +156,7 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, IndexTuple it; GISTPageOpaque opaque; bool resetoffset = false; - int ntids = 0; + int64 ntids = 0; so = (GISTScanOpaque) scan->opaque; @@ -174,6 +182,8 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, for (;;) { + CHECK_FOR_INTERRUPTS(); + /* First of all, we need lock buffer */ Assert(so->curbuf != InvalidBuffer); LockBuffer(so->curbuf, GIST_SHARE); @@ -285,20 +295,21 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, * return success. Note that we keep "curbuf" pinned so that * we can efficiently resume the index scan later. */ - ItemPointerSet(&(so->curpos), BufferGetBlockNumber(so->curbuf), n); if (!(ignore_killed_tuples && ItemIdIsDead(PageGetItemId(p, n)))) { it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n)); - tids[ntids] = scan->xs_ctup.t_self = it->t_tid; ntids++; - - if (ntids == maxtids) + if (tbm != NULL) + tbm_add_tuples(tbm, &it->t_tid, 1, false); + else { + *tid = scan->xs_ctup.t_self = it->t_tid; + LockBuffer(so->curbuf, GIST_UNLOCK); - return ntids; + return ntids; /* always 1 */ } } } @@ -308,7 +319,6 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, * We've found an entry in an internal node whose key is * consistent with the search key, so push it to stack */ - stk = (GISTSearchStack *) palloc(sizeof(GISTSearchStack)); it = (IndexTuple) PageGetItem(p, PageGetItemId(p, n)); @@ -318,7 +328,6 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, stk->next = so->stack->next; so->stack->next = stk; - } if (ScanDirectionIsBackward(dir)) diff --git a/src/backend/access/hash/hash.c b/src/backend/access/hash/hash.c index 01da35ec9f20605192170efbb6e628c8a69e9636..c090cfef8bb2042c7e7f278ae539508fe24cf4f1 100644 --- a/src/backend/access/hash/hash.c +++ b/src/backend/access/hash/hash.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.100 2008/03/16 23:15:08 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.101 2008/04/10 22:25:25 tgl Exp $ * * NOTES * This file contains only the public interface routines. @@ -22,6 +22,7 @@ #include "access/hash.h" #include "catalog/index.h" #include "commands/vacuum.h" +#include "miscadmin.h" #include "optimizer/cost.h" #include "optimizer/plancat.h" @@ -275,72 +276,51 @@ hashgettuple(PG_FUNCTION_ARGS) /* - * hashgetmulti() -- get multiple tuples at once - * - * This is a somewhat generic implementation: it avoids lock reacquisition - * overhead, but there's no smarts about picking especially good stopping - * points such as index page boundaries. + * hashgetbitmap() -- get all tuples at once */ Datum -hashgetmulti(PG_FUNCTION_ARGS) +hashgetbitmap(PG_FUNCTION_ARGS) { IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); - ItemPointer tids = (ItemPointer) PG_GETARG_POINTER(1); - int32 max_tids = PG_GETARG_INT32(2); - int32 *returned_tids = (int32 *) PG_GETARG_POINTER(3); + TIDBitmap *tbm = (TIDBitmap *) PG_GETARG_POINTER(1); HashScanOpaque so = (HashScanOpaque) scan->opaque; - Relation rel = scan->indexRelation; - bool res = true; - int32 ntids = 0; + bool res; + int64 ntids = 0; - /* - * We hold pin but not lock on current buffer while outside the hash AM. - * Reacquire the read lock here. - */ - if (BufferIsValid(so->hashso_curbuf)) - _hash_chgbufaccess(rel, so->hashso_curbuf, HASH_NOLOCK, HASH_READ); + res = _hash_first(scan, ForwardScanDirection); - while (ntids < max_tids) + while (res) { - /* - * Start scan, or advance to next tuple. - */ - if (ItemPointerIsValid(&(so->hashso_curpos))) - res = _hash_next(scan, ForwardScanDirection); - else - res = _hash_first(scan, ForwardScanDirection); + bool add_tuple; + + CHECK_FOR_INTERRUPTS(); /* * Skip killed tuples if asked to. */ if (scan->ignore_killed_tuples) { - while (res) - { - Page page; - OffsetNumber offnum; - - offnum = ItemPointerGetOffsetNumber(&(so->hashso_curpos)); - page = BufferGetPage(so->hashso_curbuf); - if (!ItemIdIsDead(PageGetItemId(page, offnum))) - break; - res = _hash_next(scan, ForwardScanDirection); - } + Page page; + OffsetNumber offnum; + + offnum = ItemPointerGetOffsetNumber(&(so->hashso_curpos)); + page = BufferGetPage(so->hashso_curbuf); + add_tuple = !ItemIdIsDead(PageGetItemId(page, offnum)); } + else + add_tuple = true; - if (!res) - break; /* Save tuple ID, and continue scanning */ - tids[ntids] = scan->xs_ctup.t_self; - ntids++; - } + if (add_tuple) + { + tbm_add_tuples(tbm, &scan->xs_ctup.t_self, 1, false); + ntids++; + } - /* Release read lock on current buffer, but keep it pinned */ - if (BufferIsValid(so->hashso_curbuf)) - _hash_chgbufaccess(rel, so->hashso_curbuf, HASH_READ, HASH_NOLOCK); + res = _hash_next(scan, ForwardScanDirection); + } - *returned_tids = ntids; - PG_RETURN_BOOL(res); + PG_RETURN_INT64(ntids); } diff --git a/src/backend/access/index/genam.c b/src/backend/access/index/genam.c index a4395cb240eb8676823d401eb5de99e4e2a8975b..8877938322d5c83b8be4a4b4c38f7a02a5b04026 100644 --- a/src/backend/access/index/genam.c +++ b/src/backend/access/index/genam.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.65 2008/03/26 21:10:37 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.66 2008/04/10 22:25:25 tgl Exp $ * * NOTES * many of the old access method routines have been turned into @@ -88,7 +88,6 @@ RelationGetIndexScan(Relation indexRelation, else scan->keyData = NULL; - scan->is_multiscan = false; /* caller may change this */ scan->kill_prior_tuple = false; scan->ignore_killed_tuples = true; /* default setting */ diff --git a/src/backend/access/index/indexam.c b/src/backend/access/index/indexam.c index c4739aa1cd15ab67a751f02337d7c2f27a2abc62..d59f1529db1c7033a5ccc6a7f8f99da6a9140f35 100644 --- a/src/backend/access/index/indexam.c +++ b/src/backend/access/index/indexam.c @@ -8,20 +8,20 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.104 2008/03/26 21:10:37 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/access/index/indexam.c,v 1.105 2008/04/10 22:25:25 tgl Exp $ * * INTERFACE ROUTINES * index_open - open an index relation by relation OID * index_close - close an index relation * index_beginscan - start a scan of an index with amgettuple - * index_beginscan_multi - start a scan of an index with amgetmulti + * index_beginscan_bitmap - start a scan of an index with amgetbitmap * index_rescan - restart a scan of an index * index_endscan - end a scan * index_insert - insert an index tuple into a relation * index_markpos - mark a scan position * index_restrpos - restore a scan position * index_getnext - get the next tuple from a scan - * index_getmulti - get multiple tuples from a scan + * index_getbitmap - get all tuples from a scan * index_bulk_delete - bulk deletion of index tuples * index_vacuum_cleanup - post-deletion cleanup of an index * index_getprocid - get a support procedure OID @@ -227,7 +227,6 @@ index_beginscan(Relation heapRelation, * Save additional parameters into the scandesc. Everything else was set * up by RelationGetIndexScan. */ - scan->is_multiscan = false; scan->heapRelation = heapRelation; scan->xs_snapshot = snapshot; @@ -235,15 +234,15 @@ index_beginscan(Relation heapRelation, } /* - * index_beginscan_multi - start a scan of an index with amgetmulti + * index_beginscan_bitmap - start a scan of an index with amgetbitmap * * As above, caller had better be holding some lock on the parent heap * relation, even though it's not explicitly mentioned here. */ IndexScanDesc -index_beginscan_multi(Relation indexRelation, - Snapshot snapshot, - int nkeys, ScanKey key) +index_beginscan_bitmap(Relation indexRelation, + Snapshot snapshot, + int nkeys, ScanKey key) { IndexScanDesc scan; @@ -253,7 +252,6 @@ index_beginscan_multi(Relation indexRelation, * Save additional parameters into the scandesc. Everything else was set * up by RelationGetIndexScan. */ - scan->is_multiscan = true; scan->xs_snapshot = snapshot; return scan; @@ -676,44 +674,39 @@ index_getnext_indexitem(IndexScanDesc scan, } /* ---------------- - * index_getmulti - get multiple tuples from an index scan + * index_getbitmap - get all tuples at once from an index scan * - * Collects the TIDs of multiple heap tuples satisfying the scan keys. + * Adds the TIDs of all heap tuples satisfying the scan keys to a bitmap. * Since there's no interlock between the index scan and the eventual heap * access, this is only safe to use with MVCC-based snapshots: the heap * item slot could have been replaced by a newer tuple by the time we get * to it. * - * A TRUE result indicates more calls should occur; a FALSE result says the - * scan is done. *returned_tids could be zero or nonzero in either case. + * Returns the number of matching tuples found. * ---------------- */ -bool -index_getmulti(IndexScanDesc scan, - ItemPointer tids, int32 max_tids, - int32 *returned_tids) +int64 +index_getbitmap(IndexScanDesc scan, TIDBitmap *bitmap) { FmgrInfo *procedure; - bool found; + int64 ntids; SCAN_CHECKS; - GET_SCAN_PROCEDURE(amgetmulti); + GET_SCAN_PROCEDURE(amgetbitmap); /* just make sure this is false... */ scan->kill_prior_tuple = false; /* - * have the am's getmulti proc do all the work. + * have the am's getbitmap proc do all the work. */ - found = DatumGetBool(FunctionCall4(procedure, - PointerGetDatum(scan), - PointerGetDatum(tids), - Int32GetDatum(max_tids), - PointerGetDatum(returned_tids))); + ntids = DatumGetInt64(FunctionCall2(procedure, + PointerGetDatum(scan), + PointerGetDatum(bitmap))); - pgstat_count_index_tuples(scan->indexRelation, *returned_tids); + pgstat_count_index_tuples(scan->indexRelation, ntids); - return found; + return ntids; } /* ---------------- diff --git a/src/backend/access/nbtree/nbtree.c b/src/backend/access/nbtree/nbtree.c index 5cfa8f315d79ee09a153c4ab72750113f62deb4d..d96348ace46eec87ebf1226d0bdccc14baa98809 100644 --- a/src/backend/access/nbtree/nbtree.c +++ b/src/backend/access/nbtree/nbtree.c @@ -12,7 +12,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.156 2008/01/01 19:45:46 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.157 2008/04/10 22:25:25 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -22,6 +22,7 @@ #include "access/nbtree.h" #include "catalog/index.h" #include "commands/vacuum.h" +#include "miscadmin.h" #include "storage/freespace.h" #include "storage/lmgr.h" #include "utils/memutils.h" @@ -278,42 +279,29 @@ btgettuple(PG_FUNCTION_ARGS) } /* - * btgetmulti() -- get multiple tuples at once - * - * In the current implementation there seems no strong reason to stop at - * index page boundaries; we just press on until we fill the caller's buffer - * or run out of matches. + * btgetbitmap() -- gets all matching tuples, and adds them to a bitmap */ Datum -btgetmulti(PG_FUNCTION_ARGS) +btgetbitmap(PG_FUNCTION_ARGS) { IndexScanDesc scan = (IndexScanDesc) PG_GETARG_POINTER(0); - ItemPointer tids = (ItemPointer) PG_GETARG_POINTER(1); - int32 max_tids = PG_GETARG_INT32(2); - int32 *returned_tids = (int32 *) PG_GETARG_POINTER(3); + TIDBitmap *tbm = (TIDBitmap *) PG_GETARG_POINTER(1); BTScanOpaque so = (BTScanOpaque) scan->opaque; - bool res = true; - int32 ntids = 0; - - if (max_tids <= 0) /* behave correctly in boundary case */ - PG_RETURN_BOOL(true); + int64 ntids = 0; + ItemPointer heapTid; - /* If we haven't started the scan yet, fetch the first page & tuple. */ - if (!BTScanPosIsValid(so->currPos)) + /* Fetch the first page & tuple. */ + if (!_bt_first(scan, ForwardScanDirection)) { - res = _bt_first(scan, ForwardScanDirection); - if (!res) - { - /* empty scan */ - *returned_tids = ntids; - PG_RETURN_BOOL(res); - } - /* Save tuple ID, and continue scanning */ - tids[ntids] = scan->xs_ctup.t_self; - ntids++; + /* empty scan */ + PG_RETURN_INT64(0); } + /* Save tuple ID, and continue scanning */ + heapTid = &scan->xs_ctup.t_self; + tbm_add_tuples(tbm, heapTid, 1, false); + ntids++; - while (ntids < max_tids) + for (;;) { /* * Advance to next tuple within page. This is the same as the easy @@ -321,19 +309,20 @@ btgetmulti(PG_FUNCTION_ARGS) */ if (++so->currPos.itemIndex > so->currPos.lastItem) { + CHECK_FOR_INTERRUPTS(); + /* let _bt_next do the heavy lifting */ - res = _bt_next(scan, ForwardScanDirection); - if (!res) + if (!_bt_next(scan, ForwardScanDirection)) break; } /* Save tuple ID, and continue scanning */ - tids[ntids] = so->currPos.items[so->currPos.itemIndex].heapTid; + heapTid = &so->currPos.items[so->currPos.itemIndex].heapTid; + tbm_add_tuples(tbm, heapTid, 1, false); ntids++; } - *returned_tids = ntids; - PG_RETURN_BOOL(res); + PG_RETURN_INT64(ntids); } /* diff --git a/src/backend/executor/nodeBitmapHeapscan.c b/src/backend/executor/nodeBitmapHeapscan.c index 998ef91097dadd096b222f2f744cc7abb050e979..3908892bc2af72e5b64f02bc515436406a34897f 100644 --- a/src/backend/executor/nodeBitmapHeapscan.c +++ b/src/backend/executor/nodeBitmapHeapscan.c @@ -21,7 +21,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/nodeBitmapHeapscan.c,v 1.25 2008/03/26 21:10:38 alvherre Exp $ + * $PostgreSQL: pgsql/src/backend/executor/nodeBitmapHeapscan.c,v 1.26 2008/04/10 22:25:25 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -206,7 +206,7 @@ BitmapHeapNext(BitmapHeapScanState *node) * If we are using lossy info, we have to recheck the qual conditions * at every tuple. */ - if (tbmres->ntuples < 0) + if (tbmres->recheck) { econtext->ecxt_scantuple = slot; ResetExprContext(econtext); diff --git a/src/backend/executor/nodeBitmapIndexscan.c b/src/backend/executor/nodeBitmapIndexscan.c index fd56e862df6461f6e3a2666f05ce2492e5098085..a2b2700723ccbe74cfa72739f13e417a23d2fec1 100644 --- a/src/backend/executor/nodeBitmapIndexscan.c +++ b/src/backend/executor/nodeBitmapIndexscan.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/executor/nodeBitmapIndexscan.c,v 1.25 2008/01/01 19:45:49 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/executor/nodeBitmapIndexscan.c,v 1.26 2008/04/10 22:25:25 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -37,11 +37,8 @@ Node * MultiExecBitmapIndexScan(BitmapIndexScanState *node) { -#define MAX_TIDS 1024 TIDBitmap *tbm; IndexScanDesc scandesc; - ItemPointerData tids[MAX_TIDS]; - int32 ntids; double nTuples = 0; bool doscan; @@ -91,23 +88,14 @@ MultiExecBitmapIndexScan(BitmapIndexScanState *node) */ while (doscan) { - bool more = index_getmulti(scandesc, tids, MAX_TIDS, &ntids); - - if (ntids > 0) - { - tbm_add_tuples(tbm, tids, ntids); - nTuples += ntids; - } + nTuples += (double) index_getbitmap(scandesc, tbm); CHECK_FOR_INTERRUPTS(); - if (!more) - { - doscan = ExecIndexAdvanceArrayKeys(node->biss_ArrayKeys, - node->biss_NumArrayKeys); - if (doscan) /* reset index scan */ - index_rescan(node->biss_ScanDesc, node->biss_ScanKeys); - } + doscan = ExecIndexAdvanceArrayKeys(node->biss_ArrayKeys, + node->biss_NumArrayKeys); + if (doscan) /* reset index scan */ + index_rescan(node->biss_ScanDesc, node->biss_ScanKeys); } /* must provide our own instrumentation support */ @@ -321,10 +309,10 @@ ExecInitBitmapIndexScan(BitmapIndexScan *node, EState *estate, int eflags) * Initialize scan descriptor. */ indexstate->biss_ScanDesc = - index_beginscan_multi(indexstate->biss_RelationDesc, - estate->es_snapshot, - indexstate->biss_NumScanKeys, - indexstate->biss_ScanKeys); + index_beginscan_bitmap(indexstate->biss_RelationDesc, + estate->es_snapshot, + indexstate->biss_NumScanKeys, + indexstate->biss_ScanKeys); /* * all done. diff --git a/src/backend/nodes/tidbitmap.c b/src/backend/nodes/tidbitmap.c index 18a260675a4602debda1ff0e5a26f9fc8f5969f9..37a2b4bfae7de53cf3d965d81b45f5909374e951 100644 --- a/src/backend/nodes/tidbitmap.c +++ b/src/backend/nodes/tidbitmap.c @@ -19,11 +19,20 @@ * of lossiness. In theory we could fall back to page ranges at some * point, but for now that seems useless complexity. * + * We also support the notion of candidate matches, or rechecking. This + * means we know that a search need visit only some tuples on a page, + * but we are not certain that all of those tuples are real matches. + * So the eventual heap scan must recheck the quals for these tuples only, + * rather than rechecking the quals for all tuples on the page as in the + * lossy-bitmap case. Rechecking can be specified when TIDs are inserted + * into a bitmap, and it can also happen internally when we AND a lossy + * and a non-lossy page. + * * * Copyright (c) 2003-2008, PostgreSQL Global Development Group * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/nodes/tidbitmap.c,v 1.14 2008/01/01 19:45:50 momjian Exp $ + * $PostgreSQL: pgsql/src/backend/nodes/tidbitmap.c,v 1.15 2008/04/10 22:25:25 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -81,11 +90,16 @@ * have exact storage for the first page of a chunk if we are using * lossy storage for any page in the chunk's range, since the same * hashtable entry has to serve both purposes. + * + * recheck is used only on exact pages --- it indicates that although + * only the stated tuples need be checked, the full index qual condition + * must be checked for each (ie, these are candidate matches). */ typedef struct PagetableEntry { BlockNumber blockno; /* page number (hashtable key) */ bool ischunk; /* T = lossy storage, F = exact */ + bool recheck; /* should the tuples be rechecked? */ bitmapword words[Max(WORDS_PER_PAGE, WORDS_PER_CHUNK)]; } PagetableEntry; @@ -244,9 +258,13 @@ tbm_free(TIDBitmap *tbm) /* * tbm_add_tuples - add some tuple IDs to a TIDBitmap + * + * If recheck is true, then the recheck flag will be set in the + * TBMIterateResult when any of these tuples are reported out. */ void -tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids) +tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids, + bool recheck) { int i; @@ -280,6 +298,7 @@ tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids) bitnum = BITNUM(off - 1); } page->words[wordnum] |= ((bitmapword) 1 << bitnum); + page->recheck |= recheck; if (tbm->nentries > tbm->maxentries) tbm_lossify(tbm); @@ -360,6 +379,7 @@ tbm_union_page(TIDBitmap *a, const PagetableEntry *bpage) /* Both pages are exact, merge at the bit level */ for (wordnum = 0; wordnum < WORDS_PER_PAGE; wordnum++) apage->words[wordnum] |= bpage->words[wordnum]; + apage->recheck |= bpage->recheck; } } @@ -471,22 +491,12 @@ tbm_intersect_page(TIDBitmap *a, PagetableEntry *apage, const TIDBitmap *b) else if (tbm_page_is_lossy(b, apage->blockno)) { /* - * When the page is lossy in b, we have to mark it lossy in a too. We - * know that no bits need be set in bitmap a, but we do not know which - * ones should be cleared, and we have no API for "at most these - * tuples need be checked". (Perhaps it's worth adding that?) - */ - tbm_mark_page_lossy(a, apage->blockno); - - /* - * Note: tbm_mark_page_lossy will have removed apage from a, and may - * have inserted a new lossy chunk instead. We can continue the same - * seq_search scan at the caller level, because it does not matter - * whether we visit such a new chunk or not: it will have only the bit - * for apage->blockno set, which is correct. - * - * We must return false here since apage was already deleted. + * Some of the tuples in 'a' might not satisfy the quals for 'b', + * but because the page 'b' is lossy, we don't know which ones. + * Therefore we mark 'a' as requiring rechecks, to indicate that + * at most those tuples set in 'a' are matches. */ + apage->recheck = true; return false; } else @@ -504,7 +514,9 @@ tbm_intersect_page(TIDBitmap *a, PagetableEntry *apage, const TIDBitmap *b) if (apage->words[wordnum] != 0) candelete = false; } + apage->recheck |= bpage->recheck; } + /* If there is no matching b page, we can just delete the a page */ return candelete; } } @@ -585,7 +597,9 @@ tbm_begin_iterate(TIDBitmap *tbm) * order. If result->ntuples < 0, then the bitmap is "lossy" and failed to * remember the exact tuples to look at on this page --- the caller must * examine all tuples on the page and check if they meet the intended - * condition. + * condition. If result->recheck is true, only the indicated tuples need + * be examined, but the condition must be rechecked anyway. (For ease of + * testing, recheck is always set true when ntuples < 0.) */ TBMIterateResult * tbm_iterate(TIDBitmap *tbm) @@ -638,6 +652,7 @@ tbm_iterate(TIDBitmap *tbm) /* Return a lossy page indicator from the chunk */ output->blockno = chunk_blockno; output->ntuples = -1; + output->recheck = true; tbm->schunkbit++; return output; } @@ -676,6 +691,7 @@ tbm_iterate(TIDBitmap *tbm) } output->blockno = page->blockno; output->ntuples = ntuples; + output->recheck = page->recheck; tbm->spageptr++; return output; } diff --git a/src/include/access/genam.h b/src/include/access/genam.h index df3c7f0ed955e8061e36fe30397b6480c771415a..57785913394b07398119ca5a2cbda69e77454a38 100644 --- a/src/include/access/genam.h +++ b/src/include/access/genam.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/genam.h,v 1.69 2008/01/01 19:45:56 momjian Exp $ + * $PostgreSQL: pgsql/src/include/access/genam.h,v 1.70 2008/04/10 22:25:25 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -17,6 +17,7 @@ #include "access/relscan.h" #include "access/sdir.h" #include "nodes/primnodes.h" +#include "nodes/tidbitmap.h" #include "storage/lock.h" /* @@ -99,7 +100,7 @@ extern IndexScanDesc index_beginscan(Relation heapRelation, Relation indexRelation, Snapshot snapshot, int nkeys, ScanKey key); -extern IndexScanDesc index_beginscan_multi(Relation indexRelation, +extern IndexScanDesc index_beginscan_bitmap(Relation indexRelation, Snapshot snapshot, int nkeys, ScanKey key); extern void index_rescan(IndexScanDesc scan, ScanKey key); @@ -109,9 +110,7 @@ extern void index_restrpos(IndexScanDesc scan); extern HeapTuple index_getnext(IndexScanDesc scan, ScanDirection direction); extern bool index_getnext_indexitem(IndexScanDesc scan, ScanDirection direction); -extern bool index_getmulti(IndexScanDesc scan, - ItemPointer tids, int32 max_tids, - int32 *returned_tids); +extern int64 index_getbitmap(IndexScanDesc scan, TIDBitmap *bitmap); extern IndexBulkDeleteResult *index_bulk_delete(IndexVacuumInfo *info, IndexBulkDeleteResult *stats, diff --git a/src/include/access/gin.h b/src/include/access/gin.h index d27ba66a5970ff59b831a5d97856ccf371682a6c..7a343c62c491a9d6230d882a0131838a41845990 100644 --- a/src/include/access/gin.h +++ b/src/include/access/gin.h @@ -4,7 +4,7 @@ * * Copyright (c) 2006-2008, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/include/access/gin.h,v 1.16 2008/01/01 19:45:56 momjian Exp $ + * $PostgreSQL: pgsql/src/include/access/gin.h,v 1.17 2008/04/10 22:25:25 tgl Exp $ *-------------------------------------------------------------------------- */ @@ -422,7 +422,7 @@ extern PGDLLIMPORT int GinFuzzySearchLimit; #define ItemPointerSetMin(p) ItemPointerSet( (p), (BlockNumber)0, (OffsetNumber)0) #define ItemPointerIsMin(p) ( ItemPointerGetBlockNumber(p) == (BlockNumber)0 && ItemPointerGetOffsetNumber(p) == (OffsetNumber)0 ) -extern Datum gingetmulti(PG_FUNCTION_ARGS); +extern Datum gingetbitmap(PG_FUNCTION_ARGS); extern Datum gingettuple(PG_FUNCTION_ARGS); /* ginvacuum.c */ diff --git a/src/include/access/gist_private.h b/src/include/access/gist_private.h index e6ca50a702f26028f9fc2ae87998433a8cbbad38..b34388b4ed149b4f8151b108b7574fa1d4dc53c8 100644 --- a/src/include/access/gist_private.h +++ b/src/include/access/gist_private.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/gist_private.h,v 1.28 2008/01/01 19:45:56 momjian Exp $ + * $PostgreSQL: pgsql/src/include/access/gist_private.h,v 1.29 2008/04/10 22:25:25 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -269,7 +269,7 @@ extern XLogRecPtr gistxlogInsertCompletion(RelFileNode node, ItemPointerData *ke /* gistget.c */ extern Datum gistgettuple(PG_FUNCTION_ARGS); -extern Datum gistgetmulti(PG_FUNCTION_ARGS); +extern Datum gistgetbitmap(PG_FUNCTION_ARGS); /* gistutil.c */ diff --git a/src/include/access/hash.h b/src/include/access/hash.h index 34275ad9d60b68fc9933d5fe4d565aac83287284..a786117ee55212db018916c4b11894ae6f1a7112 100644 --- a/src/include/access/hash.h +++ b/src/include/access/hash.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/hash.h,v 1.86 2008/03/16 23:15:08 tgl Exp $ + * $PostgreSQL: pgsql/src/include/access/hash.h,v 1.87 2008/04/10 22:25:25 tgl Exp $ * * NOTES * modeled after Margo Seltzer's hash implementation for unix. @@ -233,7 +233,7 @@ extern Datum hashbuild(PG_FUNCTION_ARGS); extern Datum hashinsert(PG_FUNCTION_ARGS); extern Datum hashbeginscan(PG_FUNCTION_ARGS); extern Datum hashgettuple(PG_FUNCTION_ARGS); -extern Datum hashgetmulti(PG_FUNCTION_ARGS); +extern Datum hashgetbitmap(PG_FUNCTION_ARGS); extern Datum hashrescan(PG_FUNCTION_ARGS); extern Datum hashendscan(PG_FUNCTION_ARGS); extern Datum hashmarkpos(PG_FUNCTION_ARGS); diff --git a/src/include/access/nbtree.h b/src/include/access/nbtree.h index 2bcf8ab38f417351f6c2dcabd87ff18819b27e1c..1422994506d539c685ab2f907cd6944cecf8fe08 100644 --- a/src/include/access/nbtree.h +++ b/src/include/access/nbtree.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.116 2008/01/01 19:45:56 momjian Exp $ + * $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.117 2008/04/10 22:25:25 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -507,7 +507,7 @@ extern Datum btbuild(PG_FUNCTION_ARGS); extern Datum btinsert(PG_FUNCTION_ARGS); extern Datum btbeginscan(PG_FUNCTION_ARGS); extern Datum btgettuple(PG_FUNCTION_ARGS); -extern Datum btgetmulti(PG_FUNCTION_ARGS); +extern Datum btgetbitmap(PG_FUNCTION_ARGS); extern Datum btrescan(PG_FUNCTION_ARGS); extern Datum btendscan(PG_FUNCTION_ARGS); extern Datum btmarkpos(PG_FUNCTION_ARGS); diff --git a/src/include/access/relscan.h b/src/include/access/relscan.h index eebcc86bb30412f0649178d4b1fc760ccbb8ec46..677fd04e2c2d94c300d11dd46e0f0186350c5031 100644 --- a/src/include/access/relscan.h +++ b/src/include/access/relscan.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/access/relscan.h,v 1.61 2008/03/26 16:20:48 alvherre Exp $ + * $PostgreSQL: pgsql/src/include/access/relscan.h,v 1.62 2008/04/10 22:25:25 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -57,7 +57,7 @@ typedef HeapScanDescData *HeapScanDesc; /* * We use the same IndexScanDescData structure for both amgettuple-based - * and amgetmulti-based index scans. Some fields are only relevant in + * and amgetbitmap-based index scans. Some fields are only relevant in * amgettuple-based scans. */ typedef struct IndexScanDescData @@ -68,7 +68,6 @@ typedef struct IndexScanDescData Snapshot xs_snapshot; /* snapshot to see */ int numberOfKeys; /* number of scan keys */ ScanKey keyData; /* array of scan key descriptors */ - bool is_multiscan; /* TRUE = using amgetmulti */ /* signaling to index AM about killing index tuples */ bool kill_prior_tuple; /* last-returned tuple is dead */ diff --git a/src/include/catalog/catversion.h b/src/include/catalog/catversion.h index c8ce4727400d75a63ec8a9213dac24df2d7c6524..a0b1a34f29cfeeb30c97235a16b0375ba67d558a 100644 --- a/src/include/catalog/catversion.h +++ b/src/include/catalog/catversion.h @@ -37,7 +37,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.446 2008/04/06 16:54:48 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/catversion.h,v 1.447 2008/04/10 22:25:25 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -53,6 +53,6 @@ */ /* yyyymmddN */ -#define CATALOG_VERSION_NO 200804051 +#define CATALOG_VERSION_NO 200804101 #endif diff --git a/src/include/catalog/pg_am.h b/src/include/catalog/pg_am.h index 06287979d19bd6beee895df1707a436815e79770..9837a8c200382bb1e5ad8abd13be7c6b6df92ed8 100644 --- a/src/include/catalog/pg_am.h +++ b/src/include/catalog/pg_am.h @@ -8,7 +8,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_am.h,v 1.54 2008/03/27 03:57:34 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_am.h,v 1.55 2008/04/10 22:25:25 tgl Exp $ * * NOTES * the genbki.sh script reads this file and generates .bki @@ -51,7 +51,7 @@ CATALOG(pg_am,2601) regproc aminsert; /* "insert this tuple" function */ regproc ambeginscan; /* "start new scan" function */ regproc amgettuple; /* "next valid tuple" function */ - regproc amgetmulti; /* "fetch multiple tuples" function */ + regproc amgetbitmap; /* "fetch all valid tuples" function */ regproc amrescan; /* "restart this scan" function */ regproc amendscan; /* "end this scan" function */ regproc ammarkpos; /* "mark current scan position" function */ @@ -89,7 +89,7 @@ typedef FormData_pg_am *Form_pg_am; #define Anum_pg_am_aminsert 12 #define Anum_pg_am_ambeginscan 13 #define Anum_pg_am_amgettuple 14 -#define Anum_pg_am_amgetmulti 15 +#define Anum_pg_am_amgetbitmap 15 #define Anum_pg_am_amrescan 16 #define Anum_pg_am_amendscan 17 #define Anum_pg_am_ammarkpos 18 @@ -105,16 +105,16 @@ typedef FormData_pg_am *Form_pg_am; * ---------------- */ -DATA(insert OID = 403 ( btree 5 1 t t t t t t f t btinsert btbeginscan btgettuple btgetmulti btrescan btendscan btmarkpos btrestrpos btbuild btbulkdelete btvacuumcleanup btcostestimate btoptions )); +DATA(insert OID = 403 ( btree 5 1 t t t t t t f t btinsert btbeginscan btgettuple btgetbitmap btrescan btendscan btmarkpos btrestrpos btbuild btbulkdelete btvacuumcleanup btcostestimate btoptions )); DESCR("b-tree index access method"); #define BTREE_AM_OID 403 -DATA(insert OID = 405 ( hash 1 1 f f f f f f f f hashinsert hashbeginscan hashgettuple hashgetmulti hashrescan hashendscan hashmarkpos hashrestrpos hashbuild hashbulkdelete hashvacuumcleanup hashcostestimate hashoptions )); +DATA(insert OID = 405 ( hash 1 1 f f f f f f f f hashinsert hashbeginscan hashgettuple hashgetbitmap hashrescan hashendscan hashmarkpos hashrestrpos hashbuild hashbulkdelete hashvacuumcleanup hashcostestimate hashoptions )); DESCR("hash index access method"); #define HASH_AM_OID 405 -DATA(insert OID = 783 ( gist 0 7 f f t t t t t t gistinsert gistbeginscan gistgettuple gistgetmulti gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbulkdelete gistvacuumcleanup gistcostestimate gistoptions )); +DATA(insert OID = 783 ( gist 0 7 f f t t t t t t gistinsert gistbeginscan gistgettuple gistgetbitmap gistrescan gistendscan gistmarkpos gistrestrpos gistbuild gistbulkdelete gistvacuumcleanup gistcostestimate gistoptions )); DESCR("GiST index access method"); #define GIST_AM_OID 783 -DATA(insert OID = 2742 ( gin 0 4 f f f f f f t f gininsert ginbeginscan gingettuple gingetmulti ginrescan ginendscan ginmarkpos ginrestrpos ginbuild ginbulkdelete ginvacuumcleanup gincostestimate ginoptions )); +DATA(insert OID = 2742 ( gin 0 4 f f f f f f t f gininsert ginbeginscan gingettuple gingetbitmap ginrescan ginendscan ginmarkpos ginrestrpos ginbuild ginbulkdelete ginvacuumcleanup gincostestimate ginoptions )); DESCR("GIN index access method"); #define GIN_AM_OID 2742 diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h index 2abaeea211efcca1fd6a50cfcac2caa65e896977..7ef852666be8cd5039135d45acfbf33c5144d33c 100644 --- a/src/include/catalog/pg_proc.h +++ b/src/include/catalog/pg_proc.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.487 2008/04/04 18:45:36 tgl Exp $ + * $PostgreSQL: pgsql/src/include/catalog/pg_proc.h,v 1.488 2008/04/10 22:25:25 tgl Exp $ * * NOTES * The script catalog/genbki.sh reads this file and generates .bki @@ -655,7 +655,7 @@ DESCR("convert float4 to int4"); DATA(insert OID = 330 ( btgettuple PGNSP PGUID 12 1 0 f f t f v 2 16 "2281 2281" _null_ _null_ _null_ btgettuple - _null_ _null_ )); DESCR("btree(internal)"); -DATA(insert OID = 636 ( btgetmulti PGNSP PGUID 12 1 0 f f t f v 4 16 "2281 2281 2281 2281" _null_ _null_ _null_ btgetmulti - _null_ _null_ )); +DATA(insert OID = 636 ( btgetbitmap PGNSP PGUID 12 1 0 f f t f v 2 20 "2281 2281" _null_ _null_ _null_ btgetbitmap - _null_ _null_ )); DESCR("btree(internal)"); DATA(insert OID = 331 ( btinsert PGNSP PGUID 12 1 0 f f t f v 6 16 "2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ btinsert - _null_ _null_ )); DESCR("btree(internal)"); @@ -774,7 +774,7 @@ DESCR("convert char(n) to name"); DATA(insert OID = 440 ( hashgettuple PGNSP PGUID 12 1 0 f f t f v 2 16 "2281 2281" _null_ _null_ _null_ hashgettuple - _null_ _null_ )); DESCR("hash(internal)"); -DATA(insert OID = 637 ( hashgetmulti PGNSP PGUID 12 1 0 f f t f v 4 16 "2281 2281 2281 2281" _null_ _null_ _null_ hashgetmulti - _null_ _null_ )); +DATA(insert OID = 637 ( hashgetbitmap PGNSP PGUID 12 1 0 f f t f v 2 20 "2281 2281" _null_ _null_ _null_ hashgetbitmap - _null_ _null_ )); DESCR("hash(internal)"); DATA(insert OID = 441 ( hashinsert PGNSP PGUID 12 1 0 f f t f v 6 16 "2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ hashinsert - _null_ _null_ )); DESCR("hash(internal)"); @@ -1040,7 +1040,7 @@ DESCR("smaller of two"); DATA(insert OID = 774 ( gistgettuple PGNSP PGUID 12 1 0 f f t f v 2 16 "2281 2281" _null_ _null_ _null_ gistgettuple - _null_ _null_ )); DESCR("gist(internal)"); -DATA(insert OID = 638 ( gistgetmulti PGNSP PGUID 12 1 0 f f t f v 4 16 "2281 2281 2281 2281" _null_ _null_ _null_ gistgetmulti - _null_ _null_ )); +DATA(insert OID = 638 ( gistgetbitmap PGNSP PGUID 12 1 0 f f t f v 2 20 "2281 2281" _null_ _null_ _null_ gistgetbitmap - _null_ _null_ )); DESCR("gist(internal)"); DATA(insert OID = 775 ( gistinsert PGNSP PGUID 12 1 0 f f t f v 6 16 "2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ gistinsert - _null_ _null_ )); DESCR("gist(internal)"); @@ -3967,7 +3967,7 @@ DESCR("GiST support"); /* GIN */ DATA(insert OID = 2730 ( gingettuple PGNSP PGUID 12 1 0 f f t f v 2 16 "2281 2281" _null_ _null_ _null_ gingettuple - _null_ _null_ )); DESCR("gin(internal)"); -DATA(insert OID = 2731 ( gingetmulti PGNSP PGUID 12 1 0 f f t f v 4 16 "2281 2281 2281 2281" _null_ _null_ _null_ gingetmulti - _null_ _null_ )); +DATA(insert OID = 2731 ( gingetbitmap PGNSP PGUID 12 1 0 f f t f v 2 20 "2281 2281" _null_ _null_ _null_ gingetbitmap - _null_ _null_ )); DESCR("gin(internal)"); DATA(insert OID = 2732 ( gininsert PGNSP PGUID 12 1 0 f f t f v 6 16 "2281 2281 2281 2281 2281 2281" _null_ _null_ _null_ gininsert - _null_ _null_ )); DESCR("gin(internal)"); diff --git a/src/include/nodes/tidbitmap.h b/src/include/nodes/tidbitmap.h index d40502b940d3f2d13b902cc24a3b7249648fc050..08eaeb0aeefabf6ba9e6631856fbacce886f4885 100644 --- a/src/include/nodes/tidbitmap.h +++ b/src/include/nodes/tidbitmap.h @@ -15,7 +15,7 @@ * * Copyright (c) 2003-2008, PostgreSQL Global Development Group * - * $PostgreSQL: pgsql/src/include/nodes/tidbitmap.h,v 1.6 2008/01/01 19:45:58 momjian Exp $ + * $PostgreSQL: pgsql/src/include/nodes/tidbitmap.h,v 1.7 2008/04/10 22:25:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -36,6 +36,8 @@ typedef struct { BlockNumber blockno; /* page number containing tuples */ int ntuples; /* -1 indicates lossy result */ + bool recheck; /* should the tuples be rechecked? */ + /* Note: recheck is always true if ntuples < 0 */ OffsetNumber offsets[1]; /* VARIABLE LENGTH ARRAY */ } TBMIterateResult; /* VARIABLE LENGTH STRUCT */ @@ -44,7 +46,9 @@ typedef struct extern TIDBitmap *tbm_create(long maxbytes); extern void tbm_free(TIDBitmap *tbm); -extern void tbm_add_tuples(TIDBitmap *tbm, const ItemPointer tids, int ntids); +extern void tbm_add_tuples(TIDBitmap *tbm, + const ItemPointer tids, int ntids, + bool recheck); extern void tbm_union(TIDBitmap *a, const TIDBitmap *b); extern void tbm_intersect(TIDBitmap *a, const TIDBitmap *b); diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index f7d46193de5d396891d2f3bec099e99ab6759ce2..25b9d43845a4cd91cf4219f04947dc0f1cad7952 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -7,7 +7,7 @@ * Portions Copyright (c) 1996-2008, PostgreSQL Global Development Group * Portions Copyright (c) 1994, Regents of the University of California * - * $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.105 2008/03/28 00:21:56 tgl Exp $ + * $PostgreSQL: pgsql/src/include/utils/rel.h,v 1.106 2008/04/10 22:25:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -100,7 +100,7 @@ typedef struct RelationAmInfo FmgrInfo aminsert; FmgrInfo ambeginscan; FmgrInfo amgettuple; - FmgrInfo amgetmulti; + FmgrInfo amgetbitmap; FmgrInfo amrescan; FmgrInfo amendscan; FmgrInfo ammarkpos; diff --git a/src/test/regress/expected/bitmapops.out b/src/test/regress/expected/bitmapops.out new file mode 100644 index 0000000000000000000000000000000000000000..d88a76fe24be274cb67e22b4f0e8b050ace218e6 --- /dev/null +++ b/src/test/regress/expected/bitmapops.out @@ -0,0 +1,38 @@ +-- Test bitmap AND and OR +-- Generate enough data that we can test the lossy bitmaps. +-- There's 55 tuples per page in the table. 53 is just +-- below 55, so that an index scan with qual a = constant +-- will return at least one hit per page. 59 is just above +-- 55, so that an index scan with qual b = constant will return +-- hits on most but not all pages. 53 and 59 are prime, so that +-- there's a maximum number of a,b combinations in the table. +-- That allows us to test all the different combinations of +-- lossy and non-lossy pages with the minimum amount of data +CREATE TABLE bmscantest (a int, b int, t text); +INSERT INTO bmscantest + SELECT (r%53), (r%59), 'foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo' + FROM generate_series(1,70000) r; +CREATE INDEX i_bmtest_a ON bmscantest(a); +CREATE INDEX i_bmtest_b ON bmscantest(b); +-- We want to use bitmapscans. With default settings, the planner currently +-- chooses a bitmap scan for the queries below anyway, but let's make sure. +set enable_indexscan=false; +set enable_seqscan=false; +-- Lower work_mem to trigger use of lossy bitmaps +set work_mem = 64; +-- Test bitmap-and. +SELECT count(*) FROM bmscantest WHERE a = 1 AND b = 1; + count +------- + 23 +(1 row) + +-- Test bitmap-or. +SELECT count(*) FROM bmscantest WHERE a = 1 OR b = 1; + count +------- + 2485 +(1 row) + +-- clean up +DROP TABLE bmscantest; diff --git a/src/test/regress/expected/create_index.out b/src/test/regress/expected/create_index.out index b56078edf235cbbb01f009663430afcb00cefd1d..52ba630a560d9050574694d129890c4146231088 100644 --- a/src/test/regress/expected/create_index.out +++ b/src/test/regress/expected/create_index.out @@ -174,7 +174,7 @@ RESET enable_bitmapscan; -- SET enable_seqscan = OFF; SET enable_indexscan = ON; -SET enable_bitmapscan = ON; +SET enable_bitmapscan = OFF; CREATE INDEX intarrayidx ON array_index_op_test USING gin (i); SELECT * FROM array_index_op_test WHERE i @> '{32}' ORDER BY seqno; seqno | i | t @@ -327,6 +327,95 @@ SELECT * FROM array_index_op_test WHERE t = '{AAAAAAAAAA646,A87088}' ORDER BY se 96 | {23,97,43} | {AAAAAAAAAA646,A87088} (1 row) +-- Repeat some of the above tests but exercising bitmapscans instead +SET enable_indexscan = OFF; +SET enable_bitmapscan = ON; +SELECT * FROM array_index_op_test WHERE i @> '{32}' ORDER BY seqno; + seqno | i | t +-------+---------------------------------+------------------------------------------------------------------------------------------------------------------------------------ + 6 | {39,35,5,94,17,92,60,32} | {AAAAAAAAAAAAAAA35875,AAAAAAAAAAAAAAAA23657} + 74 | {32} | {AAAAAAAAAAAAAAAA1729,AAAAAAAAAAAAA22860,AAAAAA99807,AAAAA17383,AAAAAAAAAAAAAAA67062,AAAAAAAAAAA15165,AAAAAAAAAAA50956} + 77 | {97,15,32,17,55,59,18,37,50,39} | {AAAAAAAAAAAA67946,AAAAAA54032,AAAAAAAA81587,55847,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAAAAA43052,AAAAAA75463,AAAA49534,AAAAAAAA44066} + 89 | {40,32,17,6,30,88} | {AA44673,AAAAAAAAAAA6119,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAAAAAA47955,AAAAAAAAAAAAAAAA33598,AAAAAAAAAAA33576,AA44673} + 98 | {38,34,32,89} | {AAAAAAAAAAAAAAAAAA71621,AAAA8857,AAAAAAAAAAAAAAAAAAA65037,AAAAAAAAAAAAAAAA31334,AAAAAAAAAA48845} + 100 | {85,32,57,39,49,84,32,3,30} | {AAAAAAA80240,AAAAAAAAAAAAAAAA1729,AAAAA60038,AAAAAAAAAAA92631,AAAAAAAA9523} +(6 rows) + +SELECT * FROM array_index_op_test WHERE i && '{32}' ORDER BY seqno; + seqno | i | t +-------+---------------------------------+------------------------------------------------------------------------------------------------------------------------------------ + 6 | {39,35,5,94,17,92,60,32} | {AAAAAAAAAAAAAAA35875,AAAAAAAAAAAAAAAA23657} + 74 | {32} | {AAAAAAAAAAAAAAAA1729,AAAAAAAAAAAAA22860,AAAAAA99807,AAAAA17383,AAAAAAAAAAAAAAA67062,AAAAAAAAAAA15165,AAAAAAAAAAA50956} + 77 | {97,15,32,17,55,59,18,37,50,39} | {AAAAAAAAAAAA67946,AAAAAA54032,AAAAAAAA81587,55847,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAAAAA43052,AAAAAA75463,AAAA49534,AAAAAAAA44066} + 89 | {40,32,17,6,30,88} | {AA44673,AAAAAAAAAAA6119,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAAAAAA47955,AAAAAAAAAAAAAAAA33598,AAAAAAAAAAA33576,AA44673} + 98 | {38,34,32,89} | {AAAAAAAAAAAAAAAAAA71621,AAAA8857,AAAAAAAAAAAAAAAAAAA65037,AAAAAAAAAAAAAAAA31334,AAAAAAAAAA48845} + 100 | {85,32,57,39,49,84,32,3,30} | {AAAAAAA80240,AAAAAAAAAAAAAAAA1729,AAAAA60038,AAAAAAAAAAA92631,AAAAAAAA9523} +(6 rows) + +SELECT * FROM array_index_op_test WHERE i @> '{17}' ORDER BY seqno; + seqno | i | t +-------+---------------------------------+------------------------------------------------------------------------------------------------------------------------------------ + 6 | {39,35,5,94,17,92,60,32} | {AAAAAAAAAAAAAAA35875,AAAAAAAAAAAAAAAA23657} + 12 | {17,99,18,52,91,72,0,43,96,23} | {AAAAA33250,AAAAAAAAAAAAAAAAAAA85420,AAAAAAAAAAA33576} + 15 | {17,14,16,63,67} | {AA6416,AAAAAAAAAA646,AAAAA95309} + 19 | {52,82,17,74,23,46,69,51,75} | {AAAAAAAAAAAAA73084,AAAAA75968,AAAAAAAAAAAAAAAA14047,AAAAAAA80240,AAAAAAAAAAAAAAAAAAA1205,A68938} + 53 | {38,17} | {AAAAAAAAAAA21658} + 65 | {61,5,76,59,17} | {AAAAAA99807,AAAAA64741,AAAAAAAAAAA53908,AA21643,AAAAAAAAA10012} + 77 | {97,15,32,17,55,59,18,37,50,39} | {AAAAAAAAAAAA67946,AAAAAA54032,AAAAAAAA81587,55847,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAAAAA43052,AAAAAA75463,AAAA49534,AAAAAAAA44066} + 89 | {40,32,17,6,30,88} | {AA44673,AAAAAAAAAAA6119,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAAAAAA47955,AAAAAAAAAAAAAAAA33598,AAAAAAAAAAA33576,AA44673} +(8 rows) + +SELECT * FROM array_index_op_test WHERE i && '{17}' ORDER BY seqno; + seqno | i | t +-------+---------------------------------+------------------------------------------------------------------------------------------------------------------------------------ + 6 | {39,35,5,94,17,92,60,32} | {AAAAAAAAAAAAAAA35875,AAAAAAAAAAAAAAAA23657} + 12 | {17,99,18,52,91,72,0,43,96,23} | {AAAAA33250,AAAAAAAAAAAAAAAAAAA85420,AAAAAAAAAAA33576} + 15 | {17,14,16,63,67} | {AA6416,AAAAAAAAAA646,AAAAA95309} + 19 | {52,82,17,74,23,46,69,51,75} | {AAAAAAAAAAAAA73084,AAAAA75968,AAAAAAAAAAAAAAAA14047,AAAAAAA80240,AAAAAAAAAAAAAAAAAAA1205,A68938} + 53 | {38,17} | {AAAAAAAAAAA21658} + 65 | {61,5,76,59,17} | {AAAAAA99807,AAAAA64741,AAAAAAAAAAA53908,AA21643,AAAAAAAAA10012} + 77 | {97,15,32,17,55,59,18,37,50,39} | {AAAAAAAAAAAA67946,AAAAAA54032,AAAAAAAA81587,55847,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAAAAA43052,AAAAAA75463,AAAA49534,AAAAAAAA44066} + 89 | {40,32,17,6,30,88} | {AA44673,AAAAAAAAAAA6119,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAAAAAA47955,AAAAAAAAAAAAAAAA33598,AAAAAAAAAAA33576,AA44673} +(8 rows) + +SELECT * FROM array_index_op_test WHERE i @> '{32,17}' ORDER BY seqno; + seqno | i | t +-------+---------------------------------+------------------------------------------------------------------------------------------------------------------------------------ + 6 | {39,35,5,94,17,92,60,32} | {AAAAAAAAAAAAAAA35875,AAAAAAAAAAAAAAAA23657} + 77 | {97,15,32,17,55,59,18,37,50,39} | {AAAAAAAAAAAA67946,AAAAAA54032,AAAAAAAA81587,55847,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAAAAA43052,AAAAAA75463,AAAA49534,AAAAAAAA44066} + 89 | {40,32,17,6,30,88} | {AA44673,AAAAAAAAAAA6119,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAAAAAA47955,AAAAAAAAAAAAAAAA33598,AAAAAAAAAAA33576,AA44673} +(3 rows) + +SELECT * FROM array_index_op_test WHERE i && '{32,17}' ORDER BY seqno; + seqno | i | t +-------+---------------------------------+------------------------------------------------------------------------------------------------------------------------------------ + 6 | {39,35,5,94,17,92,60,32} | {AAAAAAAAAAAAAAA35875,AAAAAAAAAAAAAAAA23657} + 12 | {17,99,18,52,91,72,0,43,96,23} | {AAAAA33250,AAAAAAAAAAAAAAAAAAA85420,AAAAAAAAAAA33576} + 15 | {17,14,16,63,67} | {AA6416,AAAAAAAAAA646,AAAAA95309} + 19 | {52,82,17,74,23,46,69,51,75} | {AAAAAAAAAAAAA73084,AAAAA75968,AAAAAAAAAAAAAAAA14047,AAAAAAA80240,AAAAAAAAAAAAAAAAAAA1205,A68938} + 53 | {38,17} | {AAAAAAAAAAA21658} + 65 | {61,5,76,59,17} | {AAAAAA99807,AAAAA64741,AAAAAAAAAAA53908,AA21643,AAAAAAAAA10012} + 74 | {32} | {AAAAAAAAAAAAAAAA1729,AAAAAAAAAAAAA22860,AAAAAA99807,AAAAA17383,AAAAAAAAAAAAAAA67062,AAAAAAAAAAA15165,AAAAAAAAAAA50956} + 77 | {97,15,32,17,55,59,18,37,50,39} | {AAAAAAAAAAAA67946,AAAAAA54032,AAAAAAAA81587,55847,AAAAAAAAAAAAAA28620,AAAAAAAAAAAAAAAAA43052,AAAAAA75463,AAAA49534,AAAAAAAA44066} + 89 | {40,32,17,6,30,88} | {AA44673,AAAAAAAAAAA6119,AAAAAAAAAAAAAAAA23657,AAAAAAAAAAAAAAAAAA47955,AAAAAAAAAAAAAAAA33598,AAAAAAAAAAA33576,AA44673} + 98 | {38,34,32,89} | {AAAAAAAAAAAAAAAAAA71621,AAAA8857,AAAAAAAAAAAAAAAAAAA65037,AAAAAAAAAAAAAAAA31334,AAAAAAAAAA48845} + 100 | {85,32,57,39,49,84,32,3,30} | {AAAAAAA80240,AAAAAAAAAAAAAAAA1729,AAAAA60038,AAAAAAAAAAA92631,AAAAAAAA9523} +(11 rows) + +SELECT * FROM array_index_op_test WHERE i <@ '{38,34,32,89}' ORDER BY seqno; + seqno | i | t +-------+---------------+---------------------------------------------------------------------------------------------------------------------------- + 40 | {34} | {AAAAAAAAAAAAAA10611,AAAAAAAAAAAAAAAAAAA1205,AAAAAAAAAAA50956,AAAAAAAAAAAAAAAA31334,AAAAA70466,AAAAAAAA81587,AAAAAAA74623} + 74 | {32} | {AAAAAAAAAAAAAAAA1729,AAAAAAAAAAAAA22860,AAAAAA99807,AAAAA17383,AAAAAAAAAAAAAAA67062,AAAAAAAAAAA15165,AAAAAAAAAAA50956} + 98 | {38,34,32,89} | {AAAAAAAAAAAAAAAAAA71621,AAAA8857,AAAAAAAAAAAAAAAAAAA65037,AAAAAAAAAAAAAAAA31334,AAAAAAAAAA48845} +(3 rows) + +SELECT * FROM array_index_op_test WHERE i = '{47,77}' ORDER BY seqno; + seqno | i | t +-------+---------+----------------------------------------------------------------------------------------------------------------- + 95 | {47,77} | {AAAAAAAAAAAAAAAAA764,AAAAAAAAAAA74076,AAAAAAAAAA18107,AAAAA40681,AAAAAAAAAAAAAAA35875,AAAAA60038,AAAAAAA56483} +(1 row) + RESET enable_seqscan; RESET enable_indexscan; RESET enable_bitmapscan; diff --git a/src/test/regress/expected/oidjoins.out b/src/test/regress/expected/oidjoins.out index bd55dc24ae3fcaca207913c80259e19d4ed0f00f..c57721958ff58425c03d53aaec7c93d73fcc75f7 100644 --- a/src/test/regress/expected/oidjoins.out +++ b/src/test/regress/expected/oidjoins.out @@ -65,12 +65,12 @@ WHERE amgettuple != 0 AND ------+------------ (0 rows) -SELECT ctid, amgetmulti +SELECT ctid, amgetbitmap FROM pg_catalog.pg_am fk -WHERE amgetmulti != 0 AND - NOT EXISTS(SELECT 1 FROM pg_catalog.pg_proc pk WHERE pk.oid = fk.amgetmulti); - ctid | amgetmulti -------+------------ +WHERE amgetbitmap != 0 AND + NOT EXISTS(SELECT 1 FROM pg_catalog.pg_proc pk WHERE pk.oid = fk.amgetbitmap); + ctid | amgetbitmap +------+------------- (0 rows) SELECT ctid, amrescan diff --git a/src/test/regress/parallel_schedule b/src/test/regress/parallel_schedule index 8d72885bc773b9842b6af0abe159363c70341be1..f03d4179e1eb90adfac66db429965b21c856e213 100644 --- a/src/test/regress/parallel_schedule +++ b/src/test/regress/parallel_schedule @@ -1,5 +1,5 @@ # ---------- -# $PostgreSQL: pgsql/src/test/regress/parallel_schedule,v 1.46 2007/11/24 19:49:23 darcy Exp $ +# $PostgreSQL: pgsql/src/test/regress/parallel_schedule,v 1.47 2008/04/10 22:25:26 tgl Exp $ # # By convention, we put no more than twenty tests in any one parallel group; # this limits the number of connections needed to run the tests. @@ -77,7 +77,7 @@ test: misc # ---------- # Another group of parallel tests # ---------- -test: select_views portals_p2 rules foreign_key cluster dependency guc combocid tsearch tsdicts +test: select_views portals_p2 rules foreign_key cluster dependency guc bitmapops combocid tsearch tsdicts # ---------- # Another group of parallel tests diff --git a/src/test/regress/serial_schedule b/src/test/regress/serial_schedule index 49911961f5330888748c29402cf75a60e74dae98..34c75f6c5cde9513ec696ecf2cfbcc7730728492 100644 --- a/src/test/regress/serial_schedule +++ b/src/test/regress/serial_schedule @@ -1,4 +1,4 @@ -# $PostgreSQL: pgsql/src/test/regress/serial_schedule,v 1.43 2007/11/24 20:41:35 tgl Exp $ +# $PostgreSQL: pgsql/src/test/regress/serial_schedule,v 1.44 2008/04/10 22:25:26 tgl Exp $ # This should probably be in an order similar to parallel_schedule. test: boolean test: char @@ -92,6 +92,7 @@ test: foreign_key test: cluster test: dependency test: guc +test: bitmapops test: combocid test: tsearch test: plancache diff --git a/src/test/regress/sql/bitmapops.sql b/src/test/regress/sql/bitmapops.sql new file mode 100644 index 0000000000000000000000000000000000000000..0b5477e8e1497ebb98f6efb80077e2b6e4b7139f --- /dev/null +++ b/src/test/regress/sql/bitmapops.sql @@ -0,0 +1,41 @@ +-- Test bitmap AND and OR + + +-- Generate enough data that we can test the lossy bitmaps. + +-- There's 55 tuples per page in the table. 53 is just +-- below 55, so that an index scan with qual a = constant +-- will return at least one hit per page. 59 is just above +-- 55, so that an index scan with qual b = constant will return +-- hits on most but not all pages. 53 and 59 are prime, so that +-- there's a maximum number of a,b combinations in the table. +-- That allows us to test all the different combinations of +-- lossy and non-lossy pages with the minimum amount of data + +CREATE TABLE bmscantest (a int, b int, t text); + +INSERT INTO bmscantest + SELECT (r%53), (r%59), 'foooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooo' + FROM generate_series(1,70000) r; + +CREATE INDEX i_bmtest_a ON bmscantest(a); +CREATE INDEX i_bmtest_b ON bmscantest(b); + +-- We want to use bitmapscans. With default settings, the planner currently +-- chooses a bitmap scan for the queries below anyway, but let's make sure. +set enable_indexscan=false; +set enable_seqscan=false; + +-- Lower work_mem to trigger use of lossy bitmaps +set work_mem = 64; + + +-- Test bitmap-and. +SELECT count(*) FROM bmscantest WHERE a = 1 AND b = 1; + +-- Test bitmap-or. +SELECT count(*) FROM bmscantest WHERE a = 1 OR b = 1; + + +-- clean up +DROP TABLE bmscantest; diff --git a/src/test/regress/sql/create_index.sql b/src/test/regress/sql/create_index.sql index 14f2f281ff8456aa84d4e1e1232f379e101f2e1f..447c5df37acfaa5ec8a747933df70c98f6de24a9 100644 --- a/src/test/regress/sql/create_index.sql +++ b/src/test/regress/sql/create_index.sql @@ -143,7 +143,7 @@ RESET enable_bitmapscan; SET enable_seqscan = OFF; SET enable_indexscan = ON; -SET enable_bitmapscan = ON; +SET enable_bitmapscan = OFF; CREATE INDEX intarrayidx ON array_index_op_test USING gin (i); @@ -167,6 +167,18 @@ SELECT * FROM array_index_op_test WHERE t && '{AAAAAAAA72908,AAAAAAAAAA646}' ORD SELECT * FROM array_index_op_test WHERE t <@ '{AAAAAAAA72908,AAAAAAAAAAAAAAAAAAA17075,AA88409,AAAAAAAAAAAAAAAAAA36842,AAAAAAA48038,AAAAAAAAAAAAAA10611}' ORDER BY seqno; SELECT * FROM array_index_op_test WHERE t = '{AAAAAAAAAA646,A87088}' ORDER BY seqno; +-- Repeat some of the above tests but exercising bitmapscans instead +SET enable_indexscan = OFF; +SET enable_bitmapscan = ON; + +SELECT * FROM array_index_op_test WHERE i @> '{32}' ORDER BY seqno; +SELECT * FROM array_index_op_test WHERE i && '{32}' ORDER BY seqno; +SELECT * FROM array_index_op_test WHERE i @> '{17}' ORDER BY seqno; +SELECT * FROM array_index_op_test WHERE i && '{17}' ORDER BY seqno; +SELECT * FROM array_index_op_test WHERE i @> '{32,17}' ORDER BY seqno; +SELECT * FROM array_index_op_test WHERE i && '{32,17}' ORDER BY seqno; +SELECT * FROM array_index_op_test WHERE i <@ '{38,34,32,89}' ORDER BY seqno; +SELECT * FROM array_index_op_test WHERE i = '{47,77}' ORDER BY seqno; RESET enable_seqscan; RESET enable_indexscan; diff --git a/src/test/regress/sql/oidjoins.sql b/src/test/regress/sql/oidjoins.sql index 773c2afe7faf69992ba27c36934237ec46653864..7a072d4fd3dcd13efc22e09b1b8cea39af69fd0a 100644 --- a/src/test/regress/sql/oidjoins.sql +++ b/src/test/regress/sql/oidjoins.sql @@ -33,10 +33,10 @@ SELECT ctid, amgettuple FROM pg_catalog.pg_am fk WHERE amgettuple != 0 AND NOT EXISTS(SELECT 1 FROM pg_catalog.pg_proc pk WHERE pk.oid = fk.amgettuple); -SELECT ctid, amgetmulti +SELECT ctid, amgetbitmap FROM pg_catalog.pg_am fk -WHERE amgetmulti != 0 AND - NOT EXISTS(SELECT 1 FROM pg_catalog.pg_proc pk WHERE pk.oid = fk.amgetmulti); +WHERE amgetbitmap != 0 AND + NOT EXISTS(SELECT 1 FROM pg_catalog.pg_proc pk WHERE pk.oid = fk.amgetbitmap); SELECT ctid, amrescan FROM pg_catalog.pg_am fk WHERE amrescan != 0 AND