7
7
*
8
8
*
9
9
* 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 $
11
11
*
12
12
*-------------------------------------------------------------------------
13
13
*/
@@ -727,11 +727,15 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
727
727
RegProcedure proc ;
728
728
int result ;
729
729
BTScanOpaque so ;
730
- ScanKeyData skdata ;
731
730
Size keysok ;
732
- int i ;
733
- int nKeyIndex = -1 ;
734
731
732
+ bool strategyCheck ;
733
+ ScanKey scankeys = 0 ;
734
+ int keysCount = 0 ;
735
+ int * nKeyIs = 0 ;
736
+ int i ,j ;
737
+ StrategyNumber strat_total ;
738
+
735
739
rel = scan -> relation ;
736
740
so = (BTScanOpaque )scan -> opaque ;
737
741
@@ -742,38 +746,57 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
742
746
so -> numberOfFirstKeys = 0 ;/* may be changed by _bt_orderkeys */
743
747
so -> qual_ok = 1 ;/* may be changed by _bt_orderkeys */
744
748
scan -> scanFromEnd = false;
749
+ strategyCheck = false;
745
750
if (so -> numberOfKeys > 0 )
746
751
{
747
752
_bt_orderkeys (rel ,so );
748
753
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 ++ )
750
764
{
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 )
752
774
{
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 )
754
785
break ;
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 )
762
795
break ;
763
- }
796
+ continue ;
764
797
}
765
798
}
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 )
777
800
scan -> scanFromEnd = true;
778
801
}
779
802
else
@@ -784,7 +807,11 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
784
807
785
808
/* if we just need to walk down one edge of the tree, do that */
786
809
if (scan -> scanFromEnd )
810
+ {
811
+ if (nKeyIs )
812
+ pfree (nKeyIs );
787
813
return _bt_endpoint (scan ,dir );
814
+ }
788
815
789
816
itupdesc = RelationGetDescr (rel );
790
817
current = & (scan -> currentItemData );
@@ -796,16 +823,24 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
796
823
* at the right place in the scan.
797
824
*/
798
825
/* _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 ++ )
800
828
{
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 );
803
840
}
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 );
807
842
808
- stack = _bt_search (rel ,1 , & skdata ,& buf );
843
+ stack = _bt_search (rel ,keysCount , scankeys ,& buf );
809
844
_bt_freestack (stack );
810
845
811
846
blkno = BufferGetBlockNumber (buf );
@@ -823,6 +858,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
823
858
ItemPointerSetInvalid (current );
824
859
so -> btso_curbuf = InvalidBuffer ;
825
860
_bt_relbuf (rel ,buf ,BT_READ );
861
+ pfree (scankeys );
826
862
return (RetrieveIndexResult )NULL ;
827
863
}
828
864
maxoff = PageGetMaxOffsetNumber (page );
@@ -835,7 +871,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
835
871
*/
836
872
837
873
while (maxoff == P_HIKEY && !P_RIGHTMOST (pop )&&
838
- _bt_skeycmp (rel ,1 , & skdata ,page ,
874
+ _bt_skeycmp (rel ,keysCount , scankeys ,page ,
839
875
PageGetItemId (page ,P_HIKEY ),
840
876
BTGreaterEqualStrategyNumber ))
841
877
{
@@ -849,6 +885,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
849
885
ItemPointerSetInvalid (current );
850
886
so -> btso_curbuf = InvalidBuffer ;
851
887
_bt_relbuf (rel ,buf ,BT_READ );
888
+ pfree (scankeys );
852
889
return (RetrieveIndexResult )NULL ;
853
890
}
854
891
maxoff = PageGetMaxOffsetNumber (page );
@@ -857,7 +894,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
857
894
858
895
859
896
/* 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 );
861
898
862
899
if (offnum > maxoff )
863
900
{
@@ -872,12 +909,11 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
872
909
* we're looking for minus the value we're looking at in the index.
873
910
*/
874
911
875
- result = _bt_compare (rel ,itupdesc ,page ,1 , & skdata ,offnum );
912
+ result = _bt_compare (rel ,itupdesc ,page ,keysCount , scankeys ,offnum );
876
913
877
914
/* it's yet other place to add some code latter for is(not)null */
878
915
879
- strat = _bt_getstrat (rel ,1 ,so -> keyData [nKeyIndex ].sk_procedure );
880
-
916
+ strat = strat_total ;
881
917
switch (strat )
882
918
{
883
919
case BTLessStrategyNumber :
@@ -890,7 +926,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
890
926
891
927
offnum = ItemPointerGetOffsetNumber (current );
892
928
page = BufferGetPage (buf );
893
- result = _bt_compare (rel ,itupdesc ,page ,1 , & skdata ,offnum );
929
+ result = _bt_compare (rel ,itupdesc ,page ,keysCount , scankeys ,offnum );
894
930
}while (result <=0 );
895
931
896
932
}
@@ -906,12 +942,11 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
906
942
907
943
offnum = ItemPointerGetOffsetNumber (current );
908
944
page = BufferGetPage (buf );
909
- result = _bt_compare (rel ,itupdesc ,page ,1 , & skdata ,offnum );
945
+ result = _bt_compare (rel ,itupdesc ,page ,keysCount , scankeys ,offnum );
910
946
}while (result >=0 );
911
-
912
- if (result < 0 )
913
- _bt_twostep (scan ,& buf ,BackwardScanDirection );
914
947
}
948
+ if (result < 0 )
949
+ _bt_twostep (scan ,& buf ,BackwardScanDirection );
915
950
break ;
916
951
917
952
case BTEqualStrategyNumber :
@@ -920,6 +955,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
920
955
_bt_relbuf (scan -> relation ,buf ,BT_READ );
921
956
so -> btso_curbuf = InvalidBuffer ;
922
957
ItemPointerSetInvalid (& (scan -> currentItemData ));
958
+ pfree (scankeys );
923
959
return (RetrieveIndexResult )NULL ;
924
960
}
925
961
else if (ScanDirectionIsBackward (dir ))
@@ -931,7 +967,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
931
967
932
968
offnum = ItemPointerGetOffsetNumber (current );
933
969
page = BufferGetPage (buf );
934
- result = _bt_compare (rel ,itupdesc ,page ,1 , & skdata ,offnum );
970
+ result = _bt_compare (rel ,itupdesc ,page ,keysCount , scankeys ,offnum );
935
971
}while (result == 0 );
936
972
937
973
if (result < 0 )
@@ -950,6 +986,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
950
986
_bt_relbuf (scan -> relation ,buf ,BT_READ );
951
987
so -> btso_curbuf = InvalidBuffer ;
952
988
ItemPointerSetInvalid (& (scan -> currentItemData ));
989
+ pfree (scankeys );
953
990
return (RetrieveIndexResult )NULL ;
954
991
}
955
992
}
@@ -974,7 +1011,7 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
974
1011
975
1012
page = BufferGetPage (buf );
976
1013
offnum = ItemPointerGetOffsetNumber (current );
977
- result = _bt_compare (rel ,itupdesc ,page ,1 , & skdata ,offnum );
1014
+ result = _bt_compare (rel ,itupdesc ,page ,keysCount , scankeys ,offnum );
978
1015
}while (result < 0 );
979
1016
980
1017
if (result > 0 )
@@ -993,12 +1030,13 @@ _bt_first(IndexScanDesc scan, ScanDirection dir)
993
1030
994
1031
offnum = ItemPointerGetOffsetNumber (current );
995
1032
page = BufferGetPage (buf );
996
- result = _bt_compare (rel ,itupdesc ,page ,1 , & skdata ,offnum );
1033
+ result = _bt_compare (rel ,itupdesc ,page ,keysCount , scankeys ,offnum );
997
1034
}while (result >=0 );
998
1035
}
999
1036
break ;
1000
1037
}
1001
1038
1039
+ pfree (scankeys );
1002
1040
/* okay, current item pointer for the scan is right */
1003
1041
offnum = ItemPointerGetOffsetNumber (current );
1004
1042
page = BufferGetPage (buf );