Skip to content

Commit 3e27bff

Browse files
committed
fix limit, add more tests
1 parent 8b2729f commit 3e27bff

File tree

2 files changed

+77
-28
lines changed

2 files changed

+77
-28
lines changed

src/main/scala/com/scalableminds/fossildb/db/VersionedKeyValueStore.scala

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,7 @@ class VersionedKeyValueStore(underlying: RocksDBStore) {
128128
}
129129

130130
def getMultipleKeys(startAfterKey: Option[String], prefix: Option[String] = None, version: Option[Long] = None, limit: Option[Int]): (Seq[String], Seq[Array[Byte]], Seq[Long]) = {
131+
println(s"\ngetMultipleKeys! startAfterKey: $startAfterKey, prefix: $prefix, version: $version, limit: $limit")
131132
startAfterKey.foreach(requireValidKey)
132133
prefix.foreach{ p => requireValidKey(p)}
133134
val iterator: VersionFilterIterator = scanKeys(startAfterKey, prefix, version)
@@ -139,15 +140,23 @@ class VersionedKeyValueStore(underlying: RocksDBStore) {
139140
*/
140141
val firstItemOpt: Option[VersionedKeyValuePair[Array[Byte]]] = if (iterator.hasNext) {
141142
val firstItem = iterator.next()
143+
println(s"firstItem: ${firstItem.key}")
142144
if (startAfterKey.contains(firstItem.key)) {
143145
None
144146
} else {
145147
Some(firstItem)
146148
}
147149
} else None
148150

149-
val limitPadded = limit.map(_ - 1).getOrElse(Int.MaxValue)
151+
if (firstItemOpt.isDefined) {
152+
println(s"including first item $firstItemOpt")
153+
} else {
154+
println(s"dropping first item (it equals startAfterKey)")
155+
}
156+
157+
val limitPadded = limit.map(_ + 1).getOrElse(Int.MaxValue)
150158
val asVector = iterator.take(limitPadded).toVector
159+
println(s"asVector: ${asVector.map{_.key}}")
151160
val asSequenceAdvancedIfNeeded = firstItemOpt.map(_ +: asVector).getOrElse(asVector).take(limit.getOrElse(Int.MaxValue))
152161
val keys = asSequenceAdvancedIfNeeded.map(_.key)
153162
println(s"Returning keys ${keys.toList}")

src/test/scala/com/scalableminds/fossildb/FossilDBSuite.scala

Lines changed: 67 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class FossilDBSuite extends FlatSpec with BeforeAndAfterEach with TestHelpers wi
3030
private val testData3 = ByteString.copyFromUtf8("testData3")
3131

3232
private val aKey = "aKey"
33-
private val anotherKey = "anotherKey"
33+
private val aNotherKey = "aNotherKey"
3434
private val aThirdKey = "aThirdKey"
3535

3636
override def beforeEach: Unit = {
@@ -114,7 +114,7 @@ class FossilDBSuite extends FlatSpec with BeforeAndAfterEach with TestHelpers wi
114114
}
115115

116116
it should "fail after Put with other key" in {
117-
client.put(PutRequest(collectionA, anotherKey, Some(0), testData1))
117+
client.put(PutRequest(collectionA, aNotherKey, Some(0), testData1))
118118
val reply = client.get(GetRequest(collectionA, aKey))
119119
assert(!reply.success)
120120
}
@@ -136,24 +136,24 @@ class FossilDBSuite extends FlatSpec with BeforeAndAfterEach with TestHelpers wi
136136
"ListKeys" should "list all keys of a collection" in {
137137
client.put(PutRequest(collectionA, aKey, Some(0), testData1))
138138
client.put(PutRequest(collectionA, aKey, Some(1), testData2))
139-
client.put(PutRequest(collectionA, anotherKey, Some(4), testData2))
139+
client.put(PutRequest(collectionA, aNotherKey, Some(4), testData2))
140140
client.put(PutRequest(collectionB, aThirdKey, Some(1), testData1))
141141
val reply = client.listKeys(ListKeysRequest(collectionA))
142142
assert(reply.keys.contains(aKey))
143-
assert(reply.keys.contains(anotherKey))
143+
assert(reply.keys.contains(aNotherKey))
144144
assert(reply.keys.length == 2)
145145
}
146146

147147
it should "support pagination with startAfterKey" in {
148148
client.put(PutRequest(collectionA, aKey, Some(0), testData1))
149149
client.put(PutRequest(collectionA, aKey, Some(1), testData2))
150-
client.put(PutRequest(collectionA, anotherKey, Some(4), testData2))
150+
client.put(PutRequest(collectionA, aNotherKey, Some(4), testData2))
151151
client.put(PutRequest(collectionB, aThirdKey, Some(1), testData1))
152152
val reply = client.listKeys(ListKeysRequest(collectionA, Some(1)))
153153
assert(reply.keys.length == 1)
154154
assert(reply.keys.contains(aKey))
155155
val reply2 = client.listKeys(ListKeysRequest(collectionA, Some(1), Some(reply.keys.last)))
156-
assert(reply2.keys.contains(anotherKey))
156+
assert(reply2.keys.contains(aNotherKey))
157157
assert(reply2.keys.length == 1)
158158
}
159159

@@ -173,7 +173,7 @@ class FossilDBSuite extends FlatSpec with BeforeAndAfterEach with TestHelpers wi
173173
client.put(PutRequest(collectionA, aKey, Some(0), testData1))
174174
client.put(PutRequest(collectionA, aKey, Some(1), testData2))
175175
client.put(PutRequest(collectionA, aKey, Some(2), testData3))
176-
client.put(PutRequest(collectionA, anotherKey, Some(0), testData1))
176+
client.put(PutRequest(collectionA, aNotherKey, Some(0), testData1))
177177
val reply = client.getMultipleVersions(GetMultipleVersionsRequest(collectionA, aKey))
178178
assert(reply.versions(0) == 2)
179179
assert(reply.versions(1) == 1)
@@ -191,7 +191,7 @@ class FossilDBSuite extends FlatSpec with BeforeAndAfterEach with TestHelpers wi
191191
client.put(PutRequest(collectionA, aKey, Some(3), testData3))
192192
client.put(PutRequest(collectionA, aKey, Some(4), testData1))
193193
client.put(PutRequest(collectionA, aKey, Some(5), testData1))
194-
client.put(PutRequest(collectionA, anotherKey, Some(0), testData1))
194+
client.put(PutRequest(collectionA, aNotherKey, Some(0), testData1))
195195

196196
val reply = client.getMultipleVersions(GetMultipleVersionsRequest(collectionA, aKey, Some(4), Some(2)))
197197
assert(reply.versions(0) == 4)
@@ -202,45 +202,45 @@ class FossilDBSuite extends FlatSpec with BeforeAndAfterEach with TestHelpers wi
202202
assert(reply.values.length == 2)
203203
}
204204

205-
"GetMultipleKeys" should "return keys starting with initial one (no prefix)" in {
205+
"GetMultipleKeys" should "return all keys" in {
206206
client.put(PutRequest(collectionA, aKey, Some(0), testData1))
207-
client.put(PutRequest(collectionA, anotherKey, Some(0), testData2))
207+
client.put(PutRequest(collectionA, aNotherKey, Some(0), testData2))
208208
client.put(PutRequest(collectionA, aThirdKey, Some(0), testData3))
209-
val reply = client.getMultipleKeys(GetMultipleKeysRequest(collectionA, Some(aKey)))
210-
assert(reply.keys.length == 2)
211-
assert(reply.keys.contains(anotherKey))
209+
val reply = client.getMultipleKeys(GetMultipleKeysRequest(collectionA))
210+
assert(reply.keys.length == 3)
211+
assert(reply.keys.contains(aNotherKey))
212212
assert(reply.keys.contains(aThirdKey))
213-
assert(reply.values.length == 2)
213+
assert(reply.values.length == 3)
214214
assert(reply.values.contains(testData2))
215215
assert(reply.values.contains(testData3))
216-
assert(reply.actualVersions.length == 2)
216+
assert(reply.actualVersions.length == 3)
217217
assert(reply.actualVersions.contains(0))
218218
}
219219

220-
it should "return keys of matching version (sorted alphabetically)" in {
220+
it should "return keys of matching version" in {
221221
client.put(PutRequest(collectionA, aKey, Some(0), testData1))
222-
client.put(PutRequest(collectionA, anotherKey, Some(0), testData1))
222+
client.put(PutRequest(collectionA, aNotherKey, Some(0), testData1))
223223
client.put(PutRequest(collectionA, aThirdKey, Some(0), testData1))
224224
client.put(PutRequest(collectionA, aKey, Some(1), testData2))
225-
client.put(PutRequest(collectionA, anotherKey, Some(1), testData2))
225+
client.put(PutRequest(collectionA, aNotherKey, Some(1), testData2))
226226
client.put(PutRequest(collectionA, aThirdKey, Some(1), testData2))
227227
client.put(PutRequest(collectionA, aKey, Some(2), testData3))
228-
client.put(PutRequest(collectionA, anotherKey, Some(2), testData3))
228+
client.put(PutRequest(collectionA, aNotherKey, Some(2), testData3))
229229
client.put(PutRequest(collectionA, aThirdKey, Some(2), testData3))
230-
val reply = client.getMultipleKeys(GetMultipleKeysRequest(collectionA, Some(aKey), None, Some(1)))
231-
assert(reply.keys.length == 2)
230+
val reply = client.getMultipleKeys(GetMultipleKeysRequest(collectionA, None, None, Some(1)))
231+
assert(reply.keys.length == 3)
232232
assert(reply.values.contains(testData2))
233233
}
234234

235235
it should "return keys of matching version, matching prefix (sorted alphabetically)" in {
236236
client.put(PutRequest(collectionA, aKey, Some(0), testData1))
237-
client.put(PutRequest(collectionA, anotherKey, Some(0), testData1))
237+
client.put(PutRequest(collectionA, aNotherKey, Some(0), testData1))
238238
client.put(PutRequest(collectionA, aThirdKey, Some(0), testData1))
239239
client.put(PutRequest(collectionA, aKey, Some(1), testData2))
240-
client.put(PutRequest(collectionA, anotherKey, Some(1), testData2))
240+
client.put(PutRequest(collectionA, aNotherKey, Some(1), testData2))
241241
client.put(PutRequest(collectionA, aThirdKey, Some(1), testData2))
242242
client.put(PutRequest(collectionA, aKey, Some(2), testData3))
243-
client.put(PutRequest(collectionA, anotherKey, Some(2), testData3))
243+
client.put(PutRequest(collectionA, aNotherKey, Some(2), testData3))
244244
client.put(PutRequest(collectionA, aThirdKey, Some(2), testData3))
245245
val reply = client.getMultipleKeys(GetMultipleKeysRequest(collectionA, None, Some("aK"), Some(1)))
246246
assert(reply.keys.length == 1)
@@ -250,20 +250,60 @@ class FossilDBSuite extends FlatSpec with BeforeAndAfterEach with TestHelpers wi
250250

251251
it should "with limit return only the first n keys of matching version " in {
252252
client.put(PutRequest(collectionA, aKey, Some(0), testData1))
253-
client.put(PutRequest(collectionA, anotherKey, Some(0), testData1))
253+
client.put(PutRequest(collectionA, aNotherKey, Some(0), testData1))
254254
client.put(PutRequest(collectionA, aThirdKey, Some(0), testData1))
255255
client.put(PutRequest(collectionA, aKey, Some(1), testData2))
256-
client.put(PutRequest(collectionA, anotherKey, Some(1), testData2))
256+
client.put(PutRequest(collectionA, aNotherKey, Some(1), testData2))
257257
client.put(PutRequest(collectionA, aThirdKey, Some(1), testData2))
258258
client.put(PutRequest(collectionA, aKey, Some(2), testData3))
259-
client.put(PutRequest(collectionA, anotherKey, Some(2), testData3))
259+
client.put(PutRequest(collectionA, aNotherKey, Some(2), testData3))
260260
client.put(PutRequest(collectionA, aThirdKey, Some(2), testData3))
261261
val reply = client.getMultipleKeys(GetMultipleKeysRequest(collectionA, None, None, Some(1), Some(2)))
262262
assert(reply.keys.length == 2)
263263
assert(reply.values.contains(testData2))
264264
assert(reply.actualVersions.contains(1))
265265
}
266266

267+
it should "support pagination with startAfterKey" in {
268+
client.put(PutRequest(collectionA, aKey, Some(0), testData1))
269+
client.put(PutRequest(collectionA, aNotherKey, Some(0), testData1))
270+
client.put(PutRequest(collectionA, aThirdKey, Some(0), testData1))
271+
val reply = client.getMultipleKeys(GetMultipleKeysRequest(collectionA, Some(aKey), None, None, Some(2)))
272+
assert(reply.keys.length == 2)
273+
assert(reply.values.contains(testData1))
274+
assert(reply.actualVersions.contains(0))
275+
}
276+
277+
it should "support pagination with startAfterKey, with prefix and version" in {
278+
client.put(PutRequest(collectionA, aKey, Some(0), testData1))
279+
client.put(PutRequest(collectionA, aNotherKey, Some(0), testData1))
280+
client.put(PutRequest(collectionA, aThirdKey, Some(0), testData1))
281+
client.put(PutRequest(collectionA, aKey, Some(1), testData2))
282+
client.put(PutRequest(collectionA, aNotherKey, Some(1), testData2))
283+
client.put(PutRequest(collectionA, aThirdKey, Some(1), testData2))
284+
client.put(PutRequest(collectionA, aKey, Some(2), testData3))
285+
client.put(PutRequest(collectionA, aNotherKey, Some(2), testData3))
286+
client.put(PutRequest(collectionA, aThirdKey, Some(2), testData3))
287+
val reply = client.getMultipleKeys(GetMultipleKeysRequest(collectionA, Some(aKey), Some("a"), Some(1), Some(1)))
288+
assert(reply.keys.length == 1)
289+
assert(reply.values.contains(testData2))
290+
assert(reply.actualVersions.contains(1))
291+
}
292+
293+
it should "support pagination with startAfterKey, with prefix and version where no keys match the prefix" in {
294+
client.put(PutRequest(collectionA, aKey, Some(0), testData1))
295+
client.put(PutRequest(collectionA, aNotherKey, Some(0), testData1))
296+
client.put(PutRequest(collectionA, aThirdKey, Some(0), testData1))
297+
client.put(PutRequest(collectionA, aKey, Some(1), testData2))
298+
client.put(PutRequest(collectionA, aNotherKey, Some(1), testData2))
299+
client.put(PutRequest(collectionA, aThirdKey, Some(1), testData2))
300+
client.put(PutRequest(collectionA, aKey, Some(2), testData3))
301+
client.put(PutRequest(collectionA, aNotherKey, Some(2), testData3))
302+
client.put(PutRequest(collectionA, aThirdKey, Some(2), testData3))
303+
val reply = client.getMultipleKeys(GetMultipleKeysRequest(collectionA, Some(aKey), Some("BogusPrefix"), Some(1), Some(2)))
304+
assert(reply.keys.isEmpty)
305+
}
306+
267307
"Backup" should "create non-empty backup directory" in {
268308
client.put(PutRequest(collectionA, aKey, Some(0), testData1))
269309
client.backup(BackupRequest())

0 commit comments

Comments
 (0)