]> granicus.if.org Git - postgresql/commitdiff
Keep rs_startblock the same during heap_rescan, so that a rescan of a SeqScan
authorTom Lane <tgl@sss.pgh.pa.us>
Wed, 10 Jun 2009 18:54:23 +0000 (18:54 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Wed, 10 Jun 2009 18:54:23 +0000 (18:54 +0000)
node starts from the same place as the first scan did.  This avoids surprising
behavior of scrollable and WITH HOLD cursors, as seen in Mark Kirkwood's bug
report of yesterday.

It's not entirely clear whether a rescan should be forced to drop out of the
syncscan mode, but for the moment I left the code behaving the same on that
point.  Any change there would only be a performance and not a correctness
issue, anyway.

Back-patch to 8.3, since the unstable behavior was created by the syncscan
patch.

src/backend/access/heap/heapam.c

index 9fcb1fe397728079b0f9a9adcbbd942edf4335c4..566e431cca9f2b7d93693a3b351febcc48146ef5 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.249.2.4 2008/12/16 16:26:14 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/access/heap/heapam.c,v 1.249.2.5 2009/06/10 18:54:23 tgl Exp $
  *
  *
  * INTERFACE ROUTINES
@@ -84,7 +84,7 @@ static bool HeapSatisfiesHOTUpdate(Relation relation, Bitmapset *hot_attrs,
  * ----------------
  */
 static void
-initscan(HeapScanDesc scan, ScanKey key)
+initscan(HeapScanDesc scan, ScanKey key, bool is_rescan)
 {
        bool            allow_strat;
        bool            allow_sync;
@@ -134,7 +134,16 @@ initscan(HeapScanDesc scan, ScanKey key)
                scan->rs_strategy = NULL;
        }
 
-       if (allow_sync && synchronize_seqscans)
+       if (is_rescan)
+       {
+               /*
+                * If rescan, keep the previous startblock setting so that rewinding
+                * a cursor doesn't generate surprising results.  Reset the syncscan
+                * setting, though.
+                */
+               scan->rs_syncscan = (allow_sync && synchronize_seqscans);
+       }
+       else if (allow_sync && synchronize_seqscans)
        {
                scan->rs_syncscan = true;
                scan->rs_startblock = ss_get_location(scan->rs_rd, scan->rs_nblocks);
@@ -1177,7 +1186,7 @@ heap_beginscan_internal(Relation relation, Snapshot snapshot,
        else
                scan->rs_key = NULL;
 
-       initscan(scan, key);
+       initscan(scan, key, false);
 
        return scan;
 }
@@ -1199,7 +1208,7 @@ heap_rescan(HeapScanDesc scan,
        /*
         * reinitialize scan descriptor
         */
-       initscan(scan, key);
+       initscan(scan, key, true);
 }
 
 /* ----------------