diff options
author | Araq <rumpf_a@web.de> | 2016-01-18 14:54:50 +0100 |
---|---|---|
committer | Araq <rumpf_a@web.de> | 2016-01-18 14:54:50 +0100 |
commit | a114b3251906e14d0c6dce536f82a83a958c5806 (patch) | |
tree | 9c627c554ff3175db944e1847a3db18b0fc07149 | |
parent | 7ee1847137963431d2980bb9e030dbce6c2a8506 (diff) | |
parent | 6ca9e5cbcc940ad86045884840770415d1759f56 (diff) | |
download | Nim-a114b3251906e14d0c6dce536f82a83a958c5806.tar.gz |
Merge branch 'devel' of https://github.com/nim-lang/Nim into devel
-rw-r--r-- | lib/impure/db_mysql.nim | 44 | ||||
-rw-r--r-- | lib/impure/db_odbc.nim | 48 | ||||
-rw-r--r-- | lib/impure/db_postgres.nim | 18 | ||||
-rw-r--r-- | lib/impure/db_sqlite.nim | 43 | ||||
-rw-r--r-- | lib/pure/collections/tables.nim | 14 | ||||
-rw-r--r-- | tests/untestable/tpostgres.nim | 69 |
6 files changed, 227 insertions, 9 deletions
diff --git a/lib/impure/db_mysql.nim b/lib/impure/db_mysql.nim index 170fee8b8..1b7f1de61 100644 --- a/lib/impure/db_mysql.nim +++ b/lib/impure/db_mysql.nim @@ -10,7 +10,49 @@ ## A higher level `mySQL`:idx: database wrapper. The same interface is ## implemented for other databases too. ## -## Example: +## See also: `db_odbc <db_odbc.html>`_, `db_sqlite <db_sqlite.html>`_, +## `db_postgres <db_postgres.html>`_. +## +## Parameter substitution +## ---------------------- +## +## All ``db_*`` modules support the same form of parameter substitution. +## That is, using the ``?`` (question mark) to signify the place where a +## value should be placed. For example: +## +## .. code-block:: Nim +## sql"INSERT INTO myTable (colA, colB, colC) VALUES (?, ?, ?)" +## +## +## Examples +## -------- +## +## Opening a connection to a database +## ================================== +## +## .. code-block:: Nim +## import db_mysql +## let db = open("localhost", "user", "password", "dbname") +## db.close() +## +## Creating a table +## ================ +## +## .. code-block:: Nim +## db.exec(sql"DROP TABLE IF EXISTS myTable") +## db.exec(sql("""CREATE TABLE myTable ( +## id integer, +## name varchar(50) not null)""")) +## +## Inserting data +## ============== +## +## .. code-block:: Nim +## db.exec(sql"INSERT INTO myTable (id, name) VALUES (0, ?)", +## "Dominik") +## +## Larger example +## ============== ## ## .. code-block:: Nim ## diff --git a/lib/impure/db_odbc.nim b/lib/impure/db_odbc.nim index 6af69d842..4f0b0469d 100644 --- a/lib/impure/db_odbc.nim +++ b/lib/impure/db_odbc.nim @@ -11,12 +11,54 @@ ## ## This is the same interface that is implemented for other databases. ## -## This has NOT yet been (extensively) tested agains ODBC drivers for -## Teradata, Oracle, Sybase, MSSqlvSvr, et. al. databases +## This has NOT yet been (extensively) tested against ODBC drivers for +## Teradata, Oracle, Sybase, MSSqlvSvr, et. al. databases. ## ## Currently all queries are ANSI calls, not Unicode. ## -## Example: +## See also: `db_postgres <db_postgres.html>`_, `db_sqlite <db_sqlite.html>`_, +## `db_mysql <db_mysql.html>`_. +## +## Parameter substitution +## ---------------------- +## +## All ``db_*`` modules support the same form of parameter substitution. +## That is, using the ``?`` (question mark) to signify the place where a +## value should be placed. For example: +## +## .. code-block:: Nim +## sql"INSERT INTO myTable (colA, colB, colC) VALUES (?, ?, ?)" +## +## +## Examples +## -------- +## +## Opening a connection to a database +## ================================== +## +## .. code-block:: Nim +## import db_odbc +## let db = open("localhost", "user", "password", "dbname") +## db.close() +## +## Creating a table +## ================ +## +## .. code-block:: Nim +## db.exec(sql"DROP TABLE IF EXISTS myTable") +## db.exec(sql("""CREATE TABLE myTable ( +## id integer, +## name varchar(50) not null)""")) +## +## Inserting data +## ============== +## +## .. code-block:: Nim +## db.exec(sql"INSERT INTO myTable (id, name) VALUES (0, ?)", +## "Andreas") +## +## Large example +## ============= ## ## .. code-block:: Nim ## diff --git a/lib/impure/db_postgres.nim b/lib/impure/db_postgres.nim index 9bdbae4c2..60bd1f081 100644 --- a/lib/impure/db_postgres.nim +++ b/lib/impure/db_postgres.nim @@ -10,6 +10,9 @@ ## A higher level `PostgreSQL`:idx: database wrapper. This interface ## is implemented for other databases also. ## +## See also: `db_odbc <db_odbc.html>`_, `db_sqlite <db_sqlite.html>`_, +## `db_mysql <db_mysql.html>`_. +## ## Parameter substitution ## ---------------------- ## @@ -27,7 +30,7 @@ ## ## 2. ``SqlPrepared`` using ``$1, $2, $3, ...`` ## -## .. code-block:: Nim +## .. code-block:: Nim ## prepare(db, "myExampleInsert", ## sql"""INSERT INTO myTable ## (colA, colB, colC) @@ -162,8 +165,10 @@ proc setupQuery(db: DbConn, stmtName: SqlPrepared, proc prepare*(db: DbConn; stmtName: string, query: SqlQuery; nParams: int): SqlPrepared = + ## Creates a new ``SqlPrepared`` statement. Parameter substitution is done + ## via ``$1``, ``$2``, ``$3``, etc. if nParams > 0 and not string(query).contains("$1"): - dbError("""parameter substitution expects "$1" """) + dbError("parameter substitution expects \"$1\"") var res = pqprepare(db, stmtName, query.string, int32(nParams), nil) if pqResultStatus(res) != PGRES_COMMAND_OK: dbError(db) return SqlPrepared(stmtName) @@ -282,6 +287,15 @@ proc getValue*(db: DbConn, query: SqlQuery, var x = pqgetvalue(setupQuery(db, query, args), 0, 0) result = if isNil(x): "" else: $x +proc getValue*(db: DbConn, stmtName: SqlPrepared, + args: varargs[string, `$`]): string {. + tags: [ReadDbEffect].} = + ## 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. + var x = pqgetvalue(setupQuery(db, stmtName, args), 0, 0) + result = if isNil(x): "" else: $x + proc tryInsertID*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): int64 {. tags: [WriteDbEffect].}= diff --git a/lib/impure/db_sqlite.nim b/lib/impure/db_sqlite.nim index c0d221a0d..1633d48f7 100644 --- a/lib/impure/db_sqlite.nim +++ b/lib/impure/db_sqlite.nim @@ -10,7 +10,48 @@ ## A higher level `SQLite`:idx: database wrapper. This interface ## is implemented for other databases too. ## -## Example: +## See also: `db_odbc <db_odbc.html>`_, `db_postgres <db_postgres.html>`_, +## `db_mysql <db_mysql.html>`_. +## +## Parameter substitution +## ---------------------- +## +## All ``db_*`` modules support the same form of parameter substitution. +## That is, using the ``?`` (question mark) to signify the place where a +## value should be placed. For example: +## +## .. code-block:: Nim +## sql"INSERT INTO myTable (colA, colB, colC) VALUES (?, ?, ?)" +## +## Examples +## -------- +## +## Opening a connection to a database +## ================================== +## +## .. code-block:: Nim +## import db_sqlite +## let db = open("localhost", "user", "password", "dbname") +## db.close() +## +## Creating a table +## ================ +## +## .. code-block:: Nim +## db.exec(sql"DROP TABLE IF EXISTS myTable") +## db.exec(sql("""CREATE TABLE myTable ( +## id integer, +## name varchar(50) not null)""")) +## +## Inserting data +## ============== +## +## .. code-block:: Nim +## db.exec(sql"INSERT INTO myTable (id, name) VALUES (0, ?)", +## "Jack") +## +## Larger example +## ============== ## ## .. code-block:: nim ## diff --git a/lib/pure/collections/tables.nim b/lib/pure/collections/tables.nim index 329b2a1cb..2ed0d2034 100644 --- a/lib/pure/collections/tables.nim +++ b/lib/pure/collections/tables.nim @@ -887,7 +887,7 @@ proc mget*[A](t: CountTableRef[A], key: A): var int {.deprecated.} = result = t[][key] proc getOrDefault*[A](t: CountTableRef[A], key: A): int = - getOrDefaultImpl(t, key) + result = t[].getOrDefault(key) proc hasKey*[A](t: CountTableRef[A], key: A): bool = ## returns true iff `key` is in the table `t`. @@ -1028,3 +1028,15 @@ when isMainModule: assert(merged["foo"] == 5) assert(merged["bar"] == 3) assert(merged["baz"] == 14) + + block: + const testKey = "TESTKEY" + let t: CountTableRef[string] = newCountTable[string]() + + # Before, does not compile with error message: + #test_counttable.nim(7, 43) template/generic instantiation from here + #lib/pure/collections/tables.nim(117, 21) template/generic instantiation from here + #lib/pure/collections/tableimpl.nim(32, 27) Error: undeclared field: 'hcode + doAssert 0 == t.getOrDefault(testKey) + t.inc(testKey,3) + doAssert 3 == t.getOrDefault(testKey) diff --git a/tests/untestable/tpostgres.nim b/tests/untestable/tpostgres.nim index 81fe8bf51..dcbdaad39 100644 --- a/tests/untestable/tpostgres.nim +++ b/tests/untestable/tpostgres.nim @@ -1,4 +1,5 @@ -import db_postgres +import db_postgres, strutils + let db = open("localhost", "dom", "", "test") db.exec(sql"DROP TABLE IF EXISTS myTable") @@ -12,4 +13,70 @@ doAssert db.getValue(sql"SELECT name FROM myTable") == name # Check issue #3513 doAssert db.getValue(sql"SELECT name FROM myTable") == name + +# issue #3560 +proc addToDb(conn: DbConn, fileId: int, fileName: string): int64 = + result = conn.insertId(sql("INSERT into files (id, filename) VALUES (?, ?)"), fileId, fileName) + +db.exec(sql"DROP TABLE IF EXISTS files") +db.exec(sql"DROP TABLE IF EXISTS fileobjects") +db.exec(sql("""CREATE TABLE FILEOBJECTS( + ID SERIAL PRIMARY KEY, + FILE_SIZE INT, + MD5 CHAR(32) NOT NULL UNIQUE + );""")) + +db.exec(sql("""CREATE TABLE FILES( + ID SERIAL PRIMARY KEY, + OBJECT_ID INT, + FILENAME TEXT NOT NULL, + URI TEXT, + SCHEME CHAR(10), + PUBLIC BOOLEAN DEFAULT FALSE, + CONSTRAINT fk1_fileobjs FOREIGN KEY (object_id) + REFERENCES fileobjects (id) MATCH SIMPLE + ON DELETE CASCADE + );""")) + +let f1 = db.addToDb(1, "hello.tmp") +doAssert f1 == 1 +let f2 = db.addToDb(2, "hello2.tmp") +doAssert f2 == 2 + +# PreparedStmt vs. normal query +try: + echo db.getValue(sql("select * from files where id = $1"), 1) + doAssert false, "Exception expected" +except DbError: + let msg = getCurrentExceptionMsg().normalize + doAssert "expects" in msg + doAssert "?" in msg + doAssert "parameter substitution" in msg + +doAssert db.getValue(sql("select filename from files where id = ?"), 1) == "hello.tmp" + +var first = prepare(db, "one", sql"select filename from files where id = $1", 1) +doAssert db.getValue(first, 1) == "hello.tmp" + +try: + var second = prepare(db, "two", sql"select filename from files where id = ?", 1) + doAssert false, "Exception expected" +except: + let msg = getCurrentExceptionMsg().normalize + doAssert "expects" in msg + doAssert "$1" in msg + doAssert "parameter substitution" in msg + +# issue #3569 +db.exec(SqlQuery("DROP TABLE IF EXISTS tags")) +db.exec(SqlQuery("CREATE TABLE tags(id serial UNIQUE, name varchar(255))")) + +for i in 1..10: + var name = "t" & $i + echo(name) + discard db.getRow( + SqlQuery("INSERT INTO tags(name) VALUES(\'$1\') RETURNING id" % [name])) + +echo("All tests succeeded!") + db.close() |