Commit 4c4eb571 authored by Tom Lane's avatar Tom Lane

Some marginal additional hacking to shave a few more cycles off

heapgettup.
parent 70f1482d
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * 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 * INTERFACE ROUTINES
...@@ -194,9 +194,7 @@ heapgettup(HeapScanDesc scan, ...@@ -194,9 +194,7 @@ heapgettup(HeapScanDesc scan,
ScanKey key) ScanKey key)
{ {
HeapTuple tuple = &(scan->rs_ctup); HeapTuple tuple = &(scan->rs_ctup);
ItemPointer tid = &(tuple->t_self);
Snapshot snapshot = scan->rs_snapshot; Snapshot snapshot = scan->rs_snapshot;
BlockNumber pages = scan->rs_nblocks;
BlockNumber page; BlockNumber page;
Page dp; Page dp;
int lines; int lines;
...@@ -204,65 +202,70 @@ heapgettup(HeapScanDesc scan, ...@@ -204,65 +202,70 @@ heapgettup(HeapScanDesc scan,
int linesleft; int linesleft;
ItemId lpp; ItemId lpp;
/*
* calculate next starting lineoff, given scan direction
*/
if (dir > 0)
{
/*
* forward scan direction
*/
if (!scan->rs_inited) if (!scan->rs_inited)
{ {
/* /*
* return null immediately if relation is empty * return null immediately if relation is empty
*/ */
if (pages == 0) if (scan->rs_nblocks == 0)
{ {
Assert(!BufferIsValid(scan->rs_cbuf)); Assert(!BufferIsValid(scan->rs_cbuf));
tuple->t_data = NULL; tuple->t_data = NULL;
return; return;
} }
page = 0; /* first page */
heapgetpage(scan, page);
lineoff = FirstOffsetNumber; /* first offnum */
scan->rs_inited = true;
} }
else else
{ {
/* resuming scan from tuple indicated by scan->rs_ctup.t_self */ /* continue from previously returned page/tuple */
Assert(ItemPointerIsValid(tid)); page = scan->rs_cblock; /* current page */
lineoff = /* next offnum */
OffsetNumberNext(ItemPointerGetOffsetNumber(&(tuple->t_self)));
} }
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
dp = (Page) BufferGetPage(scan->rs_cbuf);
lines = PageGetMaxOffsetNumber(dp);
/* page and lineoff now reference the physically next tid */
linesleft = lines - lineoff + 1;
}
else if (dir < 0)
{
/* /*
* calculate next starting lineoff, given scan direction * reverse scan direction
*/ */
if (dir == 0) if (!scan->rs_inited)
{ {
/* /*
* ``no movement'' scan direction: refetch prior tuple * return null immediately if relation is empty
*/ */
if (!scan->rs_inited) if (scan->rs_nblocks == 0)
{ {
Assert(!BufferIsValid(scan->rs_cbuf)); Assert(!BufferIsValid(scan->rs_cbuf));
tuple->t_data = NULL; tuple->t_data = NULL;
return; return;
} }
page = scan->rs_nblocks - 1; /* final page */
page = ItemPointerGetBlockNumber(tid);
if (page != scan->rs_cblock)
heapgetpage(scan, page); heapgetpage(scan, page);
/* 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);
return;
} }
else if (dir < 0)
{
/*
* reverse scan direction
*/
if (!scan->rs_inited)
page = pages - 1; /* final page */
else else
page = ItemPointerGetBlockNumber(tid); /* current page */ {
/* continue from previously returned page/tuple */
if (page != scan->rs_cblock) page = scan->rs_cblock; /* current page */
heapgetpage(scan, page); }
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE); LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
...@@ -277,47 +280,38 @@ heapgettup(HeapScanDesc scan, ...@@ -277,47 +280,38 @@ heapgettup(HeapScanDesc scan,
else else
{ {
lineoff = /* previous offnum */ lineoff = /* previous offnum */
OffsetNumberPrev(ItemPointerGetOffsetNumber(tid)); OffsetNumberPrev(ItemPointerGetOffsetNumber(&(tuple->t_self)));
} }
/* page and lineoff now reference the physically previous tid */ /* page and lineoff now reference the physically previous tid */
linesleft = lineoff;
} }
else else
{ {
/* /*
* forward scan direction * ``no movement'' scan direction: refetch prior tuple
*/ */
if (!scan->rs_inited) if (!scan->rs_inited)
{ {
page = 0; /* first page */ Assert(!BufferIsValid(scan->rs_cbuf));
lineoff = FirstOffsetNumber; /* first offnum */ tuple->t_data = NULL;
scan->rs_inited = true; return;
}
else
{
page = ItemPointerGetBlockNumber(tid); /* current page */
lineoff = /* next offnum */
OffsetNumberNext(ItemPointerGetOffsetNumber(tid));
} }
page = ItemPointerGetBlockNumber(&(tuple->t_self));
if (page != scan->rs_cblock) if (page != scan->rs_cblock)
heapgetpage(scan, page); 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); dp = (Page) BufferGetPage(scan->rs_cbuf);
lines = PageGetMaxOffsetNumber(dp); lineoff = ItemPointerGetOffsetNumber(&(tuple->t_self));
/* page and lineoff now reference the physically next tid */ lpp = PageGetItemId(dp, lineoff);
}
/* 'dir' is now non-zero */ tuple->t_data = (HeapTupleHeader) PageGetItem((Page) dp, lpp);
tuple->t_len = ItemIdGetLength(lpp);
/* return;
* calculate number of remaining items to check on this page }
*/
if (dir < 0)
linesleft = lineoff;
else
linesleft = lines - lineoff + 1;
/* /*
* advance the scan until we find a qualifying tuple or run out of stuff * advance the scan until we find a qualifying tuple or run out of stuff
...@@ -379,7 +373,7 @@ heapgettup(HeapScanDesc scan, ...@@ -379,7 +373,7 @@ heapgettup(HeapScanDesc scan,
/* /*
* return NULL if we've exhausted all the pages * 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)) if (BufferIsValid(scan->rs_cbuf))
ReleaseBuffer(scan->rs_cbuf); ReleaseBuffer(scan->rs_cbuf);
...@@ -432,8 +426,6 @@ heapgettup_pagemode(HeapScanDesc scan, ...@@ -432,8 +426,6 @@ heapgettup_pagemode(HeapScanDesc scan,
ScanKey key) ScanKey key)
{ {
HeapTuple tuple = &(scan->rs_ctup); HeapTuple tuple = &(scan->rs_ctup);
ItemPointer tid = &(tuple->t_self);
BlockNumber pages = scan->rs_nblocks;
BlockNumber page; BlockNumber page;
Page dp; Page dp;
int lines; int lines;
...@@ -442,69 +434,67 @@ heapgettup_pagemode(HeapScanDesc scan, ...@@ -442,69 +434,67 @@ heapgettup_pagemode(HeapScanDesc scan,
int linesleft; int linesleft;
ItemId lpp; ItemId lpp;
/*
* calculate next starting lineindex, given scan direction
*/
if (dir > 0)
{
/*
* forward scan direction
*/
if (!scan->rs_inited) if (!scan->rs_inited)
{ {
/* /*
* return null immediately if relation is empty * return null immediately if relation is empty
*/ */
if (pages == 0) if (scan->rs_nblocks == 0)
{ {
Assert(!BufferIsValid(scan->rs_cbuf)); Assert(!BufferIsValid(scan->rs_cbuf));
tuple->t_data = NULL; tuple->t_data = NULL;
return; return;
} }
page = 0; /* first page */
heapgetpage(scan, page);
lineindex = 0;
scan->rs_inited = true;
} }
else else
{ {
/* resuming scan from tuple indicated by scan->rs_ctup.t_self */ /* continue from previously returned page/tuple */
Assert(ItemPointerIsValid(tid)); page = scan->rs_cblock; /* current page */
lineindex = scan->rs_cindex + 1;
} }
dp = (Page) BufferGetPage(scan->rs_cbuf);
lines = scan->rs_ntuples;
/* page and lineindex now reference the next visible tid */
linesleft = lines - lineindex;
}
else if (dir < 0)
{
/* /*
* calculate next starting lineindex, given scan direction * reverse scan direction
*/ */
if (dir == 0) if (!scan->rs_inited)
{ {
/* /*
* ``no movement'' scan direction: refetch prior tuple * return null immediately if relation is empty
*/ */
if (!scan->rs_inited) if (scan->rs_nblocks == 0)
{ {
Assert(!BufferIsValid(scan->rs_cbuf)); Assert(!BufferIsValid(scan->rs_cbuf));
tuple->t_data = NULL; tuple->t_data = NULL;
return; return;
} }
page = scan->rs_nblocks - 1; /* final page */
page = ItemPointerGetBlockNumber(tid);
if (page != scan->rs_cblock)
heapgetpage(scan, page); heapgetpage(scan, page);
/* 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]);
return;
} }
else if (dir < 0)
{
/*
* reverse scan direction
*/
if (!scan->rs_inited)
page = pages - 1; /* final page */
else else
page = ItemPointerGetBlockNumber(tid); /* current page */ {
/* continue from previously returned page/tuple */
if (page != scan->rs_cblock) page = scan->rs_cblock; /* current page */
heapgetpage(scan, page); }
dp = (Page) BufferGetPage(scan->rs_cbuf); dp = (Page) BufferGetPage(scan->rs_cbuf);
lines = scan->rs_ntuples; lines = scan->rs_ntuples;
...@@ -519,41 +509,39 @@ heapgettup_pagemode(HeapScanDesc scan, ...@@ -519,41 +509,39 @@ heapgettup_pagemode(HeapScanDesc scan,
lineindex = scan->rs_cindex - 1; lineindex = scan->rs_cindex - 1;
} }
/* page and lineindex now reference the previous visible tid */ /* page and lineindex now reference the previous visible tid */
linesleft = lineindex + 1;
} }
else else
{ {
/* /*
* forward scan direction * ``no movement'' scan direction: refetch prior tuple
*/ */
if (!scan->rs_inited) if (!scan->rs_inited)
{ {
page = 0; /* first page */ Assert(!BufferIsValid(scan->rs_cbuf));
lineindex = 0; tuple->t_data = NULL;
scan->rs_inited = true; return;
}
else
{
page = ItemPointerGetBlockNumber(tid); /* current page */
lineindex = scan->rs_cindex + 1;
} }
page = ItemPointerGetBlockNumber(&(tuple->t_self));
if (page != scan->rs_cblock) if (page != scan->rs_cblock)
heapgetpage(scan, page); heapgetpage(scan, page);
/* Since the tuple was previously fetched, needn't lock page here */
dp = (Page) BufferGetPage(scan->rs_cbuf); dp = (Page) BufferGetPage(scan->rs_cbuf);
lines = scan->rs_ntuples; lineoff = ItemPointerGetOffsetNumber(&(tuple->t_self));
/* page and lineindex now reference the next visible tid */ lpp = PageGetItemId(dp, lineoff);
}
/* 'dir' is now non-zero */ tuple->t_data = (HeapTupleHeader) PageGetItem((Page) dp, lpp);
tuple->t_len = ItemIdGetLength(lpp);
/* /* check that rs_cindex is in sync */
* calculate number of remaining items to check on this page Assert(scan->rs_cindex < scan->rs_ntuples);
*/ Assert(lineoff == scan->rs_vistuples[scan->rs_cindex]);
if (dir < 0)
linesleft = lineindex + 1; return;
else }
linesleft = lines - lineindex;
/* /*
* advance the scan until we find a qualifying tuple or run out of stuff * advance the scan until we find a qualifying tuple or run out of stuff
...@@ -614,7 +602,7 @@ heapgettup_pagemode(HeapScanDesc scan, ...@@ -614,7 +602,7 @@ heapgettup_pagemode(HeapScanDesc scan,
/* /*
* return NULL if we've exhausted all the pages * 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)) if (BufferIsValid(scan->rs_cbuf))
ReleaseBuffer(scan->rs_cbuf); ReleaseBuffer(scan->rs_cbuf);
...@@ -2743,6 +2731,7 @@ heap_restrpos(HeapScanDesc scan) ...@@ -2743,6 +2731,7 @@ heap_restrpos(HeapScanDesc scan)
ReleaseBuffer(scan->rs_cbuf); ReleaseBuffer(scan->rs_cbuf);
scan->rs_cbuf = InvalidBuffer; scan->rs_cbuf = InvalidBuffer;
scan->rs_cblock = InvalidBlockNumber; scan->rs_cblock = InvalidBlockNumber;
scan->rs_inited = false;
} }
else else
{ {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment