db: InstantRow and instantRows

It is drop-in replacement for Row and fastRows, however instantRows returns a
handle, not seq[string], so no Nim string is created until [] operator is
called on the given handle. Also there is a len() proc returning number of
columns in the handle.

In some situations, when we iterate through many rows, but later we just read
few columns this solution will be quicker than converting all column to Nim
seq[string] on each iteration.
This commit is contained in:
Adam Strzelecki 2015-06-04 00:38:49 +02:00
commit 8742907133
3 changed files with 71 additions and 1 deletions

View file

@ -16,6 +16,9 @@ type
DbConn* = PPGconn ## encapsulates a database connection
Row* = seq[string] ## a row of a dataset. NULL database values will be
## transformed always to the empty string.
InstantRow* = tuple[res: PPGresult, line: int32] ## a handle that can be
## used to get a row's
## column text on demand
EDb* = object of IOError ## exception that is raised if a database error occurs
SqlQuery* = distinct string ## an SQL query string
@ -159,6 +162,24 @@ iterator fastRows*(db: DbConn, stmtName: SqlPrepared,
yield result
pqClear(res)
iterator instantRows*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): InstantRow
{.tags: [FReadDb].} =
## same as fastRows but returns a handle that can be used to get column text
## on demand using []. Returned handle is valid only within interator body.
var res = setupQuery(db, query, args)
for i in 0..pqNtuples(res)-1:
yield (res: res, line: i)
pqClear(res)
proc `[]`*(row: InstantRow, col: int32): string {.inline.} =
## returns text for given column of the row
$pqgetvalue(row.res, row.line, col)
proc len*(row: InstantRow): int32 {.inline.} =
## returns number of columns in the row
pqNfields(row.res)
proc getRow*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): Row {.tags: [FReadDB].} =
## retrieves a single row. If the query doesn't return any rows, this proc