diff options
-rw-r--r-- | lib/impure/db_sqlite.nim | 15 | ||||
-rw-r--r-- | lib/std/private/dbutils.nim | 15 | ||||
-rw-r--r-- | tests/stdlib/tsqlitebindatas.nim | 28 |
3 files changed, 47 insertions, 11 deletions
diff --git a/lib/impure/db_sqlite.nim b/lib/impure/db_sqlite.nim index 7bd807a12..b600576df 100644 --- a/lib/impure/db_sqlite.nim +++ b/lib/impure/db_sqlite.nim @@ -171,7 +171,7 @@ import sqlite3, macros import db_common export db_common -import std/private/since +import std/private/[since, dbutils] type DbConn* = PSqlite3 ## Encapsulates a database connection. @@ -211,14 +211,7 @@ proc dbQuote*(s: string): string = add(result, '\'') proc dbFormat(formatstr: SqlQuery, args: varargs[string]): string = - result = "" - var a = 0 - for c in items(string(formatstr)): - if c == '?': - add(result, dbQuote(args[a])) - inc(a) - else: - add(result, c) + dbFormatImpl(formatstr, dbQuote, args) proc prepare*(db: DbConn; q: string): SqlPrepared {.since: (1, 3).} = ## Creates a new `SqlPrepared` statement. @@ -642,7 +635,7 @@ proc getValue*(db: DbConn, stmtName: SqlPrepared): string proc tryInsertID*(db: DbConn, query: SqlQuery, args: varargs[string, `$`]): int64 - {.tags: [WriteDbEffect], raises: [].} = + {.tags: [WriteDbEffect], raises: [DbError].} = ## Executes the query (typically "INSERT") and returns the ## generated ID for the row or -1 in case of an error. ## @@ -699,7 +692,7 @@ proc insertID*(db: DbConn, query: SqlQuery, proc tryInsert*(db: DbConn, query: SqlQuery, pkName: string, args: varargs[string, `$`]): int64 - {.tags: [WriteDbEffect], raises: [], since: (1, 3).} = + {.tags: [WriteDbEffect], raises: [DbError], since: (1, 3).} = ## same as tryInsertID tryInsertID(db, query, args) diff --git a/lib/std/private/dbutils.nim b/lib/std/private/dbutils.nim new file mode 100644 index 000000000..0ae3b3702 --- /dev/null +++ b/lib/std/private/dbutils.nim @@ -0,0 +1,15 @@ +import db_common + + +template dbFormatImpl*(formatstr: SqlQuery, dbQuote: proc (s: string): string, args: varargs[string]): string = + var res = "" + var a = 0 + for c in items(string(formatstr)): + if c == '?': + if a == args.len: + dbError("""The number of "?" given exceeds the number of parameters present in the query.""") + add(res, dbQuote(args[a])) + inc(a) + else: + add(res, c) + res diff --git a/tests/stdlib/tsqlitebindatas.nim b/tests/stdlib/tsqlitebindatas.nim index 643f1e2e6..754c80ae1 100644 --- a/tests/stdlib/tsqlitebindatas.nim +++ b/tests/stdlib/tsqlitebindatas.nim @@ -48,3 +48,31 @@ block tsqlitebindatas: ## db_sqlite binary data db.close() doAssert tryRemoveFile(dbName) + + +block: + block: + const dbName = buildDir / "db.sqlite3" + var db = db_sqlite.open(dbName, "", "", "") + var witness = false + try: + db.exec(sql("CREATE TABLE table1 (url TEXT, other_field INT);")) + db.exec(sql("REPLACE INTO table (url, another_field) VALUES (?, '123');")) + except DbError as e: + witness = true + doAssert e.msg == "The number of \"?\" given exceeds the number of parameters present in the query." + finally: + db.close() + removeFile(dbName) + + doAssert witness + + block: + const dbName = buildDir / "db.sqlite3" + var db = db_sqlite.open(dbName, "", "", "") + try: + db.exec(sql("CREATE TABLE table1 (url TEXT, other_field INT);")) + db.exec(sql("INSERT INTO table1 (url, other_field) VALUES (?, ?);"), "http://domain.com/test?param=1", 123) + finally: + db.close() + removeFile(dbName) |