12
12
* Portions Copyright (c) 1994, Regents of the University of California
13
13
*
14
14
* IDENTIFICATION
15
- * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.149 2006/05/10 23 :18:39 tgl Exp $
15
+ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtree.c,v 1.150 2006/08/24 01 :18:34 tgl Exp $
16
16
*
17
17
*-------------------------------------------------------------------------
18
18
*/
@@ -392,6 +392,7 @@ btrescan(PG_FUNCTION_ARGS)
392
392
ReleaseBuffer (so -> markPos .buf );
393
393
so -> markPos .buf = InvalidBuffer ;
394
394
}
395
+ so -> markItemIndex = -1 ;
395
396
396
397
/*
397
398
* Reset the scan keys. Note that keys ordering stuff moved to _bt_first.
@@ -430,6 +431,7 @@ btendscan(PG_FUNCTION_ARGS)
430
431
ReleaseBuffer (so -> markPos .buf );
431
432
so -> markPos .buf = InvalidBuffer ;
432
433
}
434
+ so -> markItemIndex = -1 ;
433
435
434
436
if (so -> killedItems != NULL )
435
437
pfree (so -> killedItems );
@@ -456,14 +458,16 @@ btmarkpos(PG_FUNCTION_ARGS)
456
458
so -> markPos .buf = InvalidBuffer ;
457
459
}
458
460
459
- /* bump pin on current buffer for assignment to mark buffer */
461
+ /*
462
+ * Just record the current itemIndex. If we later step to next page
463
+ * before releasing the marked position, _bt_steppage makes a full copy
464
+ * of the currPos struct in markPos. If (as often happens) the mark is
465
+ * moved before we leave the page, we don't have to do that work.
466
+ */
460
467
if (BTScanPosIsValid (so -> currPos ))
461
- {
462
- IncrBufferRefCount (so -> currPos .buf );
463
- memcpy (& so -> markPos , & so -> currPos ,
464
- offsetof(BTScanPosData , items [1 ]) +
465
- so -> currPos .lastItem * sizeof (BTScanPosItem ));
466
- }
468
+ so -> markItemIndex = so -> currPos .itemIndex ;
469
+ else
470
+ so -> markItemIndex = -1 ;
467
471
468
472
PG_RETURN_VOID ();
469
473
}
@@ -477,24 +481,35 @@ btrestrpos(PG_FUNCTION_ARGS)
477
481
IndexScanDesc scan = (IndexScanDesc ) PG_GETARG_POINTER (0 );
478
482
BTScanOpaque so = (BTScanOpaque ) scan -> opaque ;
479
483
480
- /* we aren't holding any read locks, but gotta drop the pin */
481
- if (BTScanPosIsValid (so -> currPos ))
484
+ if (so -> markItemIndex >= 0 )
482
485
{
483
- /* Before leaving current page, deal with any killed items */
484
- if (so -> numKilled > 0 &&
485
- so -> currPos .buf != so -> markPos .buf )
486
- _bt_killitems (scan , false);
487
- ReleaseBuffer (so -> currPos .buf );
488
- so -> currPos .buf = InvalidBuffer ;
489
- }
490
-
491
- /* bump pin on marked buffer */
492
- if (BTScanPosIsValid (so -> markPos ))
486
+ /*
487
+ * The mark position is on the same page we are currently on.
488
+ * Just restore the itemIndex.
489
+ */
490
+ so -> currPos .itemIndex = so -> markItemIndex ;
491
+ }
492
+ else
493
493
{
494
- IncrBufferRefCount (so -> markPos .buf );
495
- memcpy (& so -> currPos , & so -> markPos ,
496
- offsetof(BTScanPosData , items [1 ]) +
497
- so -> markPos .lastItem * sizeof (BTScanPosItem ));
494
+ /* we aren't holding any read locks, but gotta drop the pin */
495
+ if (BTScanPosIsValid (so -> currPos ))
496
+ {
497
+ /* Before leaving current page, deal with any killed items */
498
+ if (so -> numKilled > 0 &&
499
+ so -> currPos .buf != so -> markPos .buf )
500
+ _bt_killitems (scan , false);
501
+ ReleaseBuffer (so -> currPos .buf );
502
+ so -> currPos .buf = InvalidBuffer ;
503
+ }
504
+
505
+ if (BTScanPosIsValid (so -> markPos ))
506
+ {
507
+ /* bump pin on mark buffer for assignment to current buffer */
508
+ IncrBufferRefCount (so -> markPos .buf );
509
+ memcpy (& so -> currPos , & so -> markPos ,
510
+ offsetof(BTScanPosData , items [1 ]) +
511
+ so -> markPos .lastItem * sizeof (BTScanPosItem ));
512
+ }
498
513
}
499
514
500
515
PG_RETURN_VOID ();
0 commit comments