summary refs log tree commit diff stats
diff options
context:
space:
mode:
-rw-r--r--lib/impure/db_sqlite.nim15
-rw-r--r--lib/std/private/dbutils.nim15
-rw-r--r--tests/stdlib/tsqlitebindatas.nim28
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)