[node] custom iterator/query for SQLiteStore's `method listBlocks`

This commit is contained in:
Michael Bradley, Jr 2022-08-07 10:02:18 -05:00 committed by Michael Bradley
parent 2ecf750959
commit eebcf7e7b2
1 changed files with 40 additions and 7 deletions

View File

@ -19,6 +19,7 @@ import pkg/datastore/sqlite_datastore
import pkg/libp2p import pkg/libp2p
import pkg/questionable import pkg/questionable
import pkg/questionable/results import pkg/questionable/results
import pkg/sqlite3_abi
import ./blockstore import ./blockstore
import ./cachestore import ./cachestore
@ -29,14 +30,20 @@ logScope:
topics = "codex sqlitestore" topics = "codex sqlitestore"
type type
ListBlocksQueryResponse = string
ListBlocksQueryStmt = SQLiteStmt[(string), void]
SQLiteStore* = ref object of BlockStore SQLiteStore* = ref object of BlockStore
cache: BlockStore cache: BlockStore
datastore: SQLiteDatastore datastore: SQLiteDatastore
const const
allBlocks = when (let keyRes = Key.init("*"); true): listBlocksQueryStmtStr = """
if keyRes.isOk: Query.init(keyRes.get) SELECT """ & idColName & """ FROM """ & tableName & """;
else: raise (ref Defect)(msg: keyRes.error.msg) """
listBlocksQueryStmtIdCol = 0
proc new*( proc new*(
T: type SQLiteStore, T: type SQLiteStore,
@ -195,6 +202,31 @@ method hasBlock*(
return await self.datastore.contains(blkKey) return await self.datastore.contains(blkKey)
iterator listBlocksQuery(self: SQLiteStore): ListBlocksQueryResponse =
without listBlocksQueryStmt =? ListBlocksQueryStmt.prepare(self.datastore.env,
listBlocksQueryStmtStr), error:
raise (ref Defect)(msg: error.msg)
let
s = RawStmtPtr(listBlocksQueryStmt)
defer:
discard sqlite3_reset(s)
s.dispose
while true:
let
v = sqlite3_step(s)
case v
of SQLITE_ROW:
yield $sqlite3_column_text_not_null(s, listBlocksQueryStmtIdCol)
of SQLITE_DONE:
break
else:
raise (ref Defect)(msg: $sqlite3_errstr(v))
method listBlocks*( method listBlocks*(
self: SQLiteStore, self: SQLiteStore,
onBlock: OnBlock): Future[?!void] {.async.} = onBlock: OnBlock): Future[?!void] {.async.} =
@ -202,15 +234,16 @@ method listBlocks*(
## This is an intensive operation ## This is an intensive operation
## ##
for kd in self.datastore.query(allBlocks): for id in self.listBlocksQuery():
let let
(key, _) = await kd # keys stored in id column of SQLiteDatastore are serialized Key
cidRes = Cid.init(key.name) # instances that start with "/", so drop the first character
cidRes = Cid.init(id[1..^1])
if cidRes.isOk: if cidRes.isOk:
await onBlock(cidRes.get) await onBlock(cidRes.get)
else: else:
trace "Unable to construct CID from key", key = key.id, error = $cidRes.error trace "Unable to construct CID from key", key = id, error = $cidRes.error
return success() return success()