mirror of
https://github.com/logos-storage/nim-datastore.git
synced 2026-01-09 17:13:10 +00:00
change to non-closure iterator
This commit is contained in:
parent
85352e8bc5
commit
0336b93360
@ -15,21 +15,21 @@ export backend, sqlitedsdb
|
||||
push: {.upraises: [].}
|
||||
|
||||
type
|
||||
SQLiteBackend* = object
|
||||
db: SQLiteDsDb
|
||||
SQLiteBackend*[K, V] = object
|
||||
db: SQLiteDsDb[K, V]
|
||||
|
||||
proc path*(self: SQLiteBackend): string =
|
||||
proc path*[K,V](self: SQLiteBackend[K,V]): string =
|
||||
$self.db.dbPath
|
||||
|
||||
proc readOnly*(self: SQLiteBackend): bool = self.db.readOnly
|
||||
proc readOnly*[K,V](self: SQLiteBackend[K,V]): bool = self.db.readOnly
|
||||
|
||||
proc timestamp*(t = epochTime()): int64 =
|
||||
(t * 1_000_000).int64
|
||||
|
||||
proc has*(self: SQLiteBackend, key: DbKey): ?!bool =
|
||||
proc has*[K,V](self: SQLiteBackend[K,V], key: DbKey): ?!bool =
|
||||
var
|
||||
exists = false
|
||||
key = $key
|
||||
key = key
|
||||
|
||||
proc onData(s: RawStmtPtr) =
|
||||
exists = sqlite3_column_int64(s, ContainsStmtExistsCol.cint).bool
|
||||
@ -39,15 +39,15 @@ proc has*(self: SQLiteBackend, key: DbKey): ?!bool =
|
||||
|
||||
return success exists
|
||||
|
||||
proc delete*(self: SQLiteBackend, key: DbKey): ?!void =
|
||||
return self.db.deleteStmt.exec(($key))
|
||||
proc delete*[K,V](self: SQLiteBackend[K,V], key: DbKey): ?!void =
|
||||
return self.db.deleteStmt.exec((key))
|
||||
|
||||
proc delete*(self: SQLiteBackend, keys: openArray[DbKey]): ?!void =
|
||||
proc delete*[K,V](self: SQLiteBackend[K,V], keys: openArray[DbKey]): ?!void =
|
||||
if err =? self.db.beginStmt.exec().errorOption:
|
||||
return failure(err)
|
||||
|
||||
for key in keys:
|
||||
if err =? self.db.deleteStmt.exec(($key)).errorOption:
|
||||
if err =? self.db.deleteStmt.exec((key)).errorOption:
|
||||
if err =? self.db.rollbackStmt.exec().errorOption:
|
||||
return failure err.msg
|
||||
|
||||
@ -58,7 +58,7 @@ proc delete*(self: SQLiteBackend, keys: openArray[DbKey]): ?!void =
|
||||
|
||||
return success()
|
||||
|
||||
proc get*(self: SQLiteBackend, key: DbKey): ?!seq[byte] =
|
||||
proc get*[K,V](self: SQLiteBackend[K,V], key: KeyId): ?!seq[byte] =
|
||||
# see comment in ./filesystem_datastore re: finer control of memory
|
||||
# allocation in `proc get`, could apply here as well if bytes were read
|
||||
# incrementally with `sqlite3_blob_read`
|
||||
@ -69,7 +69,7 @@ proc get*(self: SQLiteBackend, key: DbKey): ?!seq[byte] =
|
||||
proc onData(s: RawStmtPtr) =
|
||||
bytes = dataCol(self.db.getDataCol)
|
||||
|
||||
if err =? self.db.getStmt.query(($key), onData).errorOption:
|
||||
if err =? self.db.getStmt.query((key), onData).errorOption:
|
||||
return failure(err)
|
||||
|
||||
if bytes.len <= 0:
|
||||
@ -78,25 +78,15 @@ proc get*(self: SQLiteBackend, key: DbKey): ?!seq[byte] =
|
||||
|
||||
return success bytes
|
||||
|
||||
proc put*(self: SQLiteBackend, key: DbKey, data: DbVal): ?!void =
|
||||
when DbVal is seq[byte]:
|
||||
return self.db.putStmt.exec((key, data, timestamp()))
|
||||
elif DbVal is DataBuffer:
|
||||
return self.db.putBufferStmt.exec((key, data, timestamp()))
|
||||
else:
|
||||
{.error: "unknown type".}
|
||||
proc put*[K,V](self: SQLiteBackend[K,V], key: KeyId, data: DataBuffer): ?!void =
|
||||
return self.db.putStmt.exec((key, data, timestamp()))
|
||||
|
||||
proc put*(self: SQLiteBackend, batch: openArray[DbBatchEntry]): ?!void =
|
||||
proc put*[K,V](self: SQLiteBackend[K,V], batch: openArray[DbBatchEntry]): ?!void =
|
||||
if err =? self.db.beginStmt.exec().errorOption:
|
||||
return failure err
|
||||
|
||||
for entry in batch:
|
||||
when entry.key is string:
|
||||
let putStmt = self.db.putStmt
|
||||
elif entry.key is KeyId:
|
||||
let putStmt = self.db.putBufferStmt
|
||||
else:
|
||||
{.error: "unhandled type".}
|
||||
let putStmt = self.db.putStmt
|
||||
if err =? putStmt.exec((entry.key, entry.data, timestamp())).errorOption:
|
||||
if err =? self.db.rollbackStmt.exec().errorOption:
|
||||
return failure err
|
||||
@ -108,13 +98,13 @@ proc put*(self: SQLiteBackend, batch: openArray[DbBatchEntry]): ?!void =
|
||||
|
||||
return success()
|
||||
|
||||
proc close*(self: SQLiteBackend): ?!void =
|
||||
proc close*[K,V](self: SQLiteBackend[K,V]): ?!void =
|
||||
self.db.close()
|
||||
|
||||
return success()
|
||||
|
||||
proc query*(
|
||||
self: SQLiteBackend,
|
||||
proc query*[K,V](
|
||||
self: SQLiteBackend[K,V],
|
||||
query: DbQuery
|
||||
): Result[DbQueryHandle[RawStmtPtr], ref CatchableError] =
|
||||
|
||||
@ -219,23 +209,23 @@ iterator iter*(handle: var DbQueryHandle[RawStmtPtr]): ?!DbQueryResponse =
|
||||
handle.close()
|
||||
|
||||
|
||||
proc contains*(self: SQLiteBackend, key: DbKey): bool =
|
||||
proc contains*[K,V](self: SQLiteBackend[K,V], key: DbKey): bool =
|
||||
return self.has(key).get()
|
||||
|
||||
|
||||
proc new*(T: type SQLiteBackend,
|
||||
proc newSQLiteBackend*[K,V](
|
||||
path: string,
|
||||
readOnly = false): ?!SQLiteBackend =
|
||||
readOnly = false): ?!SQLiteBackend[K,V] =
|
||||
|
||||
let
|
||||
flags =
|
||||
if readOnly: SQLITE_OPEN_READONLY
|
||||
else: SQLITE_OPEN_READWRITE or SQLITE_OPEN_CREATE
|
||||
|
||||
success SQLiteBackend(db: ? SQLiteDsDb.open(path, flags))
|
||||
success SQLiteBackend[K,V](db: ? SQLiteDsDb[KeyId,DataBuffer].open(path, flags))
|
||||
|
||||
|
||||
proc new*(T: type SQLiteBackend,
|
||||
db: SQLiteDsDb): ?!T =
|
||||
proc newSQLiteBackend*[K,V](
|
||||
db: SQLiteDsDb[K,V]): ?!SQLiteBackend[K,V] =
|
||||
|
||||
success SQLiteBackend(db: db)
|
||||
success SQLiteBackend[K,V](db: db)
|
||||
|
||||
@ -17,26 +17,24 @@ type
|
||||
# feels odd to use `void` for prepared statements corresponding to SELECT
|
||||
# queries but it fits with the rest of the SQLite wrapper adapted from
|
||||
# status-im/nwaku, at least in its current form in ./sqlite
|
||||
ContainsStmt* = SQLiteStmt[(string), void]
|
||||
DeleteStmt* = SQLiteStmt[(string), void]
|
||||
GetStmt* = SQLiteStmt[(string), void]
|
||||
PutStmt* = SQLiteStmt[(string, seq[byte], int64), void]
|
||||
PutBufferStmt* = SQLiteStmt[(KeyId, DataBuffer, int64), void]
|
||||
ContainsStmt*[K] = SQLiteStmt[(K), void]
|
||||
DeleteStmt*[K] = SQLiteStmt[(K), void]
|
||||
GetStmt*[K] = SQLiteStmt[(K), void]
|
||||
PutStmt*[K, V] = SQLiteStmt[(K, V, int64), void]
|
||||
QueryStmt* = SQLiteStmt[(string), void]
|
||||
BeginStmt* = NoParamsStmt
|
||||
EndStmt* = NoParamsStmt
|
||||
RollbackStmt* = NoParamsStmt
|
||||
|
||||
SQLiteDsDb* = object
|
||||
SQLiteDsDb*[K,V] = object
|
||||
readOnly*: bool
|
||||
dbPath*: DataBuffer
|
||||
containsStmt*: ContainsStmt
|
||||
deleteStmt*: DeleteStmt
|
||||
containsStmt*: ContainsStmt[K]
|
||||
deleteStmt*: DeleteStmt[K]
|
||||
env*: SQLite
|
||||
getDataCol*: (RawStmtPtr, int)
|
||||
getStmt*: GetStmt
|
||||
putStmt*: PutStmt
|
||||
putBufferStmt*: PutBufferStmt
|
||||
getStmt*: GetStmt[K]
|
||||
putStmt*: PutStmt[K,V]
|
||||
beginStmt*: BeginStmt
|
||||
endStmt*: EndStmt
|
||||
rollbackStmt*: RollbackStmt
|
||||
@ -230,10 +228,10 @@ proc close*(self: SQLiteDsDb) =
|
||||
|
||||
self.env.dispose
|
||||
|
||||
proc open*(
|
||||
T: type SQLiteDsDb,
|
||||
proc open*[K,V](
|
||||
T: type SQLiteDsDb[K,V],
|
||||
path = Memory,
|
||||
flags = SQLITE_OPEN_READONLY): ?!SQLiteDsDb =
|
||||
flags = SQLITE_OPEN_READONLY): ?!SQLiteDsDb[K, V] =
|
||||
|
||||
# make it optional to enable WAL with it enabled being the default?
|
||||
|
||||
@ -266,11 +264,10 @@ proc open*(
|
||||
checkExec(pragmaStmt)
|
||||
|
||||
var
|
||||
containsStmt: ContainsStmt
|
||||
deleteStmt: DeleteStmt
|
||||
getStmt: GetStmt
|
||||
putStmt: PutStmt
|
||||
putBufferStmt: PutBufferStmt
|
||||
containsStmt: ContainsStmt[K]
|
||||
deleteStmt: DeleteStmt[K]
|
||||
getStmt: GetStmt[K]
|
||||
putStmt: PutStmt[K,V]
|
||||
beginStmt: BeginStmt
|
||||
endStmt: EndStmt
|
||||
rollbackStmt: RollbackStmt
|
||||
@ -278,13 +275,10 @@ proc open*(
|
||||
if not readOnly:
|
||||
checkExec(env.val, CreateStmtStr)
|
||||
|
||||
deleteStmt = ? DeleteStmt.prepare(
|
||||
deleteStmt = ? DeleteStmt[K].prepare(
|
||||
env.val, DeleteStmtStr, SQLITE_PREPARE_PERSISTENT)
|
||||
|
||||
putStmt = ? PutStmt.prepare(
|
||||
env.val, PutStmtStr, SQLITE_PREPARE_PERSISTENT)
|
||||
|
||||
putBufferStmt = ? PutBufferStmt.prepare(
|
||||
putStmt = ? PutStmt[K,V].prepare(
|
||||
env.val, PutStmtStr, SQLITE_PREPARE_PERSISTENT)
|
||||
|
||||
beginStmt = ? BeginStmt.prepare(
|
||||
@ -296,10 +290,10 @@ proc open*(
|
||||
rollbackStmt = ? RollbackStmt.prepare(
|
||||
env.val, RollbackTransactionStr, SQLITE_PREPARE_PERSISTENT)
|
||||
|
||||
containsStmt = ? ContainsStmt.prepare(
|
||||
containsStmt = ? ContainsStmt[K].prepare(
|
||||
env.val, ContainsStmtStr, SQLITE_PREPARE_PERSISTENT)
|
||||
|
||||
getStmt = ? GetStmt.prepare(
|
||||
getStmt = ? GetStmt[K].prepare(
|
||||
env.val, GetStmtStr, SQLITE_PREPARE_PERSISTENT)
|
||||
|
||||
# if a readOnly/existing database does not satisfy the expected schema
|
||||
@ -309,7 +303,7 @@ proc open*(
|
||||
let
|
||||
getDataCol = (RawStmtPtr(getStmt), GetStmtDataCol)
|
||||
|
||||
success SQLiteDsDb(
|
||||
success SQLiteDsDb[K,V](
|
||||
readOnly: readOnly,
|
||||
dbPath: DataBuffer.new path,
|
||||
containsStmt: containsStmt,
|
||||
@ -318,7 +312,6 @@ proc open*(
|
||||
getStmt: getStmt,
|
||||
getDataCol: getDataCol,
|
||||
putStmt: putStmt,
|
||||
putBufferStmt: putBufferStmt,
|
||||
beginStmt: beginStmt,
|
||||
endStmt: endStmt,
|
||||
rollbackStmt: rollbackStmt)
|
||||
|
||||
@ -60,14 +60,14 @@ proc testBasic[K, V, B](
|
||||
check: not ds.has(k).tryGet
|
||||
|
||||
test "handle missing key":
|
||||
let key = Key.init("/missing/key").tryGet().id()
|
||||
let key = KeyId.new Key.init("/missing/key").tryGet().id()
|
||||
|
||||
expect(DatastoreKeyNotFound):
|
||||
discard ds.get(key).tryGet() # non existing key
|
||||
|
||||
suite "Test Basic SQLiteDatastore":
|
||||
let
|
||||
ds = SQLiteBackend.new(Memory).tryGet()
|
||||
ds = newSQLiteBackend[KeyId, DataBuffer](path=Memory).tryGet()
|
||||
keyFull = Key.init("a:b/c/d:e").tryGet()
|
||||
key = keyFull.id()
|
||||
bytes = "some bytes".toBytes
|
||||
@ -81,11 +81,11 @@ suite "Test Basic SQLiteDatastore":
|
||||
suiteTeardown:
|
||||
ds.close().tryGet()
|
||||
|
||||
testBasic(ds, key, bytes, otherBytes, batch)
|
||||
# testBasic(ds, key, bytes, otherBytes, batch)
|
||||
|
||||
suite "Test DataBuffer SQLiteDatastore":
|
||||
let
|
||||
ds = SQLiteBackend.new(Memory).tryGet()
|
||||
ds = newSQLiteBackend[KeyId, DataBuffer](Memory).tryGet()
|
||||
keyFull = Key.init("a:b/c/d:e").tryGet()
|
||||
key = KeyId.new keyFull.id()
|
||||
bytes = DataBuffer.new "some bytes"
|
||||
@ -103,7 +103,7 @@ suite "Test DataBuffer SQLiteDatastore":
|
||||
|
||||
suite "queryTests":
|
||||
let
|
||||
ds = SQLiteBackend.new(Memory).tryGet()
|
||||
ds = newSQLiteBackend[KeyId, DataBuffer](Memory).tryGet()
|
||||
|
||||
var
|
||||
key1: KeyId
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user