aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/backend/access/heap/heapam.c257
1 files changed, 123 insertions, 134 deletions
diff --git a/src/backend/access/heap/heapam.c b/src/backend/access/heap/heapam.c
index 0b750e72a7d..eeacff56c9d 100644
--- a/src/backend/access/heap/heapam.c
+++ b/src/backend/access/heap/heapam.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.204 2005/11/26 03:03:07 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.205 2005/11/26 05:03:06 tgl Exp $
*
*
* INTERFACE ROUTINES
@@ -194,9 +194,7 @@ heapgettup(HeapScanDesc scan,
ScanKey key)
{
HeapTuple tuple = &(scan->rs_ctup);
- ItemPointer tid = &(tuple->t_self);
Snapshot snapshot = scan->rs_snapshot;
- BlockNumber pages = scan->rs_nblocks;
BlockNumber page;
Page dp;
int lines;
@@ -204,52 +202,45 @@ heapgettup(HeapScanDesc scan,
int linesleft;
ItemId lpp;
- if (!scan->rs_inited)
- {
- /*
- * return null immediately if relation is empty
- */
- if (pages == 0)
- {
- Assert(!BufferIsValid(scan->rs_cbuf));
- tuple->t_data = NULL;
- return;
- }
- }
- else
- {
- /* resuming scan from tuple indicated by scan->rs_ctup.t_self */
- Assert(ItemPointerIsValid(tid));
- }
-
/*
* calculate next starting lineoff, given scan direction
*/
- if (dir == 0)
+ if (dir > 0)
{
/*
- * ``no movement'' scan direction: refetch prior tuple
+ * forward scan direction
*/
if (!scan->rs_inited)
{
- Assert(!BufferIsValid(scan->rs_cbuf));
- tuple->t_data = NULL;
- return;
+ /*
+ * return null immediately if relation is empty
+ */
+ if (scan->rs_nblocks == 0)
+ {
+ Assert(!BufferIsValid(scan->rs_cbuf));
+ tuple->t_data = NULL;
+ return;
+ }
+ page = 0; /* first page */
+ heapgetpage(scan, page);
+ lineoff = FirstOffsetNumber; /* first offnum */
+ scan->rs_inited = true;
+ }
+ else
+ {
+ /* continue from previously returned page/tuple */
+ page = scan->rs_cblock; /* current page */
+ lineoff = /* next offnum */
+ OffsetNumberNext(ItemPointerGetOffsetNumber(&(tuple->t_self)));
}
- page = ItemPointerGetBlockNumber(tid);
- if (page != scan->rs_cblock)
- heapgetpage(scan, page);
+ LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
- /* Since the tuple was previously fetched, needn't lock page here */
dp = (Page) BufferGetPage(scan->rs_cbuf);
- lineoff = ItemPointerGetOffsetNumber(tid);
- lpp = PageGetItemId(dp, lineoff);
-
- tuple->t_data = (HeapTupleHeader) PageGetItem((Page) dp, lpp);
- tuple->t_len = ItemIdGetLength(lpp);
+ lines = PageGetMaxOffsetNumber(dp);
+ /* page and lineoff now reference the physically next tid */
- return;
+ linesleft = lines - lineoff + 1;
}
else if (dir < 0)
{
@@ -257,12 +248,24 @@ heapgettup(HeapScanDesc scan,
* reverse scan direction
*/
if (!scan->rs_inited)
- page = pages - 1; /* final page */
- else
- page = ItemPointerGetBlockNumber(tid); /* current page */
-
- if (page != scan->rs_cblock)
+ {
+ /*
+ * return null immediately if relation is empty
+ */
+ if (scan->rs_nblocks == 0)
+ {
+ Assert(!BufferIsValid(scan->rs_cbuf));
+ tuple->t_data = NULL;
+ return;
+ }
+ page = scan->rs_nblocks - 1; /* final page */
heapgetpage(scan, page);
+ }
+ else
+ {
+ /* continue from previously returned page/tuple */
+ page = scan->rs_cblock; /* current page */
+ }
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
@@ -271,53 +274,44 @@ heapgettup(HeapScanDesc scan,
if (!scan->rs_inited)
{
- lineoff = lines; /* final offnum */
+ lineoff = lines; /* final offnum */
scan->rs_inited = true;
}
else
{
- lineoff = /* previous offnum */
- OffsetNumberPrev(ItemPointerGetOffsetNumber(tid));
+ lineoff = /* previous offnum */
+ OffsetNumberPrev(ItemPointerGetOffsetNumber(&(tuple->t_self)));
}
/* page and lineoff now reference the physically previous tid */
+
+ linesleft = lineoff;
}
else
{
/*
- * forward scan direction
+ * ``no movement'' scan direction: refetch prior tuple
*/
if (!scan->rs_inited)
{
- page = 0; /* first page */
- lineoff = FirstOffsetNumber; /* first offnum */
- scan->rs_inited = true;
- }
- else
- {
- page = ItemPointerGetBlockNumber(tid); /* current page */
- lineoff = /* next offnum */
- OffsetNumberNext(ItemPointerGetOffsetNumber(tid));
+ Assert(!BufferIsValid(scan->rs_cbuf));
+ tuple->t_data = NULL;
+ return;
}
+ page = ItemPointerGetBlockNumber(&(tuple->t_self));
if (page != scan->rs_cblock)
heapgetpage(scan, page);
- LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
-
+ /* Since the tuple was previously fetched, needn't lock page here */
dp = (Page) BufferGetPage(scan->rs_cbuf);
- lines = PageGetMaxOffsetNumber(dp);
- /* page and lineoff now reference the physically next tid */
- }
+ lineoff = ItemPointerGetOffsetNumber(&(tuple->t_self));
+ lpp = PageGetItemId(dp, lineoff);
- /* 'dir' is now non-zero */
+ tuple->t_data = (HeapTupleHeader) PageGetItem((Page) dp, lpp);
+ tuple->t_len = ItemIdGetLength(lpp);
- /*
- * calculate number of remaining items to check on this page
- */
- if (dir < 0)
- linesleft = lineoff;
- else
- linesleft = lines - lineoff + 1;
+ return;
+ }
/*
* advance the scan until we find a qualifying tuple or run out of stuff
@@ -379,7 +373,7 @@ heapgettup(HeapScanDesc scan,
/*
* return NULL if we've exhausted all the pages
*/
- if ((dir < 0) ? (page == 0) : (page + 1 >= pages))
+ if ((dir < 0) ? (page == 0) : (page + 1 >= scan->rs_nblocks))
{
if (BufferIsValid(scan->rs_cbuf))
ReleaseBuffer(scan->rs_cbuf);
@@ -432,8 +426,6 @@ heapgettup_pagemode(HeapScanDesc scan,
ScanKey key)
{
HeapTuple tuple = &(scan->rs_ctup);
- ItemPointer tid = &(tuple->t_self);
- BlockNumber pages = scan->rs_nblocks;
BlockNumber page;
Page dp;
int lines;
@@ -442,56 +434,42 @@ heapgettup_pagemode(HeapScanDesc scan,
int linesleft;
ItemId lpp;
- if (!scan->rs_inited)
- {
- /*
- * return null immediately if relation is empty
- */
- if (pages == 0)
- {
- Assert(!BufferIsValid(scan->rs_cbuf));
- tuple->t_data = NULL;
- return;
- }
- }
- else
- {
- /* resuming scan from tuple indicated by scan->rs_ctup.t_self */
- Assert(ItemPointerIsValid(tid));
- }
-
/*
* calculate next starting lineindex, given scan direction
*/
- if (dir == 0)
+ if (dir > 0)
{
/*
- * ``no movement'' scan direction: refetch prior tuple
+ * forward scan direction
*/
if (!scan->rs_inited)
{
- Assert(!BufferIsValid(scan->rs_cbuf));
- tuple->t_data = NULL;
- return;
- }
-
- page = ItemPointerGetBlockNumber(tid);
- if (page != scan->rs_cblock)
+ /*
+ * return null immediately if relation is empty
+ */
+ if (scan->rs_nblocks == 0)
+ {
+ Assert(!BufferIsValid(scan->rs_cbuf));
+ tuple->t_data = NULL;
+ return;
+ }
+ page = 0; /* first page */
heapgetpage(scan, page);
+ lineindex = 0;
+ scan->rs_inited = true;
+ }
+ else
+ {
+ /* continue from previously returned page/tuple */
+ page = scan->rs_cblock; /* current page */
+ lineindex = scan->rs_cindex + 1;
+ }
- /* Since the tuple was previously fetched, needn't lock page here */
dp = (Page) BufferGetPage(scan->rs_cbuf);
- lineoff = ItemPointerGetOffsetNumber(tid);
- lpp = PageGetItemId(dp, lineoff);
-
- tuple->t_data = (HeapTupleHeader) PageGetItem((Page) dp, lpp);
- tuple->t_len = ItemIdGetLength(lpp);
-
- /* check that rs_cindex is in sync */
- Assert(scan->rs_cindex < scan->rs_ntuples);
- Assert(lineoff == scan->rs_vistuples[scan->rs_cindex]);
+ lines = scan->rs_ntuples;
+ /* page and lineindex now reference the next visible tid */
- return;
+ linesleft = lines - lineindex;
}
else if (dir < 0)
{
@@ -499,12 +477,24 @@ heapgettup_pagemode(HeapScanDesc scan,
* reverse scan direction
*/
if (!scan->rs_inited)
- page = pages - 1; /* final page */
- else
- page = ItemPointerGetBlockNumber(tid); /* current page */
-
- if (page != scan->rs_cblock)
+ {
+ /*
+ * return null immediately if relation is empty
+ */
+ if (scan->rs_nblocks == 0)
+ {
+ Assert(!BufferIsValid(scan->rs_cbuf));
+ tuple->t_data = NULL;
+ return;
+ }
+ page = scan->rs_nblocks - 1; /* final page */
heapgetpage(scan, page);
+ }
+ else
+ {
+ /* continue from previously returned page/tuple */
+ page = scan->rs_cblock; /* current page */
+ }
dp = (Page) BufferGetPage(scan->rs_cbuf);
lines = scan->rs_ntuples;
@@ -519,41 +509,39 @@ heapgettup_pagemode(HeapScanDesc scan,
lineindex = scan->rs_cindex - 1;
}
/* page and lineindex now reference the previous visible tid */
+
+ linesleft = lineindex + 1;
}
else
{
/*
- * forward scan direction
+ * ``no movement'' scan direction: refetch prior tuple
*/
if (!scan->rs_inited)
{
- page = 0; /* first page */
- lineindex = 0;
- scan->rs_inited = true;
- }
- else
- {
- page = ItemPointerGetBlockNumber(tid); /* current page */
- lineindex = scan->rs_cindex + 1;
+ Assert(!BufferIsValid(scan->rs_cbuf));
+ tuple->t_data = NULL;
+ return;
}
+ page = ItemPointerGetBlockNumber(&(tuple->t_self));
if (page != scan->rs_cblock)
heapgetpage(scan, page);
+ /* Since the tuple was previously fetched, needn't lock page here */
dp = (Page) BufferGetPage(scan->rs_cbuf);
- lines = scan->rs_ntuples;
- /* page and lineindex now reference the next visible tid */
- }
+ lineoff = ItemPointerGetOffsetNumber(&(tuple->t_self));
+ lpp = PageGetItemId(dp, lineoff);
- /* 'dir' is now non-zero */
+ tuple->t_data = (HeapTupleHeader) PageGetItem((Page) dp, lpp);
+ tuple->t_len = ItemIdGetLength(lpp);
- /*
- * calculate number of remaining items to check on this page
- */
- if (dir < 0)
- linesleft = lineindex + 1;
- else
- linesleft = lines - lineindex;
+ /* check that rs_cindex is in sync */
+ Assert(scan->rs_cindex < scan->rs_ntuples);
+ Assert(lineoff == scan->rs_vistuples[scan->rs_cindex]);
+
+ return;
+ }
/*
* advance the scan until we find a qualifying tuple or run out of stuff
@@ -614,7 +602,7 @@ heapgettup_pagemode(HeapScanDesc scan,
/*
* return NULL if we've exhausted all the pages
*/
- if ((dir < 0) ? (page == 0) : (page + 1 >= pages))
+ if ((dir < 0) ? (page == 0) : (page + 1 >= scan->rs_nblocks))
{
if (BufferIsValid(scan->rs_cbuf))
ReleaseBuffer(scan->rs_cbuf);
@@ -2743,6 +2731,7 @@ heap_restrpos(HeapScanDesc scan)
ReleaseBuffer(scan->rs_cbuf);
scan->rs_cbuf = InvalidBuffer;
scan->rs_cblock = InvalidBlockNumber;
+ scan->rs_inited = false;
}
else
{