sqlite: separate contains query

Using `select 1` for contains query tells sqlite not to actually load
the data for simple contains queries
This commit is contained in:
Jacek Sieka 2020-04-28 10:06:39 +02:00 committed by zah
parent 17586c05d7
commit f730557baa

View File

@ -12,7 +12,7 @@ export kvstore
type type
SqStoreRef* = ref object of RootObj SqStoreRef* = ref object of RootObj
env: ptr sqlite3 env: ptr sqlite3
selectStmt, insertStmt, deleteStmt: ptr sqlite3_stmt getStmt, putStmt, delStmt, containsStmt: ptr sqlite3_stmt
template checkErr(op, cleanup: untyped) = template checkErr(op, cleanup: untyped) =
if (let v = (op); v != SQLITE_OK): if (let v = (op); v != SQLITE_OK):
@ -26,16 +26,16 @@ proc bindBlob(s: ptr sqlite3_stmt, n: int, blob: openarray[byte]): cint =
sqlite3_bind_blob(s, n.cint, unsafeAddr blob[0], blob.len.cint, nil) sqlite3_bind_blob(s, n.cint, unsafeAddr blob[0], blob.len.cint, nil)
proc get*(db: SqStoreRef, key: openarray[byte], onData: DataProc): KvResult[bool] = proc get*(db: SqStoreRef, key: openarray[byte], onData: DataProc): KvResult[bool] =
checkErr sqlite3_reset(db.selectStmt) checkErr sqlite3_reset(db.getStmt)
checkErr sqlite3_clear_bindings(db.selectStmt) checkErr sqlite3_clear_bindings(db.getStmt)
checkErr bindBlob(db.selectStmt, 1, key) checkErr bindBlob(db.getStmt, 1, key)
let v = sqlite3_step(db.selectStmt) let v = sqlite3_step(db.getStmt)
case v case v
of SQLITE_ROW: of SQLITE_ROW:
let let
p = cast[ptr UncheckedArray[byte]](sqlite3_column_blob(db.selectStmt, 0)) p = cast[ptr UncheckedArray[byte]](sqlite3_column_blob(db.getStmt, 0))
l = sqlite3_column_bytes(db.selectStmt, 0) l = sqlite3_column_bytes(db.getStmt, 0)
onData(toOpenArray(p, 0, l-1)) onData(toOpenArray(p, 0, l-1))
ok(true) ok(true)
of SQLITE_DONE: of SQLITE_DONE:
@ -44,44 +44,45 @@ proc get*(db: SqStoreRef, key: openarray[byte], onData: DataProc): KvResult[bool
err($sqlite3_errstr(v)) err($sqlite3_errstr(v))
proc put*(db: SqStoreRef, key, value: openarray[byte]): KvResult[void] = proc put*(db: SqStoreRef, key, value: openarray[byte]): KvResult[void] =
checkErr sqlite3_reset(db.insertStmt) checkErr sqlite3_reset(db.putStmt)
checkErr sqlite3_clear_bindings(db.insertStmt) checkErr sqlite3_clear_bindings(db.putStmt)
checkErr bindBlob(db.insertStmt, 1, key) checkErr bindBlob(db.putStmt, 1, key)
checkErr bindBlob(db.insertStmt, 2, value) checkErr bindBlob(db.putStmt, 2, value)
if (let v = sqlite3_step(db.insertStmt); v != SQLITE_DONE): if (let v = sqlite3_step(db.putStmt); v != SQLITE_DONE):
err($sqlite3_errstr(v)) err($sqlite3_errstr(v))
else: else:
ok() ok()
proc contains*(db: SqStoreRef, key: openarray[byte]): KvResult[bool] = proc contains*(db: SqStoreRef, key: openarray[byte]): KvResult[bool] =
checkErr sqlite3_reset(db.selectStmt) checkErr sqlite3_reset(db.containsStmt)
checkErr sqlite3_clear_bindings(db.selectStmt) checkErr sqlite3_clear_bindings(db.containsStmt)
checkErr bindBlob(db.selectStmt, 1, key) checkErr bindBlob(db.containsStmt, 1, key)
let v = sqlite3_step(db.selectStmt) let v = sqlite3_step(db.containsStmt)
case v case v
of SQLITE_ROW: ok(true) of SQLITE_ROW: ok(true)
of SQLITE_DONE: ok(false) of SQLITE_DONE: ok(false)
else: err($sqlite3_errstr(v)) else: err($sqlite3_errstr(v))
proc del*(db: SqStoreRef, key: openarray[byte]): KvResult[void] = proc del*(db: SqStoreRef, key: openarray[byte]): KvResult[void] =
checkErr sqlite3_reset(db.deleteStmt) checkErr sqlite3_reset(db.delStmt)
checkErr sqlite3_clear_bindings(db.deleteStmt) checkErr sqlite3_clear_bindings(db.delStmt)
checkErr bindBlob(db.deleteStmt, 1, key) checkErr bindBlob(db.delStmt, 1, key)
if (let v = sqlite3_step(db.deleteStmt); v != SQLITE_DONE): if (let v = sqlite3_step(db.delStmt); v != SQLITE_DONE):
err($sqlite3_errstr(v)) err($sqlite3_errstr(v))
else: else:
ok() ok()
proc close*(db: SqStoreRef) = proc close*(db: SqStoreRef) =
discard sqlite3_finalize(db.insertStmt) discard sqlite3_finalize(db.putStmt)
discard sqlite3_finalize(db.selectStmt) discard sqlite3_finalize(db.getStmt)
discard sqlite3_finalize(db.deleteStmt) discard sqlite3_finalize(db.delStmt)
discard sqlite3_finalize(db.containsStmt)
discard sqlite3_close(db.env) discard sqlite3_close(db.env)
@ -142,17 +143,22 @@ proc init*(
""" """
let let
selectStmt = prepare "SELECT value FROM kvstore WHERE key = ?;": getStmt = prepare "SELECT value FROM kvstore WHERE key = ?;":
discard discard
insertStmt = prepare "INSERT OR REPLACE INTO kvstore(key, value) VALUES (?, ?);": putStmt = prepare "INSERT OR REPLACE INTO kvstore(key, value) VALUES (?, ?);":
discard sqlite3_finalize(selectStmt) discard sqlite3_finalize(getStmt)
deleteStmt = prepare "DELETE FROM kvstore WHERE key = ?;": delStmt = prepare "DELETE FROM kvstore WHERE key = ?;":
discard sqlite3_finalize(selectStmt) discard sqlite3_finalize(getStmt)
discard sqlite3_finalize(insertStmt) discard sqlite3_finalize(putStmt)
containsStmt = prepare "SELECT 1 FROM kvstore WHERE key = ?;":
discard sqlite3_finalize(getStmt)
discard sqlite3_finalize(putStmt)
discard sqlite3_finalize(delStmt)
ok(SqStoreRef( ok(SqStoreRef(
env: env, env: env,
selectStmt: selectStmt, getStmt: getStmt,
insertStmt: insertStmt, putStmt: putStmt,
deleteStmt: deleteStmt delStmt: delStmt,
containsStmt: containsStmt
)) ))