mirror of https://github.com/waku-org/nwaku.git
106 lines
2.6 KiB
Nim
106 lines
2.6 KiB
Nim
|
when (NimMajor, NimMinor) < (1, 4):
|
||
|
{.push raises: [Defect,DbError].}
|
||
|
else:
|
||
|
{.push raises: [ValueError,DbError].}
|
||
|
|
||
|
import
|
||
|
stew/results,
|
||
|
chronos
|
||
|
|
||
|
include db_postgres
|
||
|
|
||
|
## Connection management
|
||
|
|
||
|
proc check*(db: DbConn): Result[void, string] =
|
||
|
|
||
|
var message: string
|
||
|
try:
|
||
|
message = $db.pqErrorMessage()
|
||
|
except ValueError,DbError:
|
||
|
return err("exception in check: " & getCurrentExceptionMsg())
|
||
|
|
||
|
if message.len > 0:
|
||
|
return err($message)
|
||
|
|
||
|
return ok()
|
||
|
|
||
|
proc open*(connString: string):
|
||
|
Result[DbConn, string] =
|
||
|
## Opens a new connection.
|
||
|
var conn: DbConn = nil
|
||
|
try:
|
||
|
conn = open("","", "", connString)
|
||
|
except DbError:
|
||
|
return err("exception opening new connection: " &
|
||
|
getCurrentExceptionMsg())
|
||
|
|
||
|
if conn.status != CONNECTION_OK:
|
||
|
let checkRes = conn.check()
|
||
|
if checkRes.isErr():
|
||
|
return err("failed to connect to database: " & checkRes.error)
|
||
|
|
||
|
return err("unknown reason")
|
||
|
|
||
|
ok(conn)
|
||
|
|
||
|
proc rows*(db: DbConn,
|
||
|
query: SqlQuery,
|
||
|
args: seq[string]):
|
||
|
Future[Result[seq[Row], string]] {.async.} =
|
||
|
## Runs the SQL getting results.
|
||
|
|
||
|
if db.status != CONNECTION_OK:
|
||
|
let checkRes = db.check()
|
||
|
if checkRes.isErr():
|
||
|
return err("failed to connect to database: " & checkRes.error)
|
||
|
|
||
|
return err("unknown reason")
|
||
|
|
||
|
var wellFormedQuery = ""
|
||
|
try:
|
||
|
wellFormedQuery = dbFormat(query, args)
|
||
|
except DbError:
|
||
|
return err("exception formatting the query: " &
|
||
|
getCurrentExceptionMsg())
|
||
|
|
||
|
let success = db.pqsendQuery(cstring(wellFormedQuery))
|
||
|
if success != 1:
|
||
|
let checkRes = db.check()
|
||
|
if checkRes.isErr():
|
||
|
return err("failed pqsendQuery: " & checkRes.error)
|
||
|
|
||
|
return err("failed pqsendQuery: unknown reason")
|
||
|
|
||
|
var ret = newSeq[Row](0)
|
||
|
|
||
|
while true:
|
||
|
|
||
|
let success = db.pqconsumeInput()
|
||
|
if success != 1:
|
||
|
let checkRes = db.check()
|
||
|
if checkRes.isErr():
|
||
|
return err("failed pqconsumeInput: " & checkRes.error)
|
||
|
|
||
|
return err("failed pqconsumeInput: unknown reason")
|
||
|
|
||
|
if db.pqisBusy() == 1:
|
||
|
await sleepAsync(0.milliseconds) # Do not block the async runtime
|
||
|
continue
|
||
|
|
||
|
var pqResult = db.pqgetResult()
|
||
|
if pqResult == nil:
|
||
|
# Check if its a real error or just end of results
|
||
|
let checkRes = db.check()
|
||
|
if checkRes.isErr():
|
||
|
return err("error in rows: " & checkRes.error)
|
||
|
|
||
|
return ok(ret) # reached the end of the results
|
||
|
|
||
|
var cols = pqResult.pqnfields()
|
||
|
var row = cols.newRow()
|
||
|
for i in 0'i32 .. pqResult.pqNtuples() - 1:
|
||
|
pqResult.setRow(row, i, cols) # puts the value in the row
|
||
|
ret.add(row)
|
||
|
|
||
|
pqclear(pqResult)
|