Refactor the index AM API slightly: move currentItemData and

currentMarkData from IndexScanDesc to the opaque structs for the
AMs that need this information (currently gist and hash).

Patch from Heikki Linnakangas, fixes by Neil Conway.
REL8_3_STABLE
Neil Conway 19 years ago
parent 978fff7942
commit 2b7334d487
  1. 17
      src/backend/access/gist/gistget.c
  2. 18
      src/backend/access/gist/gistscan.c
  3. 44
      src/backend/access/hash/hash.c
  4. 12
      src/backend/access/hash/hashsearch.c
  5. 5
      src/backend/access/index/genam.c
  6. 4
      src/include/access/gist_private.h
  7. 6
      src/include/access/hash.h
  8. 5
      src/include/access/nbtree.h
  9. 5
      src/include/access/relscan.h

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.63 2007/01/05 22:19:22 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/gist/gistget.c,v 1.64 2007/01/20 18:43:35 neilc Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -106,8 +106,8 @@ gistgettuple(PG_FUNCTION_ARGS)
* If we have produced an index tuple in the past and the executor has * If we have produced an index tuple in the past and the executor has
* informed us we need to mark it as "killed", do so now. * informed us we need to mark it as "killed", do so now.
*/ */
if (scan->kill_prior_tuple && ItemPointerIsValid(&(scan->currentItemData))) if (scan->kill_prior_tuple && ItemPointerIsValid(&(so->curpos)))
killtuple(scan->indexRelation, so, &(scan->currentItemData)); killtuple(scan->indexRelation, so, &(so->curpos));
/* /*
* Get the next tuple that matches the search key. If asked to skip killed * Get the next tuple that matches the search key. If asked to skip killed
@ -138,7 +138,8 @@ gistgetmulti(PG_FUNCTION_ARGS)
* tuples. Returns true iff a matching tuple was found. * tuples. Returns true iff a matching tuple was found.
*/ */
static int static int
gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, bool ignore_killed_tuples) gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids,
int maxtids, bool ignore_killed_tuples)
{ {
Page p; Page p;
OffsetNumber n; OffsetNumber n;
@ -151,7 +152,7 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, b
so = (GISTScanOpaque) scan->opaque; so = (GISTScanOpaque) scan->opaque;
if (ItemPointerIsValid(&scan->currentItemData) == false) if (ItemPointerIsValid(&so->curpos) == false)
{ {
/* Being asked to fetch the first entry, so start at the root */ /* Being asked to fetch the first entry, so start at the root */
Assert(so->curbuf == InvalidBuffer); Assert(so->curbuf == InvalidBuffer);
@ -226,7 +227,7 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, b
} }
if (!GistPageIsLeaf(p) || resetoffset || if (!GistPageIsLeaf(p) || resetoffset ||
!ItemPointerIsValid(&scan->currentItemData)) !ItemPointerIsValid(&so->curpos))
{ {
if (ScanDirectionIsBackward(dir)) if (ScanDirectionIsBackward(dir))
n = PageGetMaxOffsetNumber(p); n = PageGetMaxOffsetNumber(p);
@ -235,7 +236,7 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, b
} }
else else
{ {
n = ItemPointerGetOffsetNumber(&(scan->currentItemData)); n = ItemPointerGetOffsetNumber(&(so->curpos));
if (ScanDirectionIsBackward(dir)) if (ScanDirectionIsBackward(dir))
n = OffsetNumberPrev(n); n = OffsetNumberPrev(n);
@ -285,7 +286,7 @@ gistnext(IndexScanDesc scan, ScanDirection dir, ItemPointer tids, int maxtids, b
* we can efficiently resume the index scan later. * we can efficiently resume the index scan later.
*/ */
ItemPointerSet(&(scan->currentItemData), ItemPointerSet(&(so->curpos),
BufferGetBlockNumber(so->curbuf), n); BufferGetBlockNumber(so->curbuf), n);
if (!(ignore_killed_tuples && ItemIdDeleted(PageGetItemId(p, n)))) if (!(ignore_killed_tuples && ItemIdDeleted(PageGetItemId(p, n))))

@ -8,7 +8,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/gist/gistscan.c,v 1.66 2007/01/05 22:19:22 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/gist/gistscan.c,v 1.67 2007/01/20 18:43:35 neilc Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -42,12 +42,6 @@ gistrescan(PG_FUNCTION_ARGS)
GISTScanOpaque so; GISTScanOpaque so;
int i; int i;
/*
* Clear all the pointers.
*/
ItemPointerSetInvalid(&scan->currentItemData);
ItemPointerSetInvalid(&scan->currentMarkData);
so = (GISTScanOpaque) scan->opaque; so = (GISTScanOpaque) scan->opaque;
if (so != NULL) if (so != NULL)
{ {
@ -82,6 +76,12 @@ gistrescan(PG_FUNCTION_ARGS)
scan->opaque = so; scan->opaque = so;
} }
/*
* Clear all the pointers.
*/
ItemPointerSetInvalid(&so->curpos);
ItemPointerSetInvalid(&so->markpos);
/* Update scan key, if a new one is given */ /* Update scan key, if a new one is given */
if (key && scan->numberOfKeys > 0) if (key && scan->numberOfKeys > 0)
{ {
@ -111,8 +111,8 @@ gistmarkpos(PG_FUNCTION_ARGS)
*n, *n,
*tmp; *tmp;
scan->currentMarkData = scan->currentItemData;
so = (GISTScanOpaque) scan->opaque; so = (GISTScanOpaque) scan->opaque;
so->markpos = so->curpos;
if (so->flags & GS_CURBEFORE) if (so->flags & GS_CURBEFORE)
so->flags |= GS_MRKBEFORE; so->flags |= GS_MRKBEFORE;
else else
@ -160,8 +160,8 @@ gistrestrpos(PG_FUNCTION_ARGS)
*n, *n,
*tmp; *tmp;
scan->currentItemData = scan->currentMarkData;
so = (GISTScanOpaque) scan->opaque; so = (GISTScanOpaque) scan->opaque;
so->curpos = so->markpos;
if (so->flags & GS_MRKBEFORE) if (so->flags & GS_MRKBEFORE)
so->flags |= GS_CURBEFORE; so->flags |= GS_CURBEFORE;
else else

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.92 2007/01/05 22:19:22 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/hash/hash.c,v 1.93 2007/01/20 18:43:35 neilc Exp $
* *
* NOTES * NOTES
* This file contains only the public interface routines. * This file contains only the public interface routines.
@ -185,7 +185,7 @@ hashgettuple(PG_FUNCTION_ARGS)
* appropriate direction. If we haven't done so yet, we call a routine to * appropriate direction. If we haven't done so yet, we call a routine to
* get the first item in the scan. * get the first item in the scan.
*/ */
if (ItemPointerIsValid(&(scan->currentItemData))) if (ItemPointerIsValid(&(so->hashso_curpos)))
{ {
/* /*
* Check to see if we should kill the previously-fetched tuple. * Check to see if we should kill the previously-fetched tuple.
@ -195,7 +195,7 @@ hashgettuple(PG_FUNCTION_ARGS)
/* /*
* Yes, so mark it by setting the LP_DELETE bit in the item flags. * Yes, so mark it by setting the LP_DELETE bit in the item flags.
*/ */
offnum = ItemPointerGetOffsetNumber(&(scan->currentItemData)); offnum = ItemPointerGetOffsetNumber(&(so->hashso_curpos));
page = BufferGetPage(so->hashso_curbuf); page = BufferGetPage(so->hashso_curbuf);
PageGetItemId(page, offnum)->lp_flags |= LP_DELETE; PageGetItemId(page, offnum)->lp_flags |= LP_DELETE;
@ -222,7 +222,7 @@ hashgettuple(PG_FUNCTION_ARGS)
{ {
while (res) while (res)
{ {
offnum = ItemPointerGetOffsetNumber(&(scan->currentItemData)); offnum = ItemPointerGetOffsetNumber(&(so->hashso_curpos));
page = BufferGetPage(so->hashso_curbuf); page = BufferGetPage(so->hashso_curbuf);
if (!ItemIdDeleted(PageGetItemId(page, offnum))) if (!ItemIdDeleted(PageGetItemId(page, offnum)))
break; break;
@ -269,7 +269,7 @@ hashgetmulti(PG_FUNCTION_ARGS)
/* /*
* Start scan, or advance to next tuple. * Start scan, or advance to next tuple.
*/ */
if (ItemPointerIsValid(&(scan->currentItemData))) if (ItemPointerIsValid(&(so->hashso_curpos)))
res = _hash_next(scan, ForwardScanDirection); res = _hash_next(scan, ForwardScanDirection);
else else
res = _hash_first(scan, ForwardScanDirection); res = _hash_first(scan, ForwardScanDirection);
@ -284,7 +284,7 @@ hashgetmulti(PG_FUNCTION_ARGS)
Page page; Page page;
OffsetNumber offnum; OffsetNumber offnum;
offnum = ItemPointerGetOffsetNumber(&(scan->currentItemData)); offnum = ItemPointerGetOffsetNumber(&(so->hashso_curpos));
page = BufferGetPage(so->hashso_curbuf); page = BufferGetPage(so->hashso_curbuf);
if (!ItemIdDeleted(PageGetItemId(page, offnum))) if (!ItemIdDeleted(PageGetItemId(page, offnum)))
break; break;
@ -325,6 +325,10 @@ hashbeginscan(PG_FUNCTION_ARGS)
so->hashso_bucket_valid = false; so->hashso_bucket_valid = false;
so->hashso_bucket_blkno = 0; so->hashso_bucket_blkno = 0;
so->hashso_curbuf = so->hashso_mrkbuf = InvalidBuffer; so->hashso_curbuf = so->hashso_mrkbuf = InvalidBuffer;
/* set positions invalid (this will cause _hash_first call) */
ItemPointerSetInvalid(&(so->hashso_curpos));
ItemPointerSetInvalid(&(so->hashso_mrkpos));
scan->opaque = so; scan->opaque = so;
/* register scan in case we change pages it's using */ /* register scan in case we change pages it's using */
@ -360,11 +364,11 @@ hashrescan(PG_FUNCTION_ARGS)
if (so->hashso_bucket_blkno) if (so->hashso_bucket_blkno)
_hash_droplock(rel, so->hashso_bucket_blkno, HASH_SHARE); _hash_droplock(rel, so->hashso_bucket_blkno, HASH_SHARE);
so->hashso_bucket_blkno = 0; so->hashso_bucket_blkno = 0;
}
/* set positions invalid (this will cause _hash_first call) */ /* set positions invalid (this will cause _hash_first call) */
ItemPointerSetInvalid(&(scan->currentItemData)); ItemPointerSetInvalid(&(so->hashso_curpos));
ItemPointerSetInvalid(&(scan->currentMarkData)); ItemPointerSetInvalid(&(so->hashso_mrkpos));
}
/* Update scan key, if a new one is given */ /* Update scan key, if a new one is given */
if (scankey && scan->numberOfKeys > 0) if (scankey && scan->numberOfKeys > 0)
@ -406,10 +410,6 @@ hashendscan(PG_FUNCTION_ARGS)
_hash_droplock(rel, so->hashso_bucket_blkno, HASH_SHARE); _hash_droplock(rel, so->hashso_bucket_blkno, HASH_SHARE);
so->hashso_bucket_blkno = 0; so->hashso_bucket_blkno = 0;
/* be tidy */
ItemPointerSetInvalid(&(scan->currentItemData));
ItemPointerSetInvalid(&(scan->currentMarkData));
pfree(so); pfree(so);
scan->opaque = NULL; scan->opaque = NULL;
@ -430,14 +430,14 @@ hashmarkpos(PG_FUNCTION_ARGS)
if (BufferIsValid(so->hashso_mrkbuf)) if (BufferIsValid(so->hashso_mrkbuf))
_hash_dropbuf(rel, so->hashso_mrkbuf); _hash_dropbuf(rel, so->hashso_mrkbuf);
so->hashso_mrkbuf = InvalidBuffer; so->hashso_mrkbuf = InvalidBuffer;
ItemPointerSetInvalid(&(scan->currentMarkData)); ItemPointerSetInvalid(&(so->hashso_mrkpos));
/* bump pin count on currentItemData and copy to currentMarkData */ /* bump pin count on current buffer and copy to marked buffer */
if (ItemPointerIsValid(&(scan->currentItemData))) if (ItemPointerIsValid(&(so->hashso_curpos)))
{ {
IncrBufferRefCount(so->hashso_curbuf); IncrBufferRefCount(so->hashso_curbuf);
so->hashso_mrkbuf = so->hashso_curbuf; so->hashso_mrkbuf = so->hashso_curbuf;
scan->currentMarkData = scan->currentItemData; so->hashso_mrkpos = so->hashso_curpos;
} }
PG_RETURN_VOID(); PG_RETURN_VOID();
@ -457,14 +457,14 @@ hashrestrpos(PG_FUNCTION_ARGS)
if (BufferIsValid(so->hashso_curbuf)) if (BufferIsValid(so->hashso_curbuf))
_hash_dropbuf(rel, so->hashso_curbuf); _hash_dropbuf(rel, so->hashso_curbuf);
so->hashso_curbuf = InvalidBuffer; so->hashso_curbuf = InvalidBuffer;
ItemPointerSetInvalid(&(scan->currentItemData)); ItemPointerSetInvalid(&(so->hashso_curpos));
/* bump pin count on currentMarkData and copy to currentItemData */ /* bump pin count on marked buffer and copy to current buffer */
if (ItemPointerIsValid(&(scan->currentMarkData))) if (ItemPointerIsValid(&(so->hashso_mrkpos)))
{ {
IncrBufferRefCount(so->hashso_mrkbuf); IncrBufferRefCount(so->hashso_mrkbuf);
so->hashso_curbuf = so->hashso_mrkbuf; so->hashso_curbuf = so->hashso_mrkbuf;
scan->currentItemData = scan->currentMarkData; so->hashso_curpos = so->hashso_mrkpos;
} }
PG_RETURN_VOID(); PG_RETURN_VOID();

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/hash/hashsearch.c,v 1.46 2007/01/05 22:19:22 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/hash/hashsearch.c,v 1.47 2007/01/20 18:43:35 neilc Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -21,7 +21,7 @@
/* /*
* _hash_next() -- Get the next item in a scan. * _hash_next() -- Get the next item in a scan.
* *
* On entry, we have a valid currentItemData in the scan, and a * On entry, we have a valid hashso_curpos in the scan, and a
* pin and read lock on the page that contains that item. * pin and read lock on the page that contains that item.
* We find the next item in the scan, if any. * We find the next item in the scan, if any.
* On success exit, we have the page containing the next item * On success exit, we have the page containing the next item
@ -49,7 +49,7 @@ _hash_next(IndexScanDesc scan, ScanDirection dir)
return false; return false;
/* if we're here, _hash_step found a valid tuple */ /* if we're here, _hash_step found a valid tuple */
current = &(scan->currentItemData); current = &(so->hashso_curpos);
offnum = ItemPointerGetOffsetNumber(current); offnum = ItemPointerGetOffsetNumber(current);
_hash_checkpage(rel, buf, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE); _hash_checkpage(rel, buf, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);
page = BufferGetPage(buf); page = BufferGetPage(buf);
@ -129,7 +129,7 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
pgstat_count_index_scan(&scan->xs_pgstat_info); pgstat_count_index_scan(&scan->xs_pgstat_info);
current = &(scan->currentItemData); current = &(so->hashso_curpos);
ItemPointerSetInvalid(current); ItemPointerSetInvalid(current);
/* /*
@ -224,7 +224,7 @@ _hash_first(IndexScanDesc scan, ScanDirection dir)
* _hash_step() -- step to the next valid item in a scan in the bucket. * _hash_step() -- step to the next valid item in a scan in the bucket.
* *
* If no valid record exists in the requested direction, return * If no valid record exists in the requested direction, return
* false. Else, return true and set the CurrentItemData for the * false. Else, return true and set the hashso_curpos for the
* scan to the right thing. * scan to the right thing.
* *
* 'bufP' points to the current buffer, which is pinned and read-locked. * 'bufP' points to the current buffer, which is pinned and read-locked.
@ -245,7 +245,7 @@ _hash_step(IndexScanDesc scan, Buffer *bufP, ScanDirection dir)
BlockNumber blkno; BlockNumber blkno;
IndexTuple itup; IndexTuple itup;
current = &(scan->currentItemData); current = &(so->hashso_curpos);
buf = *bufP; buf = *bufP;
_hash_checkpage(rel, buf, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE); _hash_checkpage(rel, buf, LH_BUCKET_PAGE | LH_OVERFLOW_PAGE);

@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.60 2007/01/05 22:19:22 momjian Exp $ * $PostgreSQL: pgsql/src/backend/access/index/genam.c,v 1.61 2007/01/20 18:43:35 neilc Exp $
* *
* NOTES * NOTES
* many of the old access method routines have been turned into * many of the old access method routines have been turned into
@ -92,9 +92,6 @@ RelationGetIndexScan(Relation indexRelation,
scan->opaque = NULL; scan->opaque = NULL;
ItemPointerSetInvalid(&scan->currentItemData);
ItemPointerSetInvalid(&scan->currentMarkData);
ItemPointerSetInvalid(&scan->xs_ctup.t_self); ItemPointerSetInvalid(&scan->xs_ctup.t_self);
scan->xs_ctup.t_data = NULL; scan->xs_ctup.t_data = NULL;
scan->xs_cbuf = InvalidBuffer; scan->xs_cbuf = InvalidBuffer;

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/access/gist_private.h,v 1.25 2007/01/05 22:19:51 momjian Exp $ * $PostgreSQL: pgsql/src/include/access/gist_private.h,v 1.26 2007/01/20 18:43:35 neilc Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -72,7 +72,9 @@ typedef struct GISTScanOpaqueData
GISTSTATE *giststate; GISTSTATE *giststate;
MemoryContext tempCxt; MemoryContext tempCxt;
Buffer curbuf; Buffer curbuf;
ItemPointerData curpos;
Buffer markbuf; Buffer markbuf;
ItemPointerData markpos;
} GISTScanOpaqueData; } GISTScanOpaqueData;
typedef GISTScanOpaqueData *GISTScanOpaque; typedef GISTScanOpaqueData *GISTScanOpaque;

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/access/hash.h,v 1.74 2007/01/05 22:19:51 momjian Exp $ * $PostgreSQL: pgsql/src/include/access/hash.h,v 1.75 2007/01/20 18:43:35 neilc Exp $
* *
* NOTES * NOTES
* modeled after Margo Seltzer's hash implementation for unix. * modeled after Margo Seltzer's hash implementation for unix.
@ -97,6 +97,10 @@ typedef struct HashScanOpaqueData
*/ */
Buffer hashso_curbuf; Buffer hashso_curbuf;
Buffer hashso_mrkbuf; Buffer hashso_mrkbuf;
/* Current and marked position of the scan */
ItemPointerData hashso_curpos;
ItemPointerData hashso_mrkpos;
} HashScanOpaqueData; } HashScanOpaqueData;
typedef HashScanOpaqueData *HashScanOpaque; typedef HashScanOpaqueData *HashScanOpaque;

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.108 2007/01/09 02:14:15 tgl Exp $ * $PostgreSQL: pgsql/src/include/access/nbtree.h,v 1.109 2007/01/20 18:43:35 neilc Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -390,9 +390,6 @@ typedef BTStackData *BTStack;
* items were killed, we re-lock the page to mark them killed, then unlock. * items were killed, we re-lock the page to mark them killed, then unlock.
* Finally we drop the pin and step to the next page in the appropriate * Finally we drop the pin and step to the next page in the appropriate
* direction. * direction.
*
* NOTE: in this implementation, btree does not use or set the
* currentItemData and currentMarkData fields of IndexScanDesc at all.
*/ */
typedef struct BTScanPosItem /* what we remember about each match */ typedef struct BTScanPosItem /* what we remember about each match */

@ -7,7 +7,7 @@
* Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group * Portions Copyright (c) 1996-2007, PostgreSQL Global Development Group
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* $PostgreSQL: pgsql/src/include/access/relscan.h,v 1.51 2007/01/05 22:19:51 momjian Exp $ * $PostgreSQL: pgsql/src/include/access/relscan.h,v 1.52 2007/01/20 18:43:35 neilc Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
@ -69,9 +69,6 @@ typedef struct IndexScanDescData
/* index access method's private state */ /* index access method's private state */
void *opaque; /* access-method-specific info */ void *opaque; /* access-method-specific info */
/* these fields are used by some but not all AMs: */
ItemPointerData currentItemData; /* current index pointer */
ItemPointerData currentMarkData; /* marked position, if any */
/* /*
* xs_ctup/xs_cbuf are valid after a successful index_getnext. After * xs_ctup/xs_cbuf are valid after a successful index_getnext. After

Loading…
Cancel
Save