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 );
0 commit comments