This commit is contained in:
Andreas Rumpf 2018-02-10 16:41:38 +01:00
commit 94141b8f68
2 changed files with 23 additions and 20 deletions

View file

@ -249,3 +249,5 @@ bar()
``` ```
- The ``securehash`` module is now deprecated. Instead import ``std / sha1``. - The ``securehash`` module is now deprecated. Instead import ``std / sha1``.
- ``db_mysql`` module: ``DbConn`` is now a ``distinct`` type that doesn't expose the
details of the underlying ``PMySQL`` type.

View file

@ -89,7 +89,7 @@ import db_common
export db_common export db_common
type type
DbConn* = PMySQL ## encapsulates a database connection DbConn* = distinct 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
## converted to nil. ## converted to nil.
InstantRow* = object ## a handle that can be used to get a row's InstantRow* = object ## a handle that can be used to get a row's
@ -102,7 +102,7 @@ proc dbError*(db: DbConn) {.noreturn.} =
## raises a DbError exception. ## raises a DbError exception.
var e: ref DbError var e: ref DbError
new(e) new(e)
e.msg = $mysql.error(db) e.msg = $mysql.error(PMySQL db)
raise e raise e
when false: when false:
@ -140,17 +140,17 @@ proc tryExec*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): bool {.
tags: [ReadDbEffect, WriteDbEffect].} = tags: [ReadDbEffect, WriteDbEffect].} =
## tries to execute the query and returns true if successful, false otherwise. ## tries to execute the query and returns true if successful, false otherwise.
var q = dbFormat(query, args) var q = dbFormat(query, args)
return mysql.realQuery(db, q, q.len) == 0'i32 return mysql.realQuery(PMySQL db, q, q.len) == 0'i32
proc rawExec(db: DbConn, query: SqlQuery, args: varargs[string, `$`]) = proc rawExec(db: DbConn, query: SqlQuery, args: varargs[string, `$`]) =
var q = dbFormat(query, args) var q = dbFormat(query, args)
if mysql.realQuery(db, q, q.len) != 0'i32: dbError(db) if mysql.realQuery(PMySQL db, q, q.len) != 0'i32: dbError(db)
proc exec*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]) {. proc exec*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]) {.
tags: [ReadDbEffect, WriteDbEffect].} = tags: [ReadDbEffect, WriteDbEffect].} =
## executes the query and raises EDB if not successful. ## executes the query and raises EDB if not successful.
var q = dbFormat(query, args) var q = dbFormat(query, args)
if mysql.realQuery(db, q, q.len) != 0'i32: dbError(db) if mysql.realQuery(PMySQL db, q, q.len) != 0'i32: dbError(db)
proc newRow(L: int): Row = proc newRow(L: int): Row =
newSeq(result, L) newSeq(result, L)
@ -171,7 +171,7 @@ iterator fastRows*(db: DbConn, query: SqlQuery,
## Breaking the fastRows() iterator during a loop will cause the next ## Breaking the fastRows() iterator during a loop will cause the next
## database query to raise an [EDb] exception ``Commands out of sync``. ## database query to raise an [EDb] exception ``Commands out of sync``.
rawExec(db, query, args) rawExec(db, query, args)
var sqlres = mysql.useResult(db) var sqlres = mysql.useResult(PMySQL db)
if sqlres != nil: if sqlres != nil:
var var
L = int(mysql.numFields(sqlres)) L = int(mysql.numFields(sqlres))
@ -210,7 +210,7 @@ iterator instantRows*(db: DbConn, query: SqlQuery,
## Same as fastRows but returns a handle that can be used to get column text ## Same as fastRows but returns a handle that can be used to get column text
## on demand using []. Returned handle is valid only within the iterator body. ## on demand using []. Returned handle is valid only within the iterator body.
rawExec(db, query, args) rawExec(db, query, args)
var sqlres = mysql.useResult(db) var sqlres = mysql.useResult(PMySQL db)
if sqlres != nil: if sqlres != nil:
let L = int(mysql.numFields(sqlres)) let L = int(mysql.numFields(sqlres))
var row: cstringArray var row: cstringArray
@ -290,7 +290,7 @@ iterator instantRows*(db: DbConn; columns: var DbColumns; query: SqlQuery;
## Same as fastRows but returns a handle that can be used to get column text ## Same as fastRows but returns a handle that can be used to get column text
## on demand using []. Returned handle is valid only within the iterator body. ## on demand using []. Returned handle is valid only within the iterator body.
rawExec(db, query, args) rawExec(db, query, args)
var sqlres = mysql.useResult(db) var sqlres = mysql.useResult(PMySQL db)
if sqlres != nil: if sqlres != nil:
let L = int(mysql.numFields(sqlres)) let L = int(mysql.numFields(sqlres))
setColumnInfo(columns, sqlres, L) setColumnInfo(columns, sqlres, L)
@ -315,7 +315,7 @@ proc getRow*(db: DbConn, query: SqlQuery,
## 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
## will return a Row with empty strings for each column. ## will return a Row with empty strings for each column.
rawExec(db, query, args) rawExec(db, query, args)
var sqlres = mysql.useResult(db) var sqlres = mysql.useResult(PMySQL db)
if sqlres != nil: if sqlres != nil:
var L = int(mysql.numFields(sqlres)) var L = int(mysql.numFields(sqlres))
result = newRow(L) result = newRow(L)
@ -334,7 +334,7 @@ proc getAllRows*(db: DbConn, query: SqlQuery,
## executes the query and returns the whole result dataset. ## executes the query and returns the whole result dataset.
result = @[] result = @[]
rawExec(db, query, args) rawExec(db, query, args)
var sqlres = mysql.useResult(db) var sqlres = mysql.useResult(PMySQL db)
if sqlres != nil: if sqlres != nil:
var L = int(mysql.numFields(sqlres)) var L = int(mysql.numFields(sqlres))
var row: cstringArray var row: cstringArray
@ -369,10 +369,10 @@ proc tryInsertId*(db: DbConn, query: SqlQuery,
## executes the query (typically "INSERT") and returns the ## executes the query (typically "INSERT") and returns the
## generated ID for the row or -1 in case of an error. ## generated ID for the row or -1 in case of an error.
var q = dbFormat(query, args) var q = dbFormat(query, args)
if mysql.realQuery(db, q, q.len) != 0'i32: if mysql.realQuery(PMySQL db, q, q.len) != 0'i32:
result = -1'i64 result = -1'i64
else: else:
result = mysql.insertId(db) result = mysql.insertId(PMySQL db)
proc insertId*(db: DbConn, query: SqlQuery, proc insertId*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): int64 {.tags: [WriteDbEffect].} = args: varargs[string, `$`]): int64 {.tags: [WriteDbEffect].} =
@ -387,32 +387,33 @@ proc execAffectedRows*(db: DbConn, query: SqlQuery,
## runs the query (typically "UPDATE") and returns the ## runs the query (typically "UPDATE") and returns the
## number of affected rows ## number of affected rows
rawExec(db, query, args) rawExec(db, query, args)
result = mysql.affectedRows(db) result = mysql.affectedRows(PMySQL db)
proc close*(db: DbConn) {.tags: [DbEffect].} = proc close*(db: DbConn) {.tags: [DbEffect].} =
## closes the database connection. ## closes the database connection.
if db != nil: mysql.close(db) if PMySQL(db) != nil: mysql.close(PMySQL db)
proc open*(connection, user, password, database: string): DbConn {. proc open*(connection, user, password, database: string): DbConn {.
tags: [DbEffect].} = tags: [DbEffect].} =
## opens a database connection. Raises `EDb` if the connection could not ## opens a database connection. Raises `EDb` if the connection could not
## be established. ## be established.
result = mysql.init(nil) var res = mysql.init(nil)
if result == nil: dbError("could not open database connection") if res == nil: dbError("could not open database connection")
let let
colonPos = connection.find(':') colonPos = connection.find(':')
host = if colonPos < 0: connection host = if colonPos < 0: connection
else: substr(connection, 0, colonPos-1) else: substr(connection, 0, colonPos-1)
port: int32 = if colonPos < 0: 0'i32 port: int32 = if colonPos < 0: 0'i32
else: substr(connection, colonPos+1).parseInt.int32 else: substr(connection, colonPos+1).parseInt.int32
if mysql.realConnect(result, host, user, password, database, if mysql.realConnect(res, host, user, password, database,
port, nil, 0) == nil: port, nil, 0) == nil:
var errmsg = $mysql.error(result) var errmsg = $mysql.error(res)
db_mysql.close(result) mysql.close(res)
dbError(errmsg) dbError(errmsg)
result = DbConn(res)
proc setEncoding*(connection: DbConn, encoding: string): bool {. proc setEncoding*(connection: DbConn, encoding: string): bool {.
tags: [DbEffect].} = tags: [DbEffect].} =
## sets the encoding of a database connection, returns true for ## sets the encoding of a database connection, returns true for
## success, false for failure. ## success, false for failure.
result = mysql.set_character_set(connection, encoding) == 0 result = mysql.set_character_set(PMySQL connection, encoding) == 0