fix a sqlite bug (#18669)

This commit is contained in:
flywind 2021-08-13 00:21:01 +08:00 • committed by GitHub
commit f559319a68
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 47 additions and 11 deletions

View file

@ -171,7 +171,7 @@ import sqlite3, macros
import db_common import db_common
export db_common export db_common
import std/private/since import std/private/[since, dbutils]
type type
DbConn* = PSqlite3 ## Encapsulates a database connection. DbConn* = PSqlite3 ## Encapsulates a database connection.
@ -211,14 +211,7 @@ proc dbQuote*(s: string): string =
add(result, '\'') add(result, '\'')
proc dbFormat(formatstr: SqlQuery, args: varargs[string]): string = proc dbFormat(formatstr: SqlQuery, args: varargs[string]): string =
result = "" dbFormatImpl(formatstr, dbQuote, args)
var a = 0
for c in items(string(formatstr)):
if c == '?':
add(result, dbQuote(args[a]))
inc(a)
else:
add(result, c)
proc prepare*(db: DbConn; q: string): SqlPrepared {.since: (1, 3).} = proc prepare*(db: DbConn; q: string): SqlPrepared {.since: (1, 3).} =
## Creates a new `SqlPrepared` statement. ## Creates a new `SqlPrepared` statement.
@ -642,7 +635,7 @@ proc getValue*(db: DbConn, stmtName: SqlPrepared): string
proc tryInsertID*(db: DbConn, query: SqlQuery, proc tryInsertID*(db: DbConn, query: SqlQuery,
args: varargs[string, `$`]): int64 args: varargs[string, `$`]): int64
{.tags: [WriteDbEffect], raises: [].} = {.tags: [WriteDbEffect], raises: [DbError].} =
## 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.
## ##
@ -699,7 +692,7 @@ proc insertID*(db: DbConn, query: SqlQuery,
proc tryInsert*(db: DbConn, query: SqlQuery, pkName: string, proc tryInsert*(db: DbConn, query: SqlQuery, pkName: string,
args: varargs[string, `$`]): int64 args: varargs[string, `$`]): int64
{.tags: [WriteDbEffect], raises: [], since: (1, 3).} = {.tags: [WriteDbEffect], raises: [DbError], since: (1, 3).} =
## same as tryInsertID ## same as tryInsertID
tryInsertID(db, query, args) tryInsertID(db, query, args)

View file

@ -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

View file

@ -48,3 +48,31 @@ block tsqlitebindatas: ## db_sqlite binary data
db.close() db.close()
doAssert tryRemoveFile(dbName) 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)