mirror of
https://github.com/logos-storage/nim-datastore.git
synced 2026-01-07 16:13:07 +00:00
change to non-closure iterator
This commit is contained in:
parent
0336b93360
commit
92dcbf70ae
@ -20,17 +20,17 @@ type
|
|||||||
DbKey* = string | KeyId
|
DbKey* = string | KeyId
|
||||||
DbVal* = seq[byte] | DataBuffer
|
DbVal* = seq[byte] | DataBuffer
|
||||||
|
|
||||||
DbBatchEntry* = tuple[key: string, data: seq[byte]] | tuple[key: KeyId, data: DataBuffer]
|
DbBatchEntry*[K, V] = tuple[key: K, data: V]
|
||||||
|
|
||||||
DbQuery* = object
|
DbQuery*[K] = object
|
||||||
key*: KeyId # Key to be queried
|
key*: K # Key to be queried
|
||||||
value*: bool # Flag to indicate if data should be returned
|
value*: bool # Flag to indicate if data should be returned
|
||||||
limit*: int # Max items to return - not available in all backends
|
limit*: int # Max items to return - not available in all backends
|
||||||
offset*: int # Offset from which to start querying - not available in all backends
|
offset*: int # Offset from which to start querying - not available in all backends
|
||||||
sort*: SortOrder # Sort order - not available in all backends
|
sort*: SortOrder # Sort order - not available in all backends
|
||||||
|
|
||||||
DbQueryHandle*[T] = object
|
DbQueryHandle*[K, T] = object
|
||||||
query*: DbQuery
|
query*: DbQuery[K]
|
||||||
cancel*: bool
|
cancel*: bool
|
||||||
closed*: bool
|
closed*: bool
|
||||||
env*: T
|
env*: T
|
||||||
@ -39,6 +39,9 @@ type
|
|||||||
|
|
||||||
proc `$`*(id: KeyId): string = $(id.data)
|
proc `$`*(id: KeyId): string = $(id.data)
|
||||||
|
|
||||||
|
proc toKey*(tp: typedesc[KeyId], id: cstring): KeyId = KeyId.new(id)
|
||||||
|
proc toKey*(tp: typedesc[string], id: cstring): string = $(id)
|
||||||
|
|
||||||
proc new*(tp: typedesc[KeyId], id: cstring): KeyId =
|
proc new*(tp: typedesc[KeyId], id: cstring): KeyId =
|
||||||
## copy cstring including null terminator
|
## copy cstring including null terminator
|
||||||
KeyId(data: DataBuffer.new(id.toOpenArray(0, id.len()-1)))
|
KeyId(data: DataBuffer.new(id.toOpenArray(0, id.len()-1)))
|
||||||
|
|||||||
@ -39,7 +39,7 @@ proc has*[K,V](self: SQLiteBackend[K,V], key: DbKey): ?!bool =
|
|||||||
|
|
||||||
return success exists
|
return success exists
|
||||||
|
|
||||||
proc delete*[K,V](self: SQLiteBackend[K,V], key: DbKey): ?!void =
|
proc delete*[K,V](self: SQLiteBackend[K,V], key: K): ?!void =
|
||||||
return self.db.deleteStmt.exec((key))
|
return self.db.deleteStmt.exec((key))
|
||||||
|
|
||||||
proc delete*[K,V](self: SQLiteBackend[K,V], keys: openArray[DbKey]): ?!void =
|
proc delete*[K,V](self: SQLiteBackend[K,V], keys: openArray[DbKey]): ?!void =
|
||||||
@ -58,7 +58,7 @@ proc delete*[K,V](self: SQLiteBackend[K,V], keys: openArray[DbKey]): ?!void =
|
|||||||
|
|
||||||
return success()
|
return success()
|
||||||
|
|
||||||
proc get*[K,V](self: SQLiteBackend[K,V], key: KeyId): ?!seq[byte] =
|
proc get*[K,V](self: SQLiteBackend[K,V], key: K): ?!seq[byte] =
|
||||||
# see comment in ./filesystem_datastore re: finer control of memory
|
# see comment in ./filesystem_datastore re: finer control of memory
|
||||||
# allocation in `proc get`, could apply here as well if bytes were read
|
# allocation in `proc get`, could apply here as well if bytes were read
|
||||||
# incrementally with `sqlite3_blob_read`
|
# incrementally with `sqlite3_blob_read`
|
||||||
@ -78,7 +78,7 @@ proc get*[K,V](self: SQLiteBackend[K,V], key: KeyId): ?!seq[byte] =
|
|||||||
|
|
||||||
return success bytes
|
return success bytes
|
||||||
|
|
||||||
proc put*[K,V](self: SQLiteBackend[K,V], key: KeyId, data: DataBuffer): ?!void =
|
proc put*[K,V](self: SQLiteBackend[K,V], key: K, data: V): ?!void =
|
||||||
return self.db.putStmt.exec((key, data, timestamp()))
|
return self.db.putStmt.exec((key, data, timestamp()))
|
||||||
|
|
||||||
proc put*[K,V](self: SQLiteBackend[K,V], batch: openArray[DbBatchEntry]): ?!void =
|
proc put*[K,V](self: SQLiteBackend[K,V], batch: openArray[DbBatchEntry]): ?!void =
|
||||||
@ -106,7 +106,7 @@ proc close*[K,V](self: SQLiteBackend[K,V]): ?!void =
|
|||||||
proc query*[K,V](
|
proc query*[K,V](
|
||||||
self: SQLiteBackend[K,V],
|
self: SQLiteBackend[K,V],
|
||||||
query: DbQuery
|
query: DbQuery
|
||||||
): Result[DbQueryHandle[RawStmtPtr], ref CatchableError] =
|
): Result[DbQueryHandle[K, RawStmtPtr], ref CatchableError] =
|
||||||
|
|
||||||
var
|
var
|
||||||
queryStr = if query.value:
|
queryStr = if query.value:
|
||||||
@ -151,16 +151,16 @@ proc query*[K,V](
|
|||||||
if not (v == SQLITE_OK):
|
if not (v == SQLITE_OK):
|
||||||
return failure newException(DatastoreError, $sqlite3_errstr(v))
|
return failure newException(DatastoreError, $sqlite3_errstr(v))
|
||||||
|
|
||||||
success DbQueryHandle[RawStmtPtr](query: query, env: s)
|
success DbQueryHandle[K, RawStmtPtr](query: query, env: s)
|
||||||
|
|
||||||
proc close*(handle: var DbQueryHandle[RawStmtPtr]) =
|
proc close*[K](handle: var DbQueryHandle[K, RawStmtPtr]) =
|
||||||
if not handle.closed:
|
if not handle.closed:
|
||||||
handle.closed = true
|
handle.closed = true
|
||||||
discard sqlite3_reset(handle.env)
|
discard sqlite3_reset(handle.env)
|
||||||
discard sqlite3_clear_bindings(handle.env)
|
discard sqlite3_clear_bindings(handle.env)
|
||||||
handle.env.dispose()
|
handle.env.dispose()
|
||||||
|
|
||||||
iterator iter*(handle: var DbQueryHandle[RawStmtPtr]): ?!DbQueryResponse =
|
iterator iter*[K](handle: var DbQueryHandle[K, RawStmtPtr]): ?!DbQueryResponse =
|
||||||
while not handle.cancel:
|
while not handle.cancel:
|
||||||
|
|
||||||
let v = sqlite3_step(handle.env)
|
let v = sqlite3_step(handle.env)
|
||||||
@ -168,7 +168,7 @@ iterator iter*(handle: var DbQueryHandle[RawStmtPtr]): ?!DbQueryResponse =
|
|||||||
case v
|
case v
|
||||||
of SQLITE_ROW:
|
of SQLITE_ROW:
|
||||||
let
|
let
|
||||||
key = KeyId.new(sqlite3_column_text_not_null(handle.env, QueryStmtIdCol))
|
key = K.toKey(sqlite3_column_text_not_null(handle.env, QueryStmtIdCol))
|
||||||
|
|
||||||
blob: ?pointer =
|
blob: ?pointer =
|
||||||
if handle.query.value: sqlite3_column_blob(handle.env, QueryStmtDataCol).some
|
if handle.query.value: sqlite3_column_blob(handle.env, QueryStmtDataCol).some
|
||||||
@ -222,7 +222,7 @@ proc newSQLiteBackend*[K,V](
|
|||||||
if readOnly: SQLITE_OPEN_READONLY
|
if readOnly: SQLITE_OPEN_READONLY
|
||||||
else: SQLITE_OPEN_READWRITE or SQLITE_OPEN_CREATE
|
else: SQLITE_OPEN_READWRITE or SQLITE_OPEN_CREATE
|
||||||
|
|
||||||
success SQLiteBackend[K,V](db: ? SQLiteDsDb[KeyId,DataBuffer].open(path, flags))
|
success SQLiteBackend[K,V](db: ? SQLiteDsDb[K,V].open(path, flags))
|
||||||
|
|
||||||
|
|
||||||
proc newSQLiteBackend*[K,V](
|
proc newSQLiteBackend*[K,V](
|
||||||
|
|||||||
@ -14,12 +14,12 @@ import pkg/datastore/key
|
|||||||
import ../dscommontests
|
import ../dscommontests
|
||||||
import ../querycommontests
|
import ../querycommontests
|
||||||
|
|
||||||
proc testBasic[K, V, B](
|
proc testBasic[K, V](
|
||||||
ds: SQLiteBackend,
|
ds: SQLiteBackend[K,V],
|
||||||
key: K,
|
key: K,
|
||||||
bytes: V,
|
bytes: V,
|
||||||
otherBytes: V,
|
otherBytes: V,
|
||||||
batch: B,
|
batch: seq[DbBatchEntry[K, V]],
|
||||||
) =
|
) =
|
||||||
|
|
||||||
test "put":
|
test "put":
|
||||||
@ -60,14 +60,17 @@ proc testBasic[K, V, B](
|
|||||||
check: not ds.has(k).tryGet
|
check: not ds.has(k).tryGet
|
||||||
|
|
||||||
test "handle missing key":
|
test "handle missing key":
|
||||||
let key = KeyId.new Key.init("/missing/key").tryGet().id()
|
when K is KeyId:
|
||||||
|
let key = KeyId.new Key.init("/missing/key").tryGet().id()
|
||||||
|
elif K is string:
|
||||||
|
let key = $KeyId.new Key.init("/missing/key").tryGet().id()
|
||||||
|
|
||||||
expect(DatastoreKeyNotFound):
|
expect(DatastoreKeyNotFound):
|
||||||
discard ds.get(key).tryGet() # non existing key
|
discard ds.get(key).tryGet() # non existing key
|
||||||
|
|
||||||
suite "Test Basic SQLiteDatastore":
|
suite "Test Basic SQLiteDatastore":
|
||||||
let
|
let
|
||||||
ds = newSQLiteBackend[KeyId, DataBuffer](path=Memory).tryGet()
|
ds = newSQLiteBackend[string, seq[byte]](path=Memory).tryGet()
|
||||||
keyFull = Key.init("a:b/c/d:e").tryGet()
|
keyFull = Key.init("a:b/c/d:e").tryGet()
|
||||||
key = keyFull.id()
|
key = keyFull.id()
|
||||||
bytes = "some bytes".toBytes
|
bytes = "some bytes".toBytes
|
||||||
@ -81,7 +84,7 @@ suite "Test Basic SQLiteDatastore":
|
|||||||
suiteTeardown:
|
suiteTeardown:
|
||||||
ds.close().tryGet()
|
ds.close().tryGet()
|
||||||
|
|
||||||
# testBasic(ds, key, bytes, otherBytes, batch)
|
testBasic(ds, key, bytes, otherBytes, batch)
|
||||||
|
|
||||||
suite "Test DataBuffer SQLiteDatastore":
|
suite "Test DataBuffer SQLiteDatastore":
|
||||||
let
|
let
|
||||||
@ -123,7 +126,7 @@ suite "queryTests":
|
|||||||
|
|
||||||
test "Key should query all keys and all it's children":
|
test "Key should query all keys and all it's children":
|
||||||
let
|
let
|
||||||
q = DbQuery(key: key1, value: true)
|
q = DbQuery[KeyId](key: key1, value: true)
|
||||||
|
|
||||||
ds.put(key1, val1).tryGet
|
ds.put(key1, val1).tryGet
|
||||||
ds.put(key2, val2).tryGet
|
ds.put(key2, val2).tryGet
|
||||||
@ -146,7 +149,7 @@ suite "queryTests":
|
|||||||
|
|
||||||
test "query should cancel":
|
test "query should cancel":
|
||||||
let
|
let
|
||||||
q = DbQuery(key: key1, value: true)
|
q = DbQuery[KeyId](key: key1, value: true)
|
||||||
|
|
||||||
ds.put(key1, val1).tryGet
|
ds.put(key1, val1).tryGet
|
||||||
ds.put(key2, val2).tryGet
|
ds.put(key2, val2).tryGet
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user