mirror of
https://github.com/nim-lang/Nim.git
synced 2026-01-18 10:37:12 +00:00
Fix several memory leaks in the Postgres wrapper. (#20940)
(cherry picked from commit 5a848a0707)
This commit is contained in:
@@ -207,7 +207,8 @@ proc prepare*(db: DbConn; stmtName: string, query: SqlQuery;
|
||||
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)
|
||||
result = SqlPrepared(stmtName)
|
||||
pqclear(res)
|
||||
|
||||
proc setRow(res: PPGresult, r: var Row, line, cols: int32) =
|
||||
for col in 0'i32..cols-1:
|
||||
@@ -474,12 +475,12 @@ proc getRow*(db: DbConn, query: SqlQuery,
|
||||
## retrieves a single row. If the query doesn't return any rows, this proc
|
||||
## will return a Row with empty strings for each column.
|
||||
let res = setupQuery(db, query, args)
|
||||
getRow(res)
|
||||
result = getRow(res)
|
||||
|
||||
proc getRow*(db: DbConn, stmtName: SqlPrepared,
|
||||
args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
|
||||
let res = setupQuery(db, stmtName, args)
|
||||
getRow(res)
|
||||
result = getRow(res)
|
||||
|
||||
proc getAllRows(res: PPGresult): seq[Row] =
|
||||
let N = pqntuples(res)
|
||||
@@ -496,14 +497,14 @@ proc getAllRows*(db: DbConn, query: SqlQuery,
|
||||
tags: [ReadDbEffect].} =
|
||||
## executes the query and returns the whole result dataset.
|
||||
let res = setupQuery(db, query, args)
|
||||
getAllRows(res)
|
||||
result = getAllRows(res)
|
||||
|
||||
proc getAllRows*(db: DbConn, stmtName: SqlPrepared,
|
||||
args: varargs[string, `$`]): seq[Row] {.tags:
|
||||
[ReadDbEffect].} =
|
||||
## executes the prepared query and returns the whole result dataset.
|
||||
let res = setupQuery(db, stmtName, args)
|
||||
getAllRows(res)
|
||||
result = getAllRows(res)
|
||||
|
||||
iterator rows*(db: DbConn, query: SqlQuery,
|
||||
args: varargs[string, `$`]): Row {.tags: [ReadDbEffect].} =
|
||||
@@ -529,7 +530,8 @@ proc getValue*(db: DbConn, query: SqlQuery,
|
||||
## result dataset. Returns "" if the dataset contains no rows or the database
|
||||
## value is NULL.
|
||||
let res = setupQuery(db, query, args)
|
||||
getValue(res)
|
||||
result = getValue(res)
|
||||
pqclear(res)
|
||||
|
||||
proc getValue*(db: DbConn, stmtName: SqlPrepared,
|
||||
args: varargs[string, `$`]): string {.
|
||||
@@ -538,7 +540,8 @@ proc getValue*(db: DbConn, stmtName: SqlPrepared,
|
||||
## result dataset. Returns "" if the dataset contains no rows or the database
|
||||
## value is NULL.
|
||||
let res = setupQuery(db, stmtName, args)
|
||||
getValue(res)
|
||||
result = getValue(res)
|
||||
pqclear(res)
|
||||
|
||||
proc tryInsertID*(db: DbConn, query: SqlQuery,
|
||||
args: varargs[string, `$`]): int64 {.
|
||||
@@ -547,12 +550,14 @@ proc tryInsertID*(db: DbConn, query: SqlQuery,
|
||||
## generated ID for the row or -1 in case of an error. For Postgre this adds
|
||||
## `RETURNING id` to the query, so it only works if your primary key is
|
||||
## named `id`.
|
||||
var x = pqgetvalue(setupQuery(db, SqlQuery(string(query) & " RETURNING id"),
|
||||
args), 0, 0)
|
||||
let res = setupQuery(db, SqlQuery(string(query) & " RETURNING id"),
|
||||
args)
|
||||
var x = pqgetvalue(res, 0, 0)
|
||||
if not isNil(x):
|
||||
result = parseBiggestInt($x)
|
||||
else:
|
||||
result = -1
|
||||
pqclear(res)
|
||||
|
||||
proc insertID*(db: DbConn, query: SqlQuery,
|
||||
args: varargs[string, `$`]): int64 {.
|
||||
@@ -569,12 +574,14 @@ proc tryInsert*(db: DbConn, query: SqlQuery,pkName: string,
|
||||
{.tags: [WriteDbEffect], since: (1, 3).}=
|
||||
## executes the query (typically "INSERT") and returns the
|
||||
## generated ID for the row or -1 in case of an error.
|
||||
var x = pqgetvalue(setupQuery(db, SqlQuery(string(query) & " RETURNING " & pkName),
|
||||
args), 0, 0)
|
||||
let res = setupQuery(db, SqlQuery(string(query) & " RETURNING " & pkName),
|
||||
args)
|
||||
var x = pqgetvalue(res, 0, 0)
|
||||
if not isNil(x):
|
||||
result = parseBiggestInt($x)
|
||||
else:
|
||||
result = -1
|
||||
pqclear(res)
|
||||
|
||||
proc insert*(db: DbConn, query: SqlQuery, pkName: string,
|
||||
args: varargs[string, `$`]): int64
|
||||
|
||||
@@ -2,6 +2,7 @@ import db_postgres, strutils
|
||||
|
||||
|
||||
let db = open("localhost", "dom", "", "test")
|
||||
|
||||
db.exec(sql"DROP TABLE IF EXISTS myTable")
|
||||
db.exec(sql("""CREATE TABLE myTable (
|
||||
id integer PRIMARY KEY,
|
||||
@@ -49,9 +50,12 @@ try:
|
||||
doAssert false, "Exception expected"
|
||||
except DbError:
|
||||
let msg = getCurrentExceptionMsg().normalize
|
||||
doAssert "expects" in msg
|
||||
doAssert "?" in msg
|
||||
doAssert "parameter substitution" in msg
|
||||
|
||||
info "DbError",
|
||||
msg = $msg
|
||||
|
||||
doAssert "no parameter" in msg
|
||||
doAssert "$1" in msg
|
||||
|
||||
doAssert db.getValue(sql("select filename from files where id = ?"), 1) == "hello.tmp"
|
||||
|
||||
@@ -315,11 +319,11 @@ db.exec(sql("""CREATE TABLE DICTIONARY(
|
||||
var entry = "あっそ"
|
||||
var definition = "(int) (See ああそうそう) oh, really (uninterested)/oh yeah?/hmmmmm"
|
||||
discard db.getRow(
|
||||
SqlQuery("INSERT INTO DICTIONARY(entry, definition) VALUES(\'$1\', \'$2\') RETURNING id" % [entry, definition]))
|
||||
sql("INSERT INTO DICTIONARY(entry, definition) VALUES(?, ?) RETURNING id"), entry, definition)
|
||||
doAssert db.getValue(sql"SELECT definition FROM DICTIONARY WHERE entry = ?", entry) == definition
|
||||
entry = "Format string entry"
|
||||
definition = "Format string definition"
|
||||
db.exec(sql"INSERT INTO DICTIONARY(entry, definition) VALUES (?, ?)", entry, definition)
|
||||
db.exec(SqlQuery("INSERT INTO DICTIONARY(entry, definition) VALUES (?, ?)"), entry, definition)
|
||||
doAssert db.getValue(sql"SELECT definition FROM DICTIONARY WHERE entry = ?", entry) == definition
|
||||
|
||||
echo("All tests succeeded!")
|
||||
|
||||
Reference in New Issue
Block a user