implements query-iterator object
This commit is contained in:
parent
afab7b9fa7
commit
760acd2767
|
@ -9,3 +9,4 @@ leveldbtool
|
||||||
*.css
|
*.css
|
||||||
build
|
build
|
||||||
|
|
||||||
|
*.exe
|
||||||
|
|
|
@ -76,6 +76,11 @@ type
|
||||||
|
|
||||||
LevelDbException* = object of CatchableError
|
LevelDbException* = object of CatchableError
|
||||||
|
|
||||||
|
IterNext* = proc(): (string, string) {.gcsafe, closure.}
|
||||||
|
LevelDbQueryIter* = ref object
|
||||||
|
finished*: bool
|
||||||
|
next*: IterNext
|
||||||
|
|
||||||
const
|
const
|
||||||
version* = block:
|
version* = block:
|
||||||
const configFile = "leveldbstatic.nimble"
|
const configFile = "leveldbstatic.nimble"
|
||||||
|
@ -406,6 +411,65 @@ iterator iterRange*(self: LevelDb, start, limit: string): (string, string) =
|
||||||
break
|
break
|
||||||
yield (key, value)
|
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) =
|
proc removeDb*(name: string) =
|
||||||
## Remove the database `name`.
|
## Remove the database `name`.
|
||||||
var err: cstring = nil
|
var err: cstring = nil
|
||||||
|
|
|
@ -205,6 +205,77 @@ suite "leveldb":
|
||||||
nc.put("a", "1")
|
nc.put("a", "1")
|
||||||
check(toSeq(nc.iter()) == @[("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":
|
suite "package":
|
||||||
|
|
||||||
setup:
|
setup:
|
||||||
|
|
Loading…
Reference in New Issue