@@ -38,7 +38,7 @@ static bool scanPage(RumState * rumstate, RumScanEntry entry, RumKey *item,
38
38
Page page , bool equalOk );
39
39
static void insertScanItem (RumScanOpaque so , bool recheck );
40
40
static int scan_entry_cmp (const void * p1 , const void * p2 , void * arg );
41
- static void entryGetItem (RumState * rumstate , RumScanEntry entry );
41
+ static void entryGetItem (RumState * rumstate , RumScanEntry entry , bool * nextEntryList );
42
42
43
43
44
44
/*
@@ -735,7 +735,7 @@ startScan(IndexScanDesc scan)
735
735
RumScanOpaque so = (RumScanOpaque ) scan -> opaque ;
736
736
RumState * rumstate = & so -> rumstate ;
737
737
uint32 i ;
738
- bool useFastScan = false ;
738
+ RumScanType scanType = RumRegularScan ;
739
739
740
740
MemoryContextSwitchTo (so -> keyCtx );
741
741
for (i = 0 ; i < so -> totalentries ; i ++ )
@@ -783,30 +783,36 @@ startScan(IndexScanDesc scan)
783
783
{
784
784
RumScanKey key = so -> keys [i ];
785
785
786
- if (so -> rumstate .canPreConsistent [key -> attnum - 1 ])
786
+ /* Check first key is it used to full-index scan */
787
+ if (i == 0 && key -> nentries > 0 && key -> scanEntry [i ]-> scanWithAddInfo )
787
788
{
788
- useFastScan = true;
789
+ scanType = RumFullScan ;
790
+ break ;
791
+ }
792
+ else if (so -> rumstate .canPreConsistent [key -> attnum - 1 ])
793
+ {
794
+ scanType = RumFastScan ;
789
795
break ;
790
796
}
791
797
}
792
798
793
- if (useFastScan )
799
+ if (scanType == RumFastScan )
794
800
{
795
801
for (i = 0 ; i < so -> totalentries ; i ++ )
796
802
{
797
803
RumScanEntry entry = so -> entries [i ];
798
804
799
805
if (entry -> isPartialMatch || entry -> forceUseBitmap )
800
806
{
801
- useFastScan = false ;
807
+ scanType = RumRegularScan ;
802
808
break ;
803
809
}
804
810
}
805
811
}
806
812
807
813
ItemPointerSetInvalid (& so -> key .iptr );
808
814
809
- if (useFastScan )
815
+ if (scanType == RumFastScan )
810
816
{
811
817
/*
812
818
* We are going to use fast scan. Do some preliminaries. Start scan of
@@ -819,13 +825,13 @@ startScan(IndexScanDesc scan)
819
825
for (i = 0 ; i < so -> totalentries ; i ++ )
820
826
{
821
827
if (!so -> sortedEntries [i ]-> isFinished )
822
- entryGetItem (& so -> rumstate , so -> sortedEntries [i ]);
828
+ entryGetItem (& so -> rumstate , so -> sortedEntries [i ], NULL );
823
829
}
824
830
qsort_arg (so -> sortedEntries , so -> totalentries , sizeof (RumScanEntry ),
825
831
scan_entry_cmp , rumstate );
826
832
}
827
833
828
- so -> useFastScan = useFastScan ;
834
+ so -> scanType = scanType ;
829
835
}
830
836
831
837
/*
@@ -952,7 +958,7 @@ entryGetNextItem(RumState * rumstate, RumScanEntry entry)
952
958
}
953
959
}
954
960
955
- static void
961
+ static bool
956
962
entryGetNextItemList (RumState * rumstate , RumScanEntry entry )
957
963
{
958
964
Page page ;
@@ -998,7 +1004,7 @@ entryGetNextItemList(RumState * rumstate, RumScanEntry entry)
998
1004
ItemPointerSetInvalid (& entry -> curRumKey .iptr );
999
1005
entry -> isFinished = TRUE;
1000
1006
LockBuffer (entry -> stack -> buffer , RUM_UNLOCK );
1001
- return ;
1007
+ return false ;
1002
1008
}
1003
1009
1004
1010
page = BufferGetPage (entry -> stack -> buffer );
@@ -1014,7 +1020,7 @@ entryGetNextItemList(RumState * rumstate, RumScanEntry entry)
1014
1020
ItemPointerSetInvalid (& entry -> curRumKey .iptr );
1015
1021
entry -> isFinished = TRUE;
1016
1022
LockBuffer (entry -> stack -> buffer , RUM_UNLOCK );
1017
- return ;
1023
+ return false ;
1018
1024
}
1019
1025
1020
1026
/*
@@ -1102,6 +1108,8 @@ entryGetNextItemList(RumState * rumstate, RumScanEntry entry)
1102
1108
1103
1109
if (needUnlock )
1104
1110
LockBuffer (entry -> stack -> buffer , RUM_UNLOCK );
1111
+
1112
+ return true;
1105
1113
}
1106
1114
1107
1115
#define rum_rand () (((double) random()) / ((double) MAX_RANDOM_VALUE))
@@ -1121,10 +1129,13 @@ entryGetNextItemList(RumState * rumstate, RumScanEntry entry)
1121
1129
* current implementation this is guaranteed by the behavior of tidbitmaps.
1122
1130
*/
1123
1131
static void
1124
- entryGetItem (RumState * rumstate , RumScanEntry entry )
1132
+ entryGetItem (RumState * rumstate , RumScanEntry entry , bool * nextEntryList )
1125
1133
{
1126
1134
Assert (!entry -> isFinished );
1127
1135
1136
+ if (nextEntryList )
1137
+ * nextEntryList = false;
1138
+
1128
1139
if (entry -> matchBitmap )
1129
1140
{
1130
1141
Assert (ScanDirectionIsForward (entry -> scanDirection ));
@@ -1186,7 +1197,8 @@ entryGetItem(RumState * rumstate, RumScanEntry entry)
1186
1197
else if (entry -> stack )
1187
1198
{
1188
1199
entry -> offset ++ ;
1189
- entryGetNextItemList (rumstate , entry );
1200
+ if (entryGetNextItemList (rumstate , entry ) && nextEntryList )
1201
+ * nextEntryList = true;
1190
1202
}
1191
1203
else
1192
1204
{
@@ -1205,7 +1217,8 @@ entryGetItem(RumState * rumstate, RumScanEntry entry)
1205
1217
if (entry -> stack && entry -> isFinished )
1206
1218
{
1207
1219
entry -> isFinished = FALSE;
1208
- entryGetNextItemList (rumstate , entry );
1220
+ if (entryGetNextItemList (rumstate , entry ) && nextEntryList )
1221
+ * nextEntryList = true;
1209
1222
}
1210
1223
}
1211
1224
}
@@ -1490,7 +1503,7 @@ scanGetItemRegular(IndexScanDesc scan, RumKey *advancePast,
1490
1503
compareCurRumKeyScanDirection (rumstate , entry ,
1491
1504
& myAdvancePast ) <= 0 ))
1492
1505
{
1493
- entryGetItem (rumstate , entry );
1506
+ entryGetItem (rumstate , entry , NULL );
1494
1507
1495
1508
if (!ItemPointerIsValid (& myAdvancePast .iptr ))
1496
1509
break ;
@@ -1915,7 +1928,7 @@ entryShift(int i, RumScanOpaque so, bool find)
1915
1928
entryFindItem (rumstate , so -> sortedEntries [minIndex ],
1916
1929
& so -> sortedEntries [i - 1 ]-> curRumKey );
1917
1930
else if (!so -> sortedEntries [minIndex ]-> isFinished )
1918
- entryGetItem (rumstate , so -> sortedEntries [minIndex ]);
1931
+ entryGetItem (rumstate , so -> sortedEntries [minIndex ], NULL );
1919
1932
1920
1933
/* Restore order of so->sortedEntries */
1921
1934
while (minIndex > 0 &&
@@ -2053,6 +2066,62 @@ scanGetItemFast(IndexScanDesc scan, RumKey *advancePast,
2053
2066
return false;
2054
2067
}
2055
2068
2069
+ /*
2070
+ * Get next item pointer using full-index scan.
2071
+ *
2072
+ * First key is used to full scan, other keys are only used for ranking.
2073
+ */
2074
+ static bool
2075
+ scanGetItemFull (IndexScanDesc scan , RumKey * advancePast ,
2076
+ RumKey * item , bool * recheck )
2077
+ {
2078
+ RumScanOpaque so = (RumScanOpaque ) scan -> opaque ;
2079
+ RumScanEntry entry ;
2080
+ bool nextEntryList ;
2081
+ uint32 i ;
2082
+
2083
+ Assert (so -> totalentries > 0 );
2084
+ Assert (so -> entries [0 ]-> scanWithAddInfo );
2085
+
2086
+ /*
2087
+ * This is first entry of the first key, which is used for full-index
2088
+ * scan.
2089
+ */
2090
+ entry = so -> entries [0 ];
2091
+
2092
+ entryGetItem (& so -> rumstate , entry , & nextEntryList );
2093
+ if (entry -> isFinished == TRUE)
2094
+ return false;
2095
+
2096
+ /* Move related order by entries */
2097
+ if (nextEntryList )
2098
+ for (i = 1 ; i < so -> totalentries ; i ++ )
2099
+ {
2100
+ RumScanEntry orderEntry = so -> entries [i ];
2101
+ if (orderEntry -> nlist > 0 )
2102
+ {
2103
+ orderEntry -> isFinished = FALSE;
2104
+ orderEntry -> offset = InvalidOffsetNumber ;
2105
+ RumItemSetMin (& orderEntry -> curRumKey );
2106
+ }
2107
+ }
2108
+
2109
+ for (i = 1 ; i < so -> totalentries ; i ++ )
2110
+ {
2111
+ RumScanEntry orderEntry = so -> entries [i ];
2112
+
2113
+ while (orderEntry -> isFinished == FALSE &&
2114
+ (!ItemPointerIsValid (& orderEntry -> curRumKey .iptr ) ||
2115
+ compareCurRumKeyScanDirection (& so -> rumstate , orderEntry ,
2116
+ & entry -> curRumKey ) < 0 ))
2117
+ entryGetItem (& so -> rumstate , orderEntry , NULL );
2118
+ }
2119
+
2120
+ * item = entry -> curRumKey ;
2121
+ * recheck = false;
2122
+ return true;
2123
+ }
2124
+
2056
2125
/*
2057
2126
* Get next item whether using regular or fast scan.
2058
2127
*/
@@ -2062,8 +2131,10 @@ scanGetItem(IndexScanDesc scan, RumKey *advancePast,
2062
2131
{
2063
2132
RumScanOpaque so = (RumScanOpaque ) scan -> opaque ;
2064
2133
2065
- if (so -> useFastScan )
2134
+ if (so -> scanType == RumFastScan )
2066
2135
return scanGetItemFast (scan , advancePast , item , recheck );
2136
+ else if (so -> scanType == RumFullScan )
2137
+ return scanGetItemFull (scan , advancePast , item , recheck );
2067
2138
else
2068
2139
return scanGetItemRegular (scan , advancePast , item , recheck );
2069
2140
}
0 commit comments