Merge pull request #2866 from nanoant/patch/db-deffered-rows
db: InstantRow and instantRows
This commit is contained in:
commit
f3e7e5fc13
3 changed files with 71 additions and 1 deletions
|
|
@ -16,6 +16,9 @@ type
|
||||||
DbConn* = PMySQL ## encapsulates a database connection
|
DbConn* = PMySQL ## encapsulates a database connection
|
||||||
Row* = seq[string] ## a row of a dataset. NULL database values will be
|
Row* = seq[string] ## a row of a dataset. NULL database values will be
|
||||||
## transformed always to the empty string.
|
## transformed always to the empty string.
|
||||||
|
InstantRow* = tuple[row: cstringArray, len: int] ## 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
|
EDb* = object of IOError ## exception that is raised if a database error occurs
|
||||||
|
|
||||||
SqlQuery* = distinct string ## an SQL query string
|
SqlQuery* = distinct string ## an SQL query string
|
||||||
|
|
@ -127,6 +130,30 @@ iterator fastRows*(db: DbConn, query: SqlQuery,
|
||||||
yield result
|
yield result
|
||||||
properFreeResult(sqlres, row)
|
properFreeResult(sqlres, row)
|
||||||
|
|
||||||
|
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.
|
||||||
|
rawExec(db, query, args)
|
||||||
|
var sqlres = mysql.useResult(db)
|
||||||
|
if sqlres != nil:
|
||||||
|
let L = int(mysql.numFields(sqlres))
|
||||||
|
var row: cstringArray
|
||||||
|
while true:
|
||||||
|
row = mysql.fetchRow(sqlres)
|
||||||
|
if row == nil: break
|
||||||
|
yield (row: row, len: L)
|
||||||
|
properFreeResult(sqlres, row)
|
||||||
|
|
||||||
|
proc `[]`*(row: InstantRow, col: int): string {.inline.} =
|
||||||
|
## returns text for given column of the row
|
||||||
|
$row.row[col]
|
||||||
|
|
||||||
|
proc len*(row: InstantRow): int {.inline.} =
|
||||||
|
## returns number of columns in the row
|
||||||
|
row.len
|
||||||
|
|
||||||
proc getRow*(db: DbConn, query: SqlQuery,
|
proc getRow*(db: DbConn, query: SqlQuery,
|
||||||
args: varargs[string, `$`]): Row {.tags: [FReadDB].} =
|
args: varargs[string, `$`]): Row {.tags: [FReadDB].} =
|
||||||
## retrieves a single row. If the query doesn't return any rows, this proc
|
## retrieves a single row. If the query doesn't return any rows, this proc
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,9 @@ type
|
||||||
DbConn* = PPGconn ## encapsulates a database connection
|
DbConn* = PPGconn ## encapsulates a database connection
|
||||||
Row* = seq[string] ## a row of a dataset. NULL database values will be
|
Row* = seq[string] ## a row of a dataset. NULL database values will be
|
||||||
## transformed always to the empty string.
|
## 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
|
EDb* = object of IOError ## exception that is raised if a database error occurs
|
||||||
|
|
||||||
SqlQuery* = distinct string ## an SQL query string
|
SqlQuery* = distinct string ## an SQL query string
|
||||||
|
|
@ -159,6 +162,24 @@ iterator fastRows*(db: DbConn, stmtName: SqlPrepared,
|
||||||
yield result
|
yield result
|
||||||
pqClear(res)
|
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,
|
proc getRow*(db: DbConn, query: SqlQuery,
|
||||||
args: varargs[string, `$`]): Row {.tags: [FReadDB].} =
|
args: varargs[string, `$`]): Row {.tags: [FReadDB].} =
|
||||||
## retrieves a single row. If the query doesn't return any rows, this proc
|
## retrieves a single row. If the query doesn't return any rows, this proc
|
||||||
|
|
|
||||||
|
|
@ -16,6 +16,8 @@ type
|
||||||
DbConn* = PSqlite3 ## encapsulates a database connection
|
DbConn* = PSqlite3 ## encapsulates a database connection
|
||||||
Row* = seq[string] ## a row of a dataset. NULL database values will be
|
Row* = seq[string] ## a row of a dataset. NULL database values will be
|
||||||
## transformed always to the empty string.
|
## transformed always to the empty string.
|
||||||
|
InstantRow* = Pstmt ## 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
|
EDb* = object of IOError ## exception that is raised if a database error occurs
|
||||||
|
|
||||||
SqlQuery* = distinct string ## an SQL query string
|
SqlQuery* = distinct string ## an SQL query string
|
||||||
|
|
@ -109,6 +111,24 @@ iterator fastRows*(db: DbConn, query: SqlQuery,
|
||||||
yield result
|
yield result
|
||||||
if finalize(stmt) != SQLITE_OK: dbError(db)
|
if finalize(stmt) != SQLITE_OK: dbError(db)
|
||||||
|
|
||||||
|
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 stmt = setupQuery(db, query, args)
|
||||||
|
while step(stmt) == SQLITE_ROW:
|
||||||
|
yield stmt
|
||||||
|
if finalize(stmt) != SQLITE_OK: dbError(db)
|
||||||
|
|
||||||
|
proc `[]`*(row: InstantRow, col: int32): string {.inline.} =
|
||||||
|
## returns text for given column of the row
|
||||||
|
$column_text(row, col)
|
||||||
|
|
||||||
|
proc len*(row: InstantRow): int32 {.inline.} =
|
||||||
|
## returns number of columns in the row
|
||||||
|
column_count(row)
|
||||||
|
|
||||||
proc getRow*(db: DbConn, query: SqlQuery,
|
proc getRow*(db: DbConn, query: SqlQuery,
|
||||||
args: varargs[string, `$`]): Row {.tags: [FReadDb].} =
|
args: varargs[string, `$`]): Row {.tags: [FReadDb].} =
|
||||||
## retrieves a single row. If the query doesn't return any rows, this proc
|
## retrieves a single row. If the query doesn't return any rows, this proc
|
||||||
|
|
@ -216,5 +236,7 @@ when not defined(testing) and isMainModule:
|
||||||
#db.query("insert into tbl1 values('goodbye', 20)")
|
#db.query("insert into tbl1 values('goodbye', 20)")
|
||||||
for r in db.rows(sql"select * from tbl1", []):
|
for r in db.rows(sql"select * from tbl1", []):
|
||||||
echo(r[0], r[1])
|
echo(r[0], r[1])
|
||||||
|
for r in db.instantRows(sql"select * from tbl1", []):
|
||||||
|
echo(r[0], r[1])
|
||||||
|
|
||||||
db_sqlite.close(db)
|
db_sqlite.close(db)
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue