implements query-iterator object
This commit is contained in:
parent
afab7b9fa7
commit
760acd2767
|
@ -9,3 +9,4 @@ leveldbtool
|
|||
*.css
|
||||
build
|
||||
|
||||
*.exe
|
||||
|
|
|
@ -76,6 +76,11 @@ type
|
|||
|
||||
LevelDbException* = object of CatchableError
|
||||
|
||||
IterNext* = proc(): (string, string) {.gcsafe, closure.}
|
||||
LevelDbQueryIter* = ref object
|
||||
finished*: bool
|
||||
next*: IterNext
|
||||
|
||||
const
|
||||
version* = block:
|
||||
const configFile = "leveldbstatic.nimble"
|
||||
|
@ -406,6 +411,65 @@ iterator iterRange*(self: LevelDb, start, limit: string): (string, string) =
|
|||
break
|
||||
yield (key, value)
|
||||
|
||||
|
||||
proc getIterKey(iterPtr: ptr leveldb_iterator_t): string =
|
||||
var len: csize_t
|
||||
var str: cstring
|
||||
|
||||
str = leveldb_iter_key(iterPtr, addr len)
|
||||
return newString(str, len)
|
||||
|
||||
proc getIterValue(iterPtr: ptr leveldb_iterator_t): string =
|
||||
var len: csize_t
|
||||
var str: cstring
|
||||
|
||||
str = leveldb_iter_value(iterPtr, addr len)
|
||||
return newString(str, len)
|
||||
|
||||
proc queryIter*(self: LevelDb, prefix: string = "", keysOnly: bool = false): LevelDbQueryIter =
|
||||
var iterPtr = leveldb_create_iterator(self.db, self.readOptions)
|
||||
|
||||
if prefix.len > 0:
|
||||
leveldb_iter_seek(iterPtr, prefix, prefix.len.csize_t)
|
||||
else:
|
||||
leveldb_iter_seek_to_first(iterPtr)
|
||||
|
||||
var iter = LevelDbQueryIter()
|
||||
let emptyResponse = ("", "")
|
||||
|
||||
proc getNext(): (string, string) {.gcsafe, closure.} =
|
||||
if iter.finished:
|
||||
return emptyResponse
|
||||
|
||||
if leveldb_iter_valid(iterPtr) == levelDbFalse:
|
||||
iter.finished = true
|
||||
leveldb_iter_destroy(iterPtr)
|
||||
return emptyResponse
|
||||
|
||||
let
|
||||
keyStr = getIterKey(iterPtr)
|
||||
valueStr = if keysOnly: "" else: getIterValue(iterPtr)
|
||||
|
||||
var err: cstring = nil
|
||||
leveldb_iter_get_error(iterPtr, addr err)
|
||||
checkError(err)
|
||||
|
||||
leveldb_iter_next(iterPtr)
|
||||
|
||||
if prefix.len > 0:
|
||||
if keyStr.startsWith(prefix):
|
||||
return (keyStr, valueStr)
|
||||
else:
|
||||
iter.finished = true
|
||||
leveldb_iter_destroy(iterPtr)
|
||||
return emptyResponse
|
||||
else:
|
||||
return (keyStr, valueStr)
|
||||
|
||||
iter.finished = false
|
||||
iter.next = getNext
|
||||
return iter
|
||||
|
||||
proc removeDb*(name: string) =
|
||||
## Remove the database `name`.
|
||||
var err: cstring = nil
|
||||
|
|
|
@ -205,6 +205,77 @@ suite "leveldb":
|
|||
nc.put("a", "1")
|
||||
check(toSeq(nc.iter()) == @[("a", "1")])
|
||||
|
||||
suite "leveldb queryIter":
|
||||
|
||||
setup:
|
||||
let env = leveldb_create_default_env()
|
||||
let dbName = $(leveldb_env_get_test_directory(env))
|
||||
let db = leveldb.open(dbName)
|
||||
let
|
||||
k1 = "k1"
|
||||
k2 = "k2"
|
||||
k3 = "l3"
|
||||
v1 = "v1"
|
||||
v2 = "v2"
|
||||
v3 = "v3"
|
||||
empty = ("", "")
|
||||
|
||||
db.put(k1, v1)
|
||||
db.put(k2, v2)
|
||||
db.put(k3, v3)
|
||||
|
||||
teardown:
|
||||
db.close()
|
||||
removeDb(dbName)
|
||||
|
||||
test "iterates all keys and values":
|
||||
let iter = db.queryIter()
|
||||
check:
|
||||
not iter.finished
|
||||
iter.next() == (k1, v1)
|
||||
not iter.finished
|
||||
iter.next() == (k2, v2)
|
||||
not iter.finished
|
||||
iter.next() == (k3, v3)
|
||||
not iter.finished
|
||||
iter.next() == empty
|
||||
iter.finished
|
||||
|
||||
test "iterates only keys":
|
||||
let iter = db.queryIter(keysOnly = true)
|
||||
check:
|
||||
not iter.finished
|
||||
iter.next() == (k1, "")
|
||||
not iter.finished
|
||||
iter.next() == (k2, "")
|
||||
not iter.finished
|
||||
iter.next() == (k3, "")
|
||||
not iter.finished
|
||||
iter.next() == empty
|
||||
iter.finished
|
||||
|
||||
test "iterates only 'k', both keys and values":
|
||||
let iter = db.queryIter(prefix = "k")
|
||||
check:
|
||||
not iter.finished
|
||||
iter.next() == (k1, v1)
|
||||
not iter.finished
|
||||
iter.next() == (k2, v2)
|
||||
not iter.finished
|
||||
iter.next() == empty
|
||||
iter.finished
|
||||
|
||||
test "iterates only 'k', only keys":
|
||||
let iter = db.queryIter(prefix = "k", keysOnly = true)
|
||||
check:
|
||||
not iter.finished
|
||||
iter.next() == (k1, "")
|
||||
not iter.finished
|
||||
iter.next() == (k2, "")
|
||||
not iter.finished
|
||||
iter.next() == empty
|
||||
iter.finished
|
||||
|
||||
suite "package":
|
||||
|
||||
setup:
|
||||
|
|
Loading…
Reference in New Issue