1
0
mirror of https://github.com/postgres/postgres.git synced 2025-07-30 11:03:19 +03:00

Some marginal additional hacking to shave a few more cycles off

heapgettup.
This commit is contained in:
Tom Lane
2005-11-26 05:03:06 +00:00
parent 70f1482de3
commit 4c4eb57154

View File

@ -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,
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,28 +202,91 @@ heapgettup(HeapScanDesc scan,
int linesleft; int linesleft;
ItemId lpp; 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 * calculate next starting lineoff, given scan direction
*/ */
if (dir == 0) if (dir > 0)
{
/*
* forward scan direction
*/
if (!scan->rs_inited)
{
/*
* 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)));
}
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)
{
/*
* reverse scan direction
*/
if (!scan->rs_inited)
{
/*
* 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);
dp = (Page) BufferGetPage(scan->rs_cbuf);
lines = PageGetMaxOffsetNumber(dp);
if (!scan->rs_inited)
{
lineoff = lines; /* final offnum */
scan->rs_inited = true;
}
else
{
lineoff = /* previous offnum */
OffsetNumberPrev(ItemPointerGetOffsetNumber(&(tuple->t_self)));
}
/* page and lineoff now reference the physically previous tid */
linesleft = lineoff;
}
else
{ {
/* /*
* ``no movement'' scan direction: refetch prior tuple * ``no movement'' scan direction: refetch prior tuple
@ -237,13 +298,13 @@ heapgettup(HeapScanDesc scan,
return; return;
} }
page = ItemPointerGetBlockNumber(tid); 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 */ /* Since the tuple was previously fetched, needn't lock page here */
dp = (Page) BufferGetPage(scan->rs_cbuf); dp = (Page) BufferGetPage(scan->rs_cbuf);
lineoff = ItemPointerGetOffsetNumber(tid); lineoff = ItemPointerGetOffsetNumber(&(tuple->t_self));
lpp = PageGetItemId(dp, lineoff); lpp = PageGetItemId(dp, lineoff);
tuple->t_data = (HeapTupleHeader) PageGetItem((Page) dp, lpp); tuple->t_data = (HeapTupleHeader) PageGetItem((Page) dp, lpp);
@ -251,73 +312,6 @@ heapgettup(HeapScanDesc scan,
return; return;
} }
else if (dir < 0)
{
/*
* reverse scan direction
*/
if (!scan->rs_inited)
page = pages - 1; /* final page */
else
page = ItemPointerGetBlockNumber(tid); /* current page */
if (page != scan->rs_cblock)
heapgetpage(scan, page);
LockBuffer(scan->rs_cbuf, BUFFER_LOCK_SHARE);
dp = (Page) BufferGetPage(scan->rs_cbuf);
lines = PageGetMaxOffsetNumber(dp);
if (!scan->rs_inited)
{
lineoff = lines; /* final offnum */
scan->rs_inited = true;
}
else
{
lineoff = /* previous offnum */
OffsetNumberPrev(ItemPointerGetOffsetNumber(tid));
}
/* page and lineoff now reference the physically previous tid */
}
else
{
/*
* forward scan direction
*/
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));
}
if (page != scan->rs_cblock)
heapgetpage(scan, page);
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 */
}
/* 'dir' is now non-zero */
/*
* 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,
/* /*
* 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,
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,56 +434,42 @@ heapgettup_pagemode(HeapScanDesc scan,
int linesleft; int linesleft;
ItemId lpp; 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 * 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) if (!scan->rs_inited)
{ {
Assert(!BufferIsValid(scan->rs_cbuf)); /*
tuple->t_data = NULL; * return null immediately if relation is empty
return; */
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;
} }
page = ItemPointerGetBlockNumber(tid);
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); dp = (Page) BufferGetPage(scan->rs_cbuf);
lineoff = ItemPointerGetOffsetNumber(tid); lines = scan->rs_ntuples;
lpp = PageGetItemId(dp, lineoff); /* page and lineindex now reference the next visible tid */
tuple->t_data = (HeapTupleHeader) PageGetItem((Page) dp, lpp); linesleft = lines - lineindex;
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) else if (dir < 0)
{ {
@ -499,12 +477,24 @@ heapgettup_pagemode(HeapScanDesc scan,
* reverse scan direction * reverse scan direction
*/ */
if (!scan->rs_inited) if (!scan->rs_inited)
page = pages - 1; /* final page */ {
else /*
page = ItemPointerGetBlockNumber(tid); /* current page */ * return null immediately if relation is empty
*/
if (page != scan->rs_cblock) 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); heapgetpage(scan, page);
}
else
{
/* continue from previously returned page/tuple */
page = scan->rs_cblock; /* current page */
}
dp = (Page) BufferGetPage(scan->rs_cbuf); dp = (Page) BufferGetPage(scan->rs_cbuf);
lines = scan->rs_ntuples; lines = scan->rs_ntuples;
@ -519,42 +509,40 @@ 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);
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;
} }
/* 'dir' is now non-zero */
/*
* calculate number of remaining items to check on this page
*/
if (dir < 0)
linesleft = lineindex + 1;
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
* to scan * to 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)
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
{ {