From ce4acc168cd64aa5ae5e2b7d5a2aa17d5f58ce39 Mon Sep 17 00:00:00 2001 From: Jacek Sieka Date: Fri, 28 Jan 2022 14:23:41 +0100 Subject: [PATCH] kvstore: simplified stmt exec iterator (#467) --- eth/db/kvstore_sqlite3.nim | 42 +++++++++++++++++++++++++++++++ tests/db/test_kvstore_sqlite3.nim | 8 ++++++ 2 files changed, 50 insertions(+) diff --git a/eth/db/kvstore_sqlite3.nim b/eth/db/kvstore_sqlite3.nim index 3def35e1..2c3d6095 100644 --- a/eth/db/kvstore_sqlite3.nim +++ b/eth/db/kvstore_sqlite3.nim @@ -211,6 +211,48 @@ proc exec*[Params, Res](s: SqliteStmt[Params, Res], discard sqlite3_reset(s) # same return information as step discard sqlite3_clear_bindings(s) # no errors possible +iterator exec*[Params, Res](s: SqliteStmt[Params, Res], + params: Params, item: var Res): KvResult[void] = + let s = RawStmtPtr s + + # we use a mutable `res` variable here to avoid the code bloat that multiple + # `yield` statements cause when inlining the loop body + var res = KvResult[void].ok() + when params is tuple: + var i = 1 + for param in fields(params): + if (let v = bindParam(s, i, param); v != SQLITE_OK): + res = KvResult[void].err($sqlite3_errstr(v)) + break + + inc i + else: + if (let v = bindParam(s, 1, params); v != SQLITE_OK): + res = KvResult[void].err($sqlite3_errstr(v)) + + defer: + # release implicit transaction + discard sqlite3_reset(s) # same return information as step + discard sqlite3_clear_bindings(s) # no errors possible + + while res.isOk(): + let v = sqlite3_step(s) + case v + of SQLITE_ROW: + item = readResult(s, Res) + yield KvResult[void].ok() + of SQLITE_DONE: + break + else: + res = KvResult[void].err($sqlite3_errstr(v)) + + if not res.isOk(): + yield res + +iterator exec*[Res](s: SqliteStmt[NoParams, Res], item: var Res): KvResult[void] = + for r in exec(s, (), item): + yield r + template exec*(s: SqliteStmt[NoParams, void]): KvResult[void] = exec(s, ()) diff --git a/tests/db/test_kvstore_sqlite3.nim b/tests/db/test_kvstore_sqlite3.nim index 952de8bd..a69121af 100644 --- a/tests/db/test_kvstore_sqlite3.nim +++ b/tests/db/test_kvstore_sqlite3.nim @@ -225,3 +225,11 @@ procSuite "SqStoreRef": check: selectRes.isOk and selectRes.get == true abc == val + + var found = false + var row: selectStmt.Result + for rowRes in selectStmt.exec(row): + rowRes.expect("working db") + check abc == row + found = true + check found \ No newline at end of file