mirror of https://github.com/status-im/nim-eth.git
kvstore: return bool from del, add clear (#574)
This allows making decisions based on whether an element was present during the `del`
This commit is contained in:
parent
40ec601d07
commit
8f0ae55353
|
@ -31,7 +31,8 @@ type
|
|||
PutProc = proc (db: RootRef, key, val: openArray[byte]): KvResult[void] {.nimcall, gcsafe, raises: [Defect].}
|
||||
GetProc = proc (db: RootRef, key: openArray[byte], onData: DataProc): KvResult[bool] {.nimcall, gcsafe, raises: [Defect].}
|
||||
FindProc = proc (db: RootRef, prefix: openArray[byte], onFind: KeyValueProc): KvResult[int] {.nimcall, gcsafe, raises: [Defect].}
|
||||
DelProc = proc (db: RootRef, key: openArray[byte]): KvResult[void] {.nimcall, gcsafe, raises: [Defect].}
|
||||
DelProc = proc (db: RootRef, key: openArray[byte]): KvResult[bool] {.nimcall, gcsafe, raises: [Defect].}
|
||||
ClearProc = proc (db: RootRef): KvResult[bool] {.nimcall, gcsafe, raises: [Defect].}
|
||||
ContainsProc = proc (db: RootRef, key: openArray[byte]): KvResult[bool] {.nimcall, gcsafe, raises: [Defect].}
|
||||
CloseProc = proc (db: RootRef): KvResult[void] {.nimcall, gcsafe, raises: [Defect].}
|
||||
|
||||
|
@ -42,6 +43,7 @@ type
|
|||
getProc: GetProc
|
||||
findProc: FindProc
|
||||
delProc: DelProc
|
||||
clearProc: ClearProc
|
||||
containsProc: ContainsProc
|
||||
closeProc: CloseProc
|
||||
|
||||
|
@ -68,11 +70,18 @@ template find*(
|
|||
let db = dbParam
|
||||
db.findProc(db.obj, prefix, onFind)
|
||||
|
||||
template del*(dbParam: KvStoreRef, key: openArray[byte]): KvResult[void] =
|
||||
template del*(dbParam: KvStoreRef, key: openArray[byte]): KvResult[bool] =
|
||||
## Remove value at ``key`` from store - do nothing if the value is not present
|
||||
## Returns true iff value was found and deleted
|
||||
let db = dbParam
|
||||
db.delProc(db.obj, key)
|
||||
|
||||
template clear*(dbParam: KvStoreRef): KvResult[bool] =
|
||||
## Remove all values from store
|
||||
## Returns true iff a value was found and deleted
|
||||
let db = dbParam
|
||||
db.clearProc(db.obj)
|
||||
|
||||
template contains*(dbParam: KvStoreRef, key: openArray[byte]): KvResult[bool] =
|
||||
## Return true iff ``key`` has a value in store
|
||||
let db = dbParam
|
||||
|
@ -95,10 +104,14 @@ proc findImpl[T](db: RootRef, key: openArray[byte], onFind: KeyValueProc): KvRes
|
|||
mixin get
|
||||
find(T(db), key, onFind)
|
||||
|
||||
proc delImpl[T](db: RootRef, key: openArray[byte]): KvResult[void] {.gcsafe.} =
|
||||
proc delImpl[T](db: RootRef, key: openArray[byte]): KvResult[bool] {.gcsafe.} =
|
||||
mixin del
|
||||
del(T(db), key)
|
||||
|
||||
proc clearImpl[T](db: RootRef): KvResult[bool] {.gcsafe.} =
|
||||
mixin clear
|
||||
clear(T(db))
|
||||
|
||||
proc containsImpl[T](db: RootRef, key: openArray[byte]): KvResult[bool] {.gcsafe.} =
|
||||
mixin contains
|
||||
contains(T(db), key)
|
||||
|
@ -108,7 +121,7 @@ proc closeImpl[T](db: RootRef): KvResult[void] {.gcsafe.} =
|
|||
close(T(db))
|
||||
|
||||
func kvStore*[T: RootRef](x: T): KvStoreRef =
|
||||
mixin del, get, put, contains, close
|
||||
mixin del, clear, get, put, contains, close
|
||||
|
||||
KvStoreRef(
|
||||
obj: x,
|
||||
|
@ -116,6 +129,7 @@ func kvStore*[T: RootRef](x: T): KvStoreRef =
|
|||
getProc: getImpl[T],
|
||||
findProc: findImpl[T],
|
||||
delProc: delImpl[T],
|
||||
clearProc: clearImpl[T],
|
||||
containsProc: containsImpl[T],
|
||||
closeProc: closeImpl[T]
|
||||
)
|
||||
|
@ -139,9 +153,19 @@ proc find*(
|
|||
|
||||
ok(total)
|
||||
|
||||
proc del*(db: MemStoreRef, key: openArray[byte]): KvResult[void] =
|
||||
proc del*(db: MemStoreRef, key: openArray[byte]): KvResult[bool] =
|
||||
if @key in db.records:
|
||||
db.records.del(@key)
|
||||
ok()
|
||||
ok(true)
|
||||
else:
|
||||
ok(false)
|
||||
|
||||
proc clear*(db: MemStoreRef): KvResult[bool] =
|
||||
if db.records.len > 0:
|
||||
db.records.clear()
|
||||
ok(true)
|
||||
else:
|
||||
ok(false)
|
||||
|
||||
proc contains*(db: MemStoreRef, key: openArray[byte]): KvResult[bool] =
|
||||
ok(db.records.contains(@key))
|
||||
|
|
|
@ -38,7 +38,8 @@ type
|
|||
# A Keyspace is a single key-value table - it is generally efficient to
|
||||
# create separate keyspaces for each type of data stored
|
||||
open: bool
|
||||
getStmt, putStmt, delStmt, containsStmt,
|
||||
env: Sqlite
|
||||
getStmt, putStmt, delStmt, clearStmt, containsStmt,
|
||||
findStmt0, findStmt1, findStmt2: RawStmtPtr
|
||||
|
||||
SqKeyspaceRef* = ref SqKeyspace
|
||||
|
@ -433,17 +434,17 @@ proc contains*(db: SqKeyspaceRef, key: openArray[byte]): KvResult[bool] =
|
|||
|
||||
res
|
||||
|
||||
proc del*(db: SqKeyspaceRef, key: openArray[byte]): KvResult[void] =
|
||||
proc del*(db: SqKeyspaceRef, key: openArray[byte]): KvResult[bool] =
|
||||
if not db.open: return err("sqlite: database closed")
|
||||
let delStmt = db.delStmt
|
||||
if delStmt == nil: return ok() # no such table
|
||||
if delStmt == nil: return ok(false) # no such table
|
||||
checkErr bindParam(delStmt, 1, key)
|
||||
|
||||
let res =
|
||||
if (let v = sqlite3_step(delStmt); v != SQLITE_DONE):
|
||||
err($sqlite3_errstr(v))
|
||||
else:
|
||||
ok()
|
||||
ok(sqlite3_changes(db.env) > 0)
|
||||
|
||||
# release implict transaction
|
||||
discard sqlite3_reset(delStmt) # same return information as step
|
||||
|
@ -451,11 +452,28 @@ proc del*(db: SqKeyspaceRef, key: openArray[byte]): KvResult[void] =
|
|||
|
||||
res
|
||||
|
||||
proc clear*(db: SqKeyspaceRef): KvResult[bool] =
|
||||
if not db.open: return err("sqlite: database closed")
|
||||
let clearStmt = db.clearStmt
|
||||
if clearStmt == nil: return ok(false) # no such table
|
||||
|
||||
let res =
|
||||
if (let v = sqlite3_step(clearStmt); v != SQLITE_DONE):
|
||||
err($sqlite3_errstr(v))
|
||||
else:
|
||||
ok(sqlite3_changes(db.env) > 0)
|
||||
|
||||
# release implicit transaction
|
||||
discard sqlite3_reset(clearStmt) # same return information as step
|
||||
|
||||
res
|
||||
|
||||
proc close*(db: var SqKeyspace) =
|
||||
# Calling with null stmt is harmless
|
||||
discard sqlite3_finalize(db.putStmt)
|
||||
discard sqlite3_finalize(db.getStmt)
|
||||
discard sqlite3_finalize(db.delStmt)
|
||||
discard sqlite3_finalize(db.clearStmt)
|
||||
discard sqlite3_finalize(db.containsStmt)
|
||||
discard sqlite3_finalize(db.findStmt0)
|
||||
discard sqlite3_finalize(db.findStmt1)
|
||||
|
@ -604,7 +622,7 @@ proc openKvStore*(
|
|||
if withoutRowid: createSql & " WITHOUT ROWID;" else: createSql & ";"
|
||||
true
|
||||
var
|
||||
tmp: SqKeyspace
|
||||
tmp = SqKeyspace(env: db.env)
|
||||
defer:
|
||||
# We'll "move" ownership to the return value, effectively disabling "close"
|
||||
close(tmp)
|
||||
|
@ -615,6 +633,7 @@ proc openKvStore*(
|
|||
tmp.putStmt =
|
||||
prepare(db.env, "INSERT OR REPLACE INTO '" & name & "'(key, value) VALUES (?, ?);")
|
||||
tmp.delStmt = prepare(db.env, "DELETE FROM '" & name & "' WHERE key = ?;")
|
||||
tmp.clearStmt = prepare(db.env, "DELETE FROM '" & name & "';")
|
||||
tmp.containsStmt = prepare(db.env, "SELECT 1 FROM '" & name & "' WHERE key = ?;")
|
||||
tmp.findStmt0 = prepare(db.env, "SELECT key, value FROM '" & name & "';")
|
||||
tmp.findStmt1 = prepare(db.env, "SELECT key, value FROM '" & name & "' WHERE key >= ?;")
|
||||
|
|
|
@ -16,8 +16,7 @@ proc testKvStore*(db: KvStoreRef, supportsFind: bool) =
|
|||
|
||||
not db.get(key, proc(data: openArray[byte]) = discard)[]
|
||||
not db.contains(key)[]
|
||||
|
||||
db.del(key)[] # does nothing
|
||||
not db.del(key)[] # does nothing
|
||||
|
||||
db.put(key, value)[]
|
||||
|
||||
|
@ -39,12 +38,19 @@ proc testKvStore*(db: KvStoreRef, supportsFind: bool) =
|
|||
db.get(key, grab)[]
|
||||
v == value2
|
||||
|
||||
db.del(key)[]
|
||||
check:
|
||||
db.del(key)[]
|
||||
not db.get(key, proc(data: openArray[byte]) = discard)[]
|
||||
not db.contains(key)[]
|
||||
|
||||
db.del(key)[] # does nothing
|
||||
not db.del(key)[] # does nothing
|
||||
|
||||
db.put(key, value2)[] # overwrite old value
|
||||
check:
|
||||
db.contains(key)[]
|
||||
db.clear()[]
|
||||
not db.contains(key)[]
|
||||
not db.clear()[]
|
||||
|
||||
if supportsFind:
|
||||
check:
|
||||
|
|
Loading…
Reference in New Issue