Some marginal additional hacking to shave a few more cycles off
authorTom Lane
Sat, 26 Nov 2005 05:03:06 +0000 (05:03 +0000)
committerTom Lane
Sat, 26 Nov 2005 05:03:06 +0000 (05:03 +0000)
heapgettup.

src/backend/access/heap/heapam.c

index 0b750e72a7d53408b95a4cf5728f6ac720b65892..eeacff56c9d82a0d09eb7d953cea0d64f378a8c8 100644 (file)
@@ -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
    {