change to non-closure iterator

This commit is contained in:
Jaremy Creechley 2023-09-25 17:49:17 -07:00
parent 0336b93360
commit 92dcbf70ae
No known key found for this signature in database
GPG Key ID: 4E66FB67B21D3300
3 changed files with 28 additions and 22 deletions

View File

@ -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)))

View File

@ -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](

View File

@ -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