From da2d0845b8d4725888a58aaf0741d9227a380f3b Mon Sep 17 00:00:00 2001 From: JamesP Date: Sat, 29 Aug 2015 07:50:14 +1000 Subject: [PATCH 1/5] lib/impure/db_mysql add example code-block --- lib/impure/db_mysql.nim | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/lib/impure/db_mysql.nim b/lib/impure/db_mysql.nim index 197286f29a..34537c7f7a 100644 --- a/lib/impure/db_mysql.nim +++ b/lib/impure/db_mysql.nim @@ -9,6 +9,37 @@ ## A higher level `mySQL`:idx: database wrapper. The same interface is ## implemented for other databases too. +## +## Example: +## +## .. code-block:: Nim +## +## import db_mysql, math +## +## let theDb = open("localhost", "nim", "nim", "test") +## +## theDb.exec(sql"Drop table if exists myTestTbl") +## theDb.exec(sql("create table myTestTbl (" & +## " Id INT(11) NOT NULL AUTO_INCREMENT PRIMARY KEY, " & +## " Name VARCHAR(50) NOT NULL, " & +## " i INT(11), " & +## " f DECIMAL(18,10))")) +## +## theDb.exec(sql"START TRANSACTION") +## for i in 1..1000: +## theDb.exec(sql"INSERT INTO myTestTbl (name,i,f) VALUES (?,?,?)", +## "Item#" & $i, i, sqrt(i.float)) +## theDb.exec(sql"COMMIT") +## +## for x in theDb.fastRows(sql"select * from myTestTbl"): +## echo x +## +## let id = theDb.tryInsertId(sql"INSERT INTO myTestTbl (name,i,f) VALUES (?,?,?)", +## "Item#1001", 1001, sqrt(1001.0)) +## echo "Inserted item: ", theDb.getValue(sql"SELECT name FROM myTestTbl WHERE id=?", id) +## +## theDb.close() + import strutils, mysql From 5b11ce27c4aedea27a84142df3022028a5249494 Mon Sep 17 00:00:00 2001 From: JamesP Date: Sat, 5 Sep 2015 11:47:28 +1000 Subject: [PATCH 2/5] fastRows iterator doco updated to clarify what happens when break a fastRows loop --- lib/impure/db_mysql.nim | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/lib/impure/db_mysql.nim b/lib/impure/db_mysql.nim index 34537c7f7a..fc6df72cc0 100644 --- a/lib/impure/db_mysql.nim +++ b/lib/impure/db_mysql.nim @@ -140,9 +140,13 @@ proc properFreeResult(sqlres: mysql.PRES, row: cstringArray) = iterator fastRows*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): Row {.tags: [FReadDB].} = - ## executes the query and iterates over the result dataset. This is very - ## fast, but potenially dangerous: If the for-loop-body executes another - ## query, the results can be undefined. For MySQL this is the case!. + ## executes the query and iterates over the result dataset. + ## + ## This is very fast, but potenially dangerous. Use this iterator only + ## if you require ALL the rows. + ## + ## Breaking the fastRows() iterator during a loop will cause the next + ## database query to raise an [EDb] exception ``Commands out of sync``. rawExec(db, query, args) var sqlres = mysql.useResult(db) if sqlres != nil: From d02d1219b0c5157d6e56a09e9bf82cc03d73229b Mon Sep 17 00:00:00 2001 From: JamesP Date: Sat, 5 Sep 2015 11:48:47 +1000 Subject: [PATCH 3/5] instantRows doco updated with "the" to improve readability --- lib/impure/db_mysql.nim | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/impure/db_mysql.nim b/lib/impure/db_mysql.nim index fc6df72cc0..3d92743516 100644 --- a/lib/impure/db_mysql.nim +++ b/lib/impure/db_mysql.nim @@ -169,7 +169,7 @@ 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. + ## on demand using []. Returned handle is valid only within the interator body. rawExec(db, query, args) var sqlres = mysql.useResult(db) if sqlres != nil: From 22d56fc494519769724fa4301f5d17d77c9a43e4 Mon Sep 17 00:00:00 2001 From: JamesP Date: Sat, 5 Sep 2015 11:49:25 +1000 Subject: [PATCH 4/5] Cleanup of line endings --- lib/impure/db_mysql.nim | 68 ++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/lib/impure/db_mysql.nim b/lib/impure/db_mysql.nim index 3d92743516..9a03f97836 100644 --- a/lib/impure/db_mysql.nim +++ b/lib/impure/db_mysql.nim @@ -7,7 +7,7 @@ # distribution, for details about the copyright. # -## A higher level `mySQL`:idx: database wrapper. The same interface is +## A higher level `mySQL`:idx: database wrapper. The same interface is ## implemented for other databases too. ## ## Example: @@ -60,22 +60,22 @@ type {.deprecated: [TRow: Row, TSqlQuery: SqlQuery, TDbConn: DbConn].} proc sql*(query: string): SqlQuery {.noSideEffect, inline.} = - ## constructs a SqlQuery from the string `query`. This is supposed to be + ## constructs a SqlQuery from the string `query`. This is supposed to be ## used as a raw-string-literal modifier: ## ``sql"update user set counter = counter + 1"`` ## - ## If assertions are turned off, it does nothing. If assertions are turned + ## If assertions are turned off, it does nothing. If assertions are turned ## on, later versions will check the string for valid syntax. result = SqlQuery(query) -proc dbError(db: DbConn) {.noreturn.} = +proc dbError(db: DbConn) {.noreturn.} = ## raises an EDb exception. var e: ref EDb new(e) e.msg = $mysql.error(db) raise e -proc dbError*(msg: string) {.noreturn.} = +proc dbError*(msg: string) {.noreturn.} = ## raises an EDb exception with message `msg`. var e: ref EDb new(e) @@ -86,9 +86,9 @@ when false: proc dbQueryOpt*(db: DbConn, query: string, args: varargs[string, `$`]) = var stmt = mysql_stmt_init(db) if stmt == nil: dbError(db) - if mysql_stmt_prepare(stmt, query, len(query)) != 0: + if mysql_stmt_prepare(stmt, query, len(query)) != 0: dbError(db) - var + var binding: seq[MYSQL_BIND] discard mysql_stmt_close(stmt) @@ -110,9 +110,9 @@ proc dbFormat(formatstr: SqlQuery, args: varargs[string]): string = else: add(result, dbQuote(args[a])) inc(a) - else: + else: add(result, c) - + proc tryExec*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): bool {. tags: [FReadDB, FWriteDb].} = ## tries to execute the query and returns true if successful, false otherwise. @@ -128,16 +128,16 @@ proc exec*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]) {. ## executes the query and raises EDB if not successful. var q = dbFormat(query, args) if mysql.realQuery(db, q, q.len) != 0'i32: dbError(db) - -proc newRow(L: int): Row = + +proc newRow(L: int): Row = newSeq(result, L) for i in 0..L-1: result[i] = "" - -proc properFreeResult(sqlres: mysql.PRES, row: cstringArray) = + +proc properFreeResult(sqlres: mysql.PRES, row: cstringArray) = if row != nil: while mysql.fetchRow(sqlres) != nil: discard mysql.freeResult(sqlres) - + iterator fastRows*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): Row {.tags: [FReadDB].} = ## executes the query and iterates over the result dataset. @@ -156,7 +156,7 @@ iterator fastRows*(db: DbConn, query: SqlQuery, while true: row = mysql.fetchRow(sqlres) if row == nil: break - for i in 0..L-1: + for i in 0..L-1: setLen(result[i], 0) if row[i] == nil: result[i] = nil @@ -199,8 +199,8 @@ proc getRow*(db: DbConn, query: SqlQuery, var L = int(mysql.numFields(sqlres)) result = newRow(L) var row = mysql.fetchRow(sqlres) - if row != nil: - for i in 0..L-1: + if row != nil: + for i in 0..L-1: setLen(result[i], 0) if row[i] == nil: result[i] = nil @@ -208,7 +208,7 @@ proc getRow*(db: DbConn, query: SqlQuery, add(result[i], row[i]) properFreeResult(sqlres, row) -proc getAllRows*(db: DbConn, query: SqlQuery, +proc getAllRows*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): seq[Row] {.tags: [FReadDB].} = ## executes the query and returns the whole result dataset. result = @[] @@ -231,44 +231,44 @@ proc getAllRows*(db: DbConn, query: SqlQuery, inc(j) mysql.freeResult(sqlres) -iterator rows*(db: DbConn, query: SqlQuery, +iterator rows*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): Row {.tags: [FReadDB].} = ## same as `fastRows`, but slower and safe. for r in items(getAllRows(db, query, args)): yield r -proc getValue*(db: DbConn, query: SqlQuery, - args: varargs[string, `$`]): string {.tags: [FReadDB].} = +proc getValue*(db: DbConn, query: SqlQuery, + args: varargs[string, `$`]): string {.tags: [FReadDB].} = ## executes the query and returns the first column of the first row of the ## result dataset. Returns "" if the dataset contains no rows or the database ## value is NULL. result = getRow(db, query, args)[0] -proc tryInsertId*(db: DbConn, query: SqlQuery, +proc tryInsertId*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} = - ## 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. var q = dbFormat(query, args) - if mysql.realQuery(db, q, q.len) != 0'i32: + if mysql.realQuery(db, q, q.len) != 0'i32: result = -1'i64 else: result = mysql.insertId(db) - -proc insertId*(db: DbConn, query: SqlQuery, - args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} = - ## executes the query (typically "INSERT") and returns the + +proc insertId*(db: DbConn, query: SqlQuery, + args: varargs[string, `$`]): int64 {.tags: [FWriteDb].} = + ## executes the query (typically "INSERT") and returns the ## generated ID for the row. result = tryInsertID(db, query, args) if result < 0: dbError(db) -proc execAffectedRows*(db: DbConn, query: SqlQuery, +proc execAffectedRows*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): int64 {. - tags: [FReadDB, FWriteDb].} = + tags: [FReadDB, FWriteDb].} = ## runs the query (typically "UPDATE") and returns the ## number of affected rows rawExec(db, query, args) result = mysql.affectedRows(db) -proc close*(db: DbConn) {.tags: [FDb].} = +proc close*(db: DbConn) {.tags: [FDb].} = ## closes the database connection. if db != nil: mysql.close(db) @@ -277,14 +277,14 @@ proc open*(connection, user, password, database: string): DbConn {. ## opens a database connection. Raises `EDb` if the connection could not ## be established. result = mysql.init(nil) - if result == nil: dbError("could not open database connection") + if result == nil: dbError("could not open database connection") let colonPos = connection.find(':') host = if colonPos < 0: connection else: substr(connection, 0, colonPos-1) port: int32 = if colonPos < 0: 0'i32 else: substr(connection, colonPos+1).parseInt.int32 - if mysql.realConnect(result, host, user, password, database, + if mysql.realConnect(result, host, user, password, database, port, nil, 0) == nil: var errmsg = $mysql.error(result) db_mysql.close(result) @@ -292,6 +292,6 @@ proc open*(connection, user, password, database: string): DbConn {. proc setEncoding*(connection: DbConn, encoding: string): bool {. tags: [FDb].} = - ## sets the encoding of a database connection, returns true for + ## sets the encoding of a database connection, returns true for ## success, false for failure. result = mysql.set_character_set(connection, encoding) == 0 From d7c60e86b460b10aced436eae8816b45e284d49a Mon Sep 17 00:00:00 2001 From: Dominik Picheta Date: Sat, 5 Sep 2015 21:15:01 +0100 Subject: [PATCH 5/5] Bold emphasis and fix typo. --- lib/impure/db_mysql.nim | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/impure/db_mysql.nim b/lib/impure/db_mysql.nim index 9a03f97836..7f75112646 100644 --- a/lib/impure/db_mysql.nim +++ b/lib/impure/db_mysql.nim @@ -142,8 +142,8 @@ iterator fastRows*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): Row {.tags: [FReadDB].} = ## executes the query and iterates over the result dataset. ## - ## This is very fast, but potenially dangerous. Use this iterator only - ## if you require ALL the rows. + ## This is very fast, but potentially dangerous. Use this iterator only + ## if you require **ALL** the rows. ## ## Breaking the fastRows() iterator during a loop will cause the next ## database query to raise an [EDb] exception ``Commands out of sync``.