88 * Portions Copyright (c) 1994, Regents of the University of California
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.85 2003/12/2103:00:04 tgl Exp $
11+ * $PostgreSQL: pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.86 2003/12/2117:52:34 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -496,6 +496,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
496496StrategyNumber strat ;
497497bool res ;
498498bool nextkey ;
499+ bool goback ;
499500bool continuescan ;
500501ScanKey scankeys ;
501502ScanKey * startKeys = NULL ;
@@ -695,18 +696,41 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
695696pfree (startKeys );
696697
697698/*
698- * We want to locate either the first item >= boundary point, or
699- * first item > boundary point, depending on the initial-positioning
700- * strategy we just chose.
699+ * Examine the selected initial-positioning strategy to determine
700+ * exactly where we need to start the scan, and set flag variables
701+ * to control the code below.
702+ *
703+ * If nextkey = false, _bt_search and _bt_binsrch will locate the
704+ * first item >= scan key. If nextkey = true, they will locate the
705+ * first item > scan key.
706+ *
707+ * If goback = true, we will then step back one item, while if
708+ * goback = false, we will start the scan on the located item.
709+ *
710+ * it's yet other place to add some code later for is(not)null ...
701711 */
702712switch (strat_total )
703713{
704714case BTLessStrategyNumber :
715+ /*
716+ * Find first item >= scankey, then back up one to arrive at last
717+ * item < scankey. (Note: this positioning strategy is only used
718+ * for a backward scan, so that is always the correct starting
719+ * position.)
720+ */
705721nextkey = false;
722+ goback = true;
706723break ;
707724
708725case BTLessEqualStrategyNumber :
726+ /*
727+ * Find first item > scankey, then back up one to arrive at last
728+ * item <= scankey. (Note: this positioning strategy is only used
729+ * for a backward scan, so that is always the correct starting
730+ * position.)
731+ */
709732nextkey = true;
733+ goback = true;
710734break ;
711735
712736case BTEqualStrategyNumber :
@@ -715,17 +739,41 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
715739 * equal item not first one.
716740 */
717741if (ScanDirectionIsBackward (dir ))
742+ {
743+ /*
744+ * This is the same as the <= strategy. We will check
745+ * at the end whether the found item is actually =.
746+ */
718747nextkey = true;
748+ goback = true;
749+ }
719750else
751+ {
752+ /*
753+ * This is the same as the >= strategy. We will check
754+ * at the end whether the found item is actually =.
755+ */
720756nextkey = false;
757+ goback = false;
758+ }
721759break ;
722760
723761case BTGreaterEqualStrategyNumber :
762+ /*
763+ * Find first item >= scankey. (This is only used for
764+ * forward scans.)
765+ */
724766nextkey = false;
767+ goback = false;
725768break ;
726769
727770case BTGreaterStrategyNumber :
771+ /*
772+ * Find first item > scankey. (This is only used for
773+ * forward scans.)
774+ */
728775nextkey = true;
776+ goback = false;
729777break ;
730778
731779default :
@@ -756,21 +804,18 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
756804
757805/* remember which buffer we have pinned */
758806so -> btso_curbuf = buf ;
759- blkno = BufferGetBlockNumber (buf );
760- page = BufferGetPage (buf );
761807
762808/* position to the precise item on the page */
763809offnum = _bt_binsrch (rel ,buf ,keysCount ,scankeys ,nextkey );
764810
811+ page = BufferGetPage (buf );
812+ blkno = BufferGetBlockNumber (buf );
765813ItemPointerSet (current ,blkno ,offnum );
766814
767815/* done with manufactured scankey, now */
768816pfree (scankeys );
769817
770818/*
771- * It's now time to examine the initial-positioning strategy to find the
772- * exact place to start the scan.
773- *
774819 * If nextkey = false, we are positioned at the first item >= scan key,
775820 * or possibly at the end of a page on which all the existing items are
776821 * less than the scan key and we know that everything on later pages
@@ -781,103 +826,29 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
781826 * less than or equal to the scan key and we know that everything on
782827 * later pages is greater than scan key.
783828 *
784- * The actually desired starting point is either this item oran adjacent
785- * one, or in the end-of-page case it's thelast item onthis page or
786- * thefirst item onthe next . We apply _bt_step if needed to get to
829+ * The actually desired starting point is either this item orthe prior
830+ * one, or in the end-of-page case it's thefirst item onthe next page
831+ *or thelast item onthis page . We apply _bt_step if needed to get to
787832 * the right place.
788833 *
789- *Note: if _bt_step fails (meaning we fell off the end of the index in
834+ *If _bt_step fails (meaning we fell off the end of the index in
790835 * one direction or the other), then there are no matches so we just
791836 * return false.
792- *
793- * it's yet other place to add some code later for is(not)null ...
794837 */
795- switch ( strat_total )
838+ if ( goback )
796839{
797- case BTLessStrategyNumber :
798-
799- /*
800- * We are on first item >= scankey.
801- *
802- * Back up one to arrive at last item < scankey. (Note: this
803- * positioning strategy is only used for a backward scan, so
804- * that is always the correct starting position.)
805- */
806- if (!_bt_step (scan ,& buf ,BackwardScanDirection ))
807- return false;
808- break ;
809-
810- case BTLessEqualStrategyNumber :
811-
812- /*
813- * We are on first item > scankey.
814- *
815- * Back up one to arrive at last item <= scankey. (Note: this
816- * positioning strategy is only used for a backward scan, so
817- * that is always the correct starting position.)
818- */
819- if (!_bt_step (scan ,& buf ,BackwardScanDirection ))
840+ /* _bt_step will do the right thing if we are at end-of-page */
841+ if (!_bt_step (scan ,& buf ,BackwardScanDirection ))
842+ return false;
843+ }
844+ else
845+ {
846+ /* If we're at end-of-page, must step forward to next page */
847+ if (offnum > PageGetMaxOffsetNumber (page ))
848+ {
849+ if (!_bt_step (scan ,& buf ,ForwardScanDirection ))
820850return false;
821- break ;
822-
823- case BTEqualStrategyNumber :
824- /*
825- * If a backward scan was specified, need to start with last
826- * equal item not first one.
827- */
828- if (ScanDirectionIsBackward (dir ))
829- {
830- /*
831- * We are on first item > scankey.
832- *
833- * Back up one to arrive at last item <= scankey.
834- * We will check below to see if it is equal to scankey.
835- */
836- if (!_bt_step (scan ,& buf ,BackwardScanDirection ))
837- return false;
838- }
839- else
840- {
841- /*
842- * We are on first item >= scankey.
843- *
844- * Make sure we are on a real item; might have to
845- * step forward if currently at end of page.
846- * We will check below to see if it is equal to scankey.
847- */
848- if (offnum > PageGetMaxOffsetNumber (page ))
849- {
850- if (!_bt_step (scan ,& buf ,ForwardScanDirection ))
851- return false;
852- }
853- }
854- break ;
855-
856- case BTGreaterEqualStrategyNumber :
857-
858- /*
859- * We want the first item >= scankey, which is where we are...
860- * unless we're not anywhere at all...
861- */
862- if (offnum > PageGetMaxOffsetNumber (page ))
863- {
864- if (!_bt_step (scan ,& buf ,ForwardScanDirection ))
865- return false;
866- }
867- break ;
868-
869- case BTGreaterStrategyNumber :
870-
871- /*
872- * We want the first item > scankey, which is where we are...
873- * unless we're not anywhere at all...
874- */
875- if (offnum > PageGetMaxOffsetNumber (page ))
876- {
877- if (!_bt_step (scan ,& buf ,ForwardScanDirection ))
878- return false;
879- }
880- break ;
851+ }
881852}
882853
883854/* okay, current item pointer for the scan is right */