Skip to content

Commit 51671c5

Browse files
committed
Add range support for bidirectional open (#7)
1 parent 98d46bf commit 51671c5

File tree

4 files changed

+90
-1
lines changed

4 files changed

+90
-1
lines changed

src/main/java/org/lmdbjava/KeyRange.java

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,6 +198,30 @@ public static <T> KeyRange<T> lessThanBackward(final T stop) {
198198
return new KeyRange<>(KeyRangeType.BACKWARD_LESS_THAN, null, stop);
199199
}
200200

201+
/**
202+
* Create a {@link KeyRangeType#FORWARD_OPEN} range.
203+
*
204+
* @param <T> buffer type
205+
* @param start start key (required)
206+
* @param stop stop key (required)
207+
* @return a key range (never null)
208+
*/
209+
public static <T> KeyRange<T> open(final T start, final T stop) {
210+
return new KeyRange<>(KeyRangeType.FORWARD_OPEN, start, stop);
211+
}
212+
213+
/**
214+
* Create a {@link KeyRangeType#BACKWARD_OPEN} range.
215+
*
216+
* @param <T> buffer type
217+
* @param start start key (required)
218+
* @param stop stop key (required)
219+
* @return a key range (never null)
220+
*/
221+
public static <T> KeyRange<T> openBackward(final T start, final T stop) {
222+
return new KeyRange<>(KeyRangeType.BACKWARD_OPEN, start, stop);
223+
}
224+
201225
/**
202226
* Start key.
203227
*

src/main/java/org/lmdbjava/KeyRangeType.java

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -121,6 +121,17 @@ public enum KeyRangeType {
121121
* be 2 and 4. With a passed key of 8, the returned keys would be 2, 4 and 6.
122122
*/
123123
FORWARD_LESS_THAN(true, false, true),
124+
/**
125+
* Iterate forward between the passed keys but not equal to either of them.
126+
*
127+
* <p>
128+
* The "start" and "stop" values are both required.
129+
*
130+
* <p>
131+
* In our example and with a passed search range of 3 - 7, the returned keys
132+
* would be 4 and 6. With a range of 2 - 8, the key would be 4 and 6.
133+
*/
134+
FORWARD_OPEN(true, true, true),
124135
/**
125136
* Start on the last key and iterate backward until no keys remain.
126137
*
@@ -192,7 +203,19 @@ public enum KeyRangeType {
192203
* In our example and with a passed search key of 5, the returned keys would
193204
* be 8 and 6. With a passed key of 2, the returned keys would be 8, 6 and 4
194205
*/
195-
BACKWARD_LESS_THAN(false, false, true);
206+
BACKWARD_LESS_THAN(false, false, true),
207+
/**
208+
* Iterate backward between the passed keys, but do not return the passed
209+
* keys.
210+
*
211+
* <p>
212+
* The "start" and "stop" values are both required.
213+
*
214+
* <p>
215+
* In our example and with a passed search range of 7 - 2, the returned keys
216+
* would be 6 and 4. With a range of 8 - 1, the keys would be 6, 4 and 2.
217+
*/
218+
BACKWARD_OPEN(false, true, true);
196219

197220
private final boolean directionForward;
198221
private final boolean startKeyRequired;
@@ -256,6 +279,8 @@ CursorOp initialOp() {
256279
return GET_START_KEY;
257280
case FORWARD_LESS_THAN:
258281
return FIRST;
282+
case FORWARD_OPEN:
283+
return GET_START_KEY;
259284
case BACKWARD_ALL:
260285
return LAST;
261286
case BACKWARD_AT_LEAST:
@@ -268,6 +293,8 @@ CursorOp initialOp() {
268293
return GET_START_KEY;
269294
case BACKWARD_LESS_THAN:
270295
return LAST;
296+
case BACKWARD_OPEN:
297+
return GET_START_KEY;
271298
default:
272299
throw new IllegalStateException("Invalid type");
273300
}
@@ -304,6 +331,11 @@ <T, C extends Comparator<T>> IteratorOp iteratorOp(final T start, final T stop,
304331
return c.compare(buffer, start) == 0 ? CALL_NEXT_OP : RELEASE;
305332
case FORWARD_LESS_THAN:
306333
return c.compare(buffer, stop) >= 0 ? TERMINATE : RELEASE;
334+
case FORWARD_OPEN:
335+
if (c.compare(buffer, start) == 0) {
336+
return CALL_NEXT_OP;
337+
}
338+
return c.compare(buffer, stop) >= 0 ? TERMINATE : RELEASE;
307339
case BACKWARD_ALL:
308340
return RELEASE;
309341
case BACKWARD_AT_LEAST:
@@ -319,6 +351,11 @@ <T, C extends Comparator<T>> IteratorOp iteratorOp(final T start, final T stop,
319351
return c.compare(buffer, start) >= 0 ? CALL_NEXT_OP : RELEASE;
320352
case BACKWARD_LESS_THAN:
321353
return c.compare(buffer, stop) > 0 ? RELEASE : TERMINATE;
354+
case BACKWARD_OPEN:
355+
if (c.compare(buffer, start) >= 0) {
356+
return CALL_NEXT_OP; // rewind
357+
}
358+
return c.compare(buffer, stop) > 0 ? RELEASE : TERMINATE;
322359
default:
323360
throw new IllegalStateException("Invalid type");
324361
}

src/test/java/org/lmdbjava/CursorIteratorTest.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,8 @@
5454
import static org.lmdbjava.KeyRange.greaterThanBackward;
5555
import static org.lmdbjava.KeyRange.lessThan;
5656
import static org.lmdbjava.KeyRange.lessThanBackward;
57+
import static org.lmdbjava.KeyRange.open;
58+
import static org.lmdbjava.KeyRange.openBackward;
5759
import static org.lmdbjava.PutFlags.MDB_NOOVERWRITE;
5860
import static org.lmdbjava.TestUtils.DB_1;
5961
import static org.lmdbjava.TestUtils.bb;
@@ -238,6 +240,18 @@ public void nextThrowsNoSuchElementExceptionIfNoMoreElements() {
238240
}
239241
}
240242

243+
@Test
244+
public void openBackwardTest() {
245+
verify(openBackward(bb(7), bb(2)), 6, 4);
246+
verify(openBackward(bb(8), bb(1)), 6, 4, 2);
247+
}
248+
249+
@Test
250+
public void openTest() {
251+
verify(open(bb(3), bb(7)), 4, 6);
252+
verify(open(bb(2), bb(8)), 4, 6);
253+
}
254+
241255
@Test(expected = UnsupportedOperationException.class)
242256
public void removeUnsupported() {
243257
try (Txn<ByteBuffer> txn = env.txnRead();

src/test/java/org/lmdbjava/KeyRangeTest.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@
3939
import static org.lmdbjava.KeyRange.greaterThanBackward;
4040
import static org.lmdbjava.KeyRange.lessThan;
4141
import static org.lmdbjava.KeyRange.lessThanBackward;
42+
import static org.lmdbjava.KeyRange.open;
43+
import static org.lmdbjava.KeyRange.openBackward;
4244
import org.lmdbjava.KeyRangeType.CursorOp;
4345
import static org.lmdbjava.KeyRangeType.CursorOp.FIRST;
4446
import org.lmdbjava.KeyRangeType.IteratorOp;
@@ -147,6 +149,18 @@ public void lessThanTest() {
147149
verify(lessThan(8), 2, 4, 6);
148150
}
149151

152+
@Test
153+
public void openBackwardTest() {
154+
verify(openBackward(7, 2), 6, 4);
155+
verify(openBackward(8, 1), 6, 4, 2);
156+
}
157+
158+
@Test
159+
public void openTest() {
160+
verify(open(3, 7), 4, 6);
161+
verify(open(2, 8), 4, 6);
162+
}
163+
150164
private void verify(final KeyRange<Integer> range, final int... expected) {
151165
final List<Integer> results = new ArrayList<>();
152166

0 commit comments

Comments
 (0)