Skip to content

Commit 98d46bf

Browse files
committed
Add range support for bidirectional lessThan (#7)
1 parent 8b1e5fa commit 98d46bf

File tree

4 files changed

+83
-1
lines changed

4 files changed

+83
-1
lines changed

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

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -176,6 +176,28 @@ public static <T> KeyRange<T> greaterThanBackward(final T start) {
176176
return new KeyRange<>(KeyRangeType.BACKWARD_GREATER_THAN, start, null);
177177
}
178178

179+
/**
180+
* Create a {@link KeyRangeType#FORWARD_LESS_THAN} range.
181+
*
182+
* @param <T> buffer type
183+
* @param stop stop key (required)
184+
* @return a key range (never null)
185+
*/
186+
public static <T> KeyRange<T> lessThan(final T stop) {
187+
return new KeyRange<>(KeyRangeType.FORWARD_LESS_THAN, null, stop);
188+
}
189+
190+
/**
191+
* Create a {@link KeyRangeType#BACKWARD_LESS_THAN} range.
192+
*
193+
* @param <T> buffer type
194+
* @param stop stop key (required)
195+
* @return a key range (never null)
196+
*/
197+
public static <T> KeyRange<T> lessThanBackward(final T stop) {
198+
return new KeyRange<>(KeyRangeType.BACKWARD_LESS_THAN, null, stop);
199+
}
200+
179201
/**
180202
* Start key.
181203
*

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

Lines changed: 33 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,18 @@ public enum KeyRangeType {
109109
* be 6 and 8. With a passed key of 3, the returned keys would be 4, 6 and 8.
110110
*/
111111
FORWARD_GREATER_THAN(true, true, false),
112+
/**
113+
* Start on the first key and iterate forward until a key the passed key has
114+
* been reached (but do not return that key).
115+
*
116+
* <p>
117+
* The "stop" value is required. The "start" value is ignored.
118+
*
119+
* <p>
120+
* In our example and with a passed search key of 5, the returned keys would
121+
* be 2 and 4. With a passed key of 8, the returned keys would be 2, 4 and 6.
122+
*/
123+
FORWARD_LESS_THAN(true, false, true),
112124
/**
113125
* Start on the last key and iterate backward until no keys remain.
114126
*
@@ -168,7 +180,19 @@ public enum KeyRangeType {
168180
* In our example and with a passed search key of 6, the returned keys would
169181
* be 4 and 2. With a passed key of 7, the returned keys would be 6, 4 and 2.
170182
*/
171-
BACKWARD_GREATER_THAN(false, true, false);
183+
BACKWARD_GREATER_THAN(false, true, false),
184+
/**
185+
* Start on the last key and iterate backward until the last key greater than
186+
* the passed "stop" key is reached. Do not return the "stop" key.
187+
*
188+
* <p>
189+
* The "stop" value is required. The "start" value is ignored.
190+
*
191+
* <p>
192+
* In our example and with a passed search key of 5, the returned keys would
193+
* be 8 and 6. With a passed key of 2, the returned keys would be 8, 6 and 4
194+
*/
195+
BACKWARD_LESS_THAN(false, false, true);
172196

173197
private final boolean directionForward;
174198
private final boolean startKeyRequired;
@@ -230,6 +254,8 @@ CursorOp initialOp() {
230254
return GET_START_KEY;
231255
case FORWARD_GREATER_THAN:
232256
return GET_START_KEY;
257+
case FORWARD_LESS_THAN:
258+
return FIRST;
233259
case BACKWARD_ALL:
234260
return LAST;
235261
case BACKWARD_AT_LEAST:
@@ -240,6 +266,8 @@ CursorOp initialOp() {
240266
return GET_START_KEY;
241267
case BACKWARD_GREATER_THAN:
242268
return GET_START_KEY;
269+
case BACKWARD_LESS_THAN:
270+
return LAST;
243271
default:
244272
throw new IllegalStateException("Invalid type");
245273
}
@@ -274,6 +302,8 @@ <T, C extends Comparator<T>> IteratorOp iteratorOp(final T start, final T stop,
274302
return c.compare(buffer, stop) > 0 ? TERMINATE : RELEASE;
275303
case FORWARD_GREATER_THAN:
276304
return c.compare(buffer, start) == 0 ? CALL_NEXT_OP : RELEASE;
305+
case FORWARD_LESS_THAN:
306+
return c.compare(buffer, stop) >= 0 ? TERMINATE : RELEASE;
277307
case BACKWARD_ALL:
278308
return RELEASE;
279309
case BACKWARD_AT_LEAST:
@@ -287,6 +317,8 @@ <T, C extends Comparator<T>> IteratorOp iteratorOp(final T start, final T stop,
287317
return c.compare(buffer, stop) >= 0 ? RELEASE : TERMINATE;
288318
case BACKWARD_GREATER_THAN:
289319
return c.compare(buffer, start) >= 0 ? CALL_NEXT_OP : RELEASE;
320+
case BACKWARD_LESS_THAN:
321+
return c.compare(buffer, stop) > 0 ? RELEASE : TERMINATE;
290322
default:
291323
throw new IllegalStateException("Invalid type");
292324
}

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

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@
5252
import static org.lmdbjava.KeyRange.closedBackward;
5353
import static org.lmdbjava.KeyRange.greaterThan;
5454
import static org.lmdbjava.KeyRange.greaterThanBackward;
55+
import static org.lmdbjava.KeyRange.lessThan;
56+
import static org.lmdbjava.KeyRange.lessThanBackward;
5557
import static org.lmdbjava.PutFlags.MDB_NOOVERWRITE;
5658
import static org.lmdbjava.TestUtils.DB_1;
5759
import static org.lmdbjava.TestUtils.bb;
@@ -211,6 +213,18 @@ public void iterate() {
211213
}
212214
}
213215

216+
@Test
217+
public void lessThanBackwardTest() {
218+
verify(lessThanBackward(bb(5)), 8, 6);
219+
verify(lessThanBackward(bb(2)), 8, 6, 4);
220+
}
221+
222+
@Test
223+
public void lessThanTest() {
224+
verify(lessThan(bb(5)), 2, 4);
225+
verify(lessThan(bb(8)), 2, 4, 6);
226+
}
227+
214228
@Test(expected = NoSuchElementException.class)
215229
public void nextThrowsNoSuchElementExceptionIfNoMoreElements() {
216230
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
@@ -37,6 +37,8 @@
3737
import static org.lmdbjava.KeyRange.closedBackward;
3838
import static org.lmdbjava.KeyRange.greaterThan;
3939
import static org.lmdbjava.KeyRange.greaterThanBackward;
40+
import static org.lmdbjava.KeyRange.lessThan;
41+
import static org.lmdbjava.KeyRange.lessThanBackward;
4042
import org.lmdbjava.KeyRangeType.CursorOp;
4143
import static org.lmdbjava.KeyRangeType.CursorOp.FIRST;
4244
import org.lmdbjava.KeyRangeType.IteratorOp;
@@ -133,6 +135,18 @@ public void greaterThanTest() {
133135
verify(greaterThan(3), 4, 6, 8);
134136
}
135137

138+
@Test
139+
public void lessThanBackwardTest() {
140+
verify(lessThanBackward(5), 8, 6);
141+
verify(lessThanBackward(2), 8, 6, 4);
142+
}
143+
144+
@Test
145+
public void lessThanTest() {
146+
verify(lessThan(5), 2, 4);
147+
verify(lessThan(8), 2, 4, 6);
148+
}
149+
136150
private void verify(final KeyRange<Integer> range, final int... expected) {
137151
final List<Integer> results = new ArrayList<>();
138152

0 commit comments

Comments
 (0)