77 *
88 *
99 * IDENTIFICATION
10- * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.53 1999/07/17 20:16:43 momjian Exp $
10+ * $Header: /cvsroot/pgsql/src/backend/access/nbtree/nbtsearch.c,v 1.54 1999/09/27 18: 20:21 momjian Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
@@ -727,11 +727,15 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
727727RegProcedure proc ;
728728int result ;
729729BTScanOpaque so ;
730- ScanKeyData skdata ;
731730Size keysok ;
732- int i ;
733- int nKeyIndex = -1 ;
734731
732+ bool strategyCheck ;
733+ ScanKey scankeys = 0 ;
734+ int keysCount = 0 ;
735+ int * nKeyIs = 0 ;
736+ int i ,j ;
737+ StrategyNumber strat_total ;
738+
735739rel = scan -> relation ;
736740so = (BTScanOpaque )scan -> opaque ;
737741
@@ -742,38 +746,57 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
742746so -> numberOfFirstKeys = 0 ;/* may be changed by _bt_orderkeys */
743747so -> qual_ok = 1 ;/* may be changed by _bt_orderkeys */
744748scan -> scanFromEnd = false;
749+ strategyCheck = false;
745750if (so -> numberOfKeys > 0 )
746751{
747752_bt_orderkeys (rel ,so );
748753
749- if (ScanDirectionIsBackward (dir ))
754+ if (so -> qual_ok )
755+ strategyCheck = true;
756+ }
757+ strat_total = BTEqualStrategyNumber ;
758+ if (strategyCheck )
759+ {
760+ AttrNumber attno ;
761+
762+ nKeyIs = (int * )palloc (so -> numberOfKeys * sizeof (int ));
763+ for (i = 0 ;i < so -> numberOfKeys ;i ++ )
750764{
751- for (i = 0 ;i < so -> numberOfKeys ;i ++ )
765+ attno = so -> keyData [i ].sk_attno ;
766+ if (attno == keysCount )
767+ continue ;
768+ if (attno > keysCount + 1 )
769+ break ;
770+ strat = _bt_getstrat (rel ,attno ,
771+ so -> keyData [i ].sk_procedure );
772+ if (strat == strat_total ||
773+ strat == BTEqualStrategyNumber )
752774{
753- if (so -> keyData [i ].sk_attno != 1 )
775+ nKeyIs [keysCount ++ ]= i ;
776+ continue ;
777+ }
778+ if (ScanDirectionIsBackward (dir )&&
779+ (strat == BTLessStrategyNumber ||
780+ strat == BTLessEqualStrategyNumber ) )
781+ {
782+ nKeyIs [keysCount ++ ]= i ;
783+ strat_total = strat ;
784+ if (strat == BTLessStrategyNumber )
754785break ;
755- strat = _bt_getstrat (rel ,so -> keyData [i ].sk_attno ,
756- so -> keyData [i ].sk_procedure );
757- if (strat == BTLessStrategyNumber ||
758- strat == BTLessEqualStrategyNumber ||
759- strat == BTEqualStrategyNumber )
760- {
761- nKeyIndex = i ;
786+ continue ;
787+ }
788+ if (ScanDirectionIsForward (dir )&&
789+ (strat == BTGreaterStrategyNumber ||
790+ strat == BTGreaterEqualStrategyNumber ) )
791+ {
792+ nKeyIs [keysCount ++ ]= i ;
793+ strat_total = strat ;
794+ if (strat == BTGreaterStrategyNumber )
762795break ;
763- }
796+ continue ;
764797}
765798}
766- else
767- {
768- strat = _bt_getstrat (rel ,1 ,so -> keyData [0 ].sk_procedure );
769-
770- if (strat == BTLessStrategyNumber ||
771- strat == BTLessEqualStrategyNumber )
772- ;
773- else
774- nKeyIndex = 0 ;
775- }
776- if (nKeyIndex < 0 )
799+ if (!keysCount )
777800scan -> scanFromEnd = true;
778801}
779802else
@@ -784,7 +807,11 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
784807
785808/* if we just need to walk down one edge of the tree, do that */
786809if (scan -> scanFromEnd )
810+ {
811+ if (nKeyIs )
812+ pfree (nKeyIs );
787813return _bt_endpoint (scan ,dir );
814+ }
788815
789816itupdesc = RelationGetDescr (rel );
790817current = & (scan -> currentItemData );
@@ -796,16 +823,24 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
796823 * at the right place in the scan.
797824 */
798825/* _bt_orderkeys disallows it, but it's place to add some code latter */
799- if (so -> keyData [0 ].sk_flags & SK_ISNULL )
826+ scankeys = (ScanKey )palloc (keysCount * sizeof (ScanKeyData ));
827+ for (i = 0 ;i < keysCount ;i ++ )
800828{
801- elog (ERROR ,"_bt_first: btree doesn't support is(not)null, yet" );
802- return (RetrieveIndexResult )NULL ;
829+ j = nKeyIs [i ];
830+ if (so -> keyData [j ].sk_flags & SK_ISNULL )
831+ {
832+ pfree (nKeyIs );
833+ pfree (scankeys );
834+ elog (ERROR ,"_bt_first: btree doesn't support is(not)null, yet" );
835+ return ((RetrieveIndexResult )NULL );
836+ }
837+ proc = index_getprocid (rel ,i + 1 ,BTORDER_PROC );
838+ ScanKeyEntryInitialize (scankeys + i ,so -> keyData [j ].sk_flags ,
839+ i + 1 ,proc ,so -> keyData [j ].sk_argument );
803840}
804- proc = index_getprocid (rel ,1 ,BTORDER_PROC );
805- ScanKeyEntryInitialize (& skdata ,so -> keyData [nKeyIndex ].sk_flags ,
806- 1 ,proc ,so -> keyData [nKeyIndex ].sk_argument );
841+ if (nKeyIs )pfree (nKeyIs );
807842
808- stack = _bt_search (rel ,1 , & skdata ,& buf );
843+ stack = _bt_search (rel ,keysCount , scankeys ,& buf );
809844_bt_freestack (stack );
810845
811846blkno = BufferGetBlockNumber (buf );
@@ -823,6 +858,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
823858ItemPointerSetInvalid (current );
824859so -> btso_curbuf = InvalidBuffer ;
825860_bt_relbuf (rel ,buf ,BT_READ );
861+ pfree (scankeys );
826862return (RetrieveIndexResult )NULL ;
827863}
828864maxoff = PageGetMaxOffsetNumber (page );
@@ -835,7 +871,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
835871 */
836872
837873while (maxoff == P_HIKEY && !P_RIGHTMOST (pop )&&
838- _bt_skeycmp (rel ,1 , & skdata ,page ,
874+ _bt_skeycmp (rel ,keysCount , scankeys ,page ,
839875PageGetItemId (page ,P_HIKEY ),
840876BTGreaterEqualStrategyNumber ))
841877{
@@ -849,6 +885,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
849885ItemPointerSetInvalid (current );
850886so -> btso_curbuf = InvalidBuffer ;
851887_bt_relbuf (rel ,buf ,BT_READ );
888+ pfree (scankeys );
852889return (RetrieveIndexResult )NULL ;
853890}
854891maxoff = PageGetMaxOffsetNumber (page );
@@ -857,7 +894,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
857894
858895
859896/* find the nearest match to the manufactured scan key on the page */
860- offnum = _bt_binsrch (rel ,buf ,1 , & skdata ,BT_DESCENT );
897+ offnum = _bt_binsrch (rel ,buf ,keysCount , scankeys ,BT_DESCENT );
861898
862899if (offnum > maxoff )
863900{
@@ -872,12 +909,11 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
872909 * we're looking for minus the value we're looking at in the index.
873910 */
874911
875- result = _bt_compare (rel ,itupdesc ,page ,1 , & skdata ,offnum );
912+ result = _bt_compare (rel ,itupdesc ,page ,keysCount , scankeys ,offnum );
876913
877914/* it's yet other place to add some code latter for is(not)null */
878915
879- strat = _bt_getstrat (rel ,1 ,so -> keyData [nKeyIndex ].sk_procedure );
880-
916+ strat = strat_total ;
881917switch (strat )
882918{
883919case BTLessStrategyNumber :
@@ -890,7 +926,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
890926
891927offnum = ItemPointerGetOffsetNumber (current );
892928page = BufferGetPage (buf );
893- result = _bt_compare (rel ,itupdesc ,page ,1 , & skdata ,offnum );
929+ result = _bt_compare (rel ,itupdesc ,page ,keysCount , scankeys ,offnum );
894930}while (result <=0 );
895931
896932}
@@ -906,12 +942,11 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
906942
907943offnum = ItemPointerGetOffsetNumber (current );
908944page = BufferGetPage (buf );
909- result = _bt_compare (rel ,itupdesc ,page ,1 , & skdata ,offnum );
945+ result = _bt_compare (rel ,itupdesc ,page ,keysCount , scankeys ,offnum );
910946}while (result >=0 );
911-
912- if (result < 0 )
913- _bt_twostep (scan ,& buf ,BackwardScanDirection );
914947}
948+ if (result < 0 )
949+ _bt_twostep (scan ,& buf ,BackwardScanDirection );
915950break ;
916951
917952case BTEqualStrategyNumber :
@@ -920,6 +955,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
920955_bt_relbuf (scan -> relation ,buf ,BT_READ );
921956so -> btso_curbuf = InvalidBuffer ;
922957ItemPointerSetInvalid (& (scan -> currentItemData ));
958+ pfree (scankeys );
923959return (RetrieveIndexResult )NULL ;
924960}
925961else if (ScanDirectionIsBackward (dir ))
@@ -931,7 +967,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
931967
932968offnum = ItemPointerGetOffsetNumber (current );
933969page = BufferGetPage (buf );
934- result = _bt_compare (rel ,itupdesc ,page ,1 , & skdata ,offnum );
970+ result = _bt_compare (rel ,itupdesc ,page ,keysCount , scankeys ,offnum );
935971}while (result == 0 );
936972
937973if (result < 0 )
@@ -950,6 +986,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
950986_bt_relbuf (scan -> relation ,buf ,BT_READ );
951987so -> btso_curbuf = InvalidBuffer ;
952988ItemPointerSetInvalid (& (scan -> currentItemData ));
989+ pfree (scankeys );
953990return (RetrieveIndexResult )NULL ;
954991}
955992}
@@ -974,7 +1011,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
9741011
9751012page = BufferGetPage (buf );
9761013offnum = ItemPointerGetOffsetNumber (current );
977- result = _bt_compare (rel ,itupdesc ,page ,1 , & skdata ,offnum );
1014+ result = _bt_compare (rel ,itupdesc ,page ,keysCount , scankeys ,offnum );
9781015}while (result < 0 );
9791016
9801017if (result > 0 )
@@ -993,12 +1030,13 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
9931030
9941031offnum = ItemPointerGetOffsetNumber (current );
9951032page = BufferGetPage (buf );
996- result = _bt_compare (rel ,itupdesc ,page ,1 , & skdata ,offnum );
1033+ result = _bt_compare (rel ,itupdesc ,page ,keysCount , scankeys ,offnum );
9971034}while (result >=0 );
9981035}
9991036break ;
10001037}
10011038
1039+ pfree (scankeys );
10021040/* okay, current item pointer for the scan is right */
10031041offnum = ItemPointerGetOffsetNumber (current );
10041042page = BufferGetPage (buf );