@@ -68,6 +68,8 @@ static class State {
6868
6969 private final MDBVal valueData = MDBVal .malloc ();
7070
71+ private ByteBuffer valueBuf ;
72+
7173 private final ByteBuffer minKeyBuf = MemoryUtil .memAlloc ((Long .BYTES + 1 ) * 4 );
7274
7375 private final ByteBuffer minValueBuf = MemoryUtil .memAlloc ((Long .BYTES + 1 ) * 4 );
@@ -203,12 +205,19 @@ public long[] next() {
203205
204206 boolean isDupValue = false ;
205207 if (fetchNext ) {
206- lastResult = mdb_cursor_get (state .cursor , state .keyData , state .valueData , MDB_NEXT_DUP );
207- if (lastResult != MDB_SUCCESS ) {
208- // no more duplicates, move to next key
209- lastResult = mdb_cursor_get (state .cursor , state .keyData , state .valueData , MDB_NEXT_NODUP );
208+ if (!state .valueBuf .hasRemaining ()) {
209+ lastResult = mdb_cursor_get (state .cursor , state .keyData , state .valueData , MDB_NEXT_DUP );
210+ if (lastResult != MDB_SUCCESS ) {
211+ // no more duplicates, move to next key
212+ lastResult = mdb_cursor_get (state .cursor , state .keyData , state .valueData , MDB_NEXT_NODUP );
213+ } else {
214+ isDupValue = true ;
215+ }
216+ if (lastResult == MDB_SUCCESS ) {
217+ state .valueBuf = state .valueData .mv_data ();
218+ }
210219 } else {
211- isDupValue = true ;
220+ lastResult = MDB_SUCCESS ;
212221 }
213222 fetchNext = false ;
214223 } else {
@@ -231,31 +240,56 @@ public long[] next() {
231240 // set cursor to first item
232241 lastResult = mdb_cursor_get (state .cursor , state .keyData , state .valueData , MDB_FIRST );
233242 }
243+ if (lastResult == MDB_SUCCESS ) {
244+ state .valueBuf = state .valueData .mv_data ();
245+ }
234246 }
235247
236248 while (lastResult == MDB_SUCCESS ) {
237- // if (maxKey != null && TripleStore.COMPARATOR.compare(keyData.mv_data(), maxKey.mv_data()) > 0) {
238- int keyDiff ;
239- if (state .indexScore > 0 &&
240- (keyDiff = isDupValue ? 0 : mdb_cmp (state .txn , state .dbi , state .keyData , state .maxKey )) >= 0
241- && (keyDiff > 0 || mdb_dcmp (state .txn , state .dbi , state .valueData , state .maxValue ) > 0 )) {
242- lastResult = MDB_NOTFOUND ;
243- } else if (notMatches (isDupValue )) {
244- // value doesn't match search key/mask, fetch next value
249+ if (state .indexScore > 0 ) {
250+ int keyDiff = isDupValue ? 0 : mdb_cmp (state .txn , state .dbi , state .keyData , state .maxKey );
251+ if (keyDiff > 0 ) {
252+ break ;
253+ }
254+ int valueDiff = TripleStore .compareRegion (state .valueBuf , state .valueBuf .position (),
255+ state .maxValueBuf , 0 ,
256+ Math .min (state .valueBuf .remaining (), state .maxValueBuf .remaining ()));
257+ if (valueDiff > 0 ) {
258+ break ;
259+ }
260+ }
261+
262+ // value doesn't match search key/mask, fetch next value
263+ if (!state .valueBuf .hasRemaining ()) {
245264 lastResult = mdb_cursor_get (state .cursor , state .keyData , state .valueData , MDB_NEXT_DUP );
246265 if (lastResult != MDB_SUCCESS ) {
247266 // no more duplicates, move to next key
248267 lastResult = mdb_cursor_get (state .cursor , state .keyData , state .valueData , MDB_NEXT_NODUP );
249268 isDupValue = false ;
250269 }
251- } else {
252- // Matching value found
253- state .index .entryToQuad (state .keyData .mv_data (), state .valueData .mv_data (), state .patternQuad ,
254- state .quad );
255- // fetch next value
256- fetchNext = true ;
257- return state .quad ;
270+ if (lastResult == MDB_SUCCESS ) {
271+ state .valueBuf = state .valueData .mv_data ();
272+ } else {
273+ break ;
274+ }
258275 }
276+
277+ int valueBufPos = state .valueBuf .position ();
278+ if (notMatches (isDupValue , isDupValue ? null : state .keyData .mv_data (), state .valueBuf )) {
279+ state .valueBuf .position (valueBufPos );
280+ int skip = 4 - state .index .getIndexSplitPosition ();
281+ for (int i = 0 ; i < skip ; i ++) {
282+ TripleStore .skipVarint (state .valueBuf );
283+ }
284+ continue ;
285+ }
286+ state .valueBuf .position (valueBufPos );
287+
288+ // Matching value found
289+ state .index .entryToQuad (state .keyData .mv_data (), state .valueBuf , state .patternQuad , state .quad );
290+ // fetch next value
291+ fetchNext = true ;
292+ return state .quad ;
259293 }
260294 closeInternal (false );
261295 return null ;
@@ -264,18 +298,14 @@ public long[] next() {
264298 }
265299 }
266300
267- private boolean notMatches (boolean testValueOnly ) {
301+ private boolean notMatches (boolean testValueOnly , ByteBuffer keyBuf , ByteBuffer valueBuf ) {
268302 if (state .matcher != null ) {
269- if (testValueOnly ) {
270- // already positioned on correct key, no need to match key again
271- return !state .matcher .matchesValue (state .valueData .mv_data ());
272- }
273- return !state .matcher .matches (state .keyData .mv_data (), state .valueData .mv_data ());
303+ return testValueOnly ? !state .matcher .matchesValue (valueBuf ) : !state .matcher .matches (keyBuf , valueBuf );
274304 } else if (state .matchValues ) {
275305 // lazy init of group matcher
276306 state .matcher = state .index .createMatcher (state .patternQuad [0 ], state .patternQuad [1 ], state .patternQuad [2 ],
277307 state .patternQuad [3 ]);
278- return !state .matcher .matches ( state . keyData . mv_data (), state .valueData . mv_data () );
308+ return testValueOnly ? !state .matcher .matchesValue ( valueBuf ) : ! state .matcher . matches ( keyBuf , valueBuf );
279309 } else {
280310 return false ;
281311 }
0 commit comments