pg: fix exec & exec_param_many (#6782)

pull/6785/head
KJ Lawrence 2020-11-09 02:22:16 -05:00 committed by GitHub
parent b0053d8910
commit 7108f89b69
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 29 additions and 41 deletions

View File

@ -16,8 +16,7 @@ pub mut:
vals []string vals []string
} }
struct C.PGResult { struct C.PGResult
}
pub struct Config { pub struct Config {
pub: pub:
@ -32,19 +31,21 @@ fn C.PQconnectdb(a byteptr) &C.PGconn
fn C.PQerrorMessage(voidptr) byteptr fn C.PQerrorMessage(voidptr) byteptr
fn C.PQgetvalue(voidptr, int, int) byteptr fn C.PQgetvalue(&C.PGResult, int, int) byteptr
fn C.PQstatus(voidptr) int fn C.PQstatus(voidptr) int
fn C.PQntuples(voidptr) int fn C.PQresultStatus(voidptr) int
fn C.PQnfields(voidptr) int fn C.PQntuples(&C.PGResult) int
fn C.PQexec(voidptr) voidptr fn C.PQnfields(&C.PGResult) int
fn C.PQexecParams(voidptr) voidptr fn C.PQexec(voidptr) &C.PGResult
fn C.PQclear(voidptr) voidptr fn C.PQexecParams(voidptr) &C.PGResult
fn C.PQclear(&C.PGResult) voidptr
fn C.PQfinish(voidptr) fn C.PQfinish(voidptr)
@ -75,6 +76,7 @@ pub fn connect(config Config) ?DB {
fn res_to_rows(res voidptr) []Row { fn res_to_rows(res voidptr) []Row {
nr_rows := C.PQntuples(res) nr_rows := C.PQntuples(res)
nr_cols := C.PQnfields(res) nr_cols := C.PQnfields(res)
mut rows := []Row{} mut rows := []Row{}
for i in 0 .. nr_rows { for i in 0 .. nr_rows {
mut row := Row{} mut row := Row{}
@ -85,6 +87,7 @@ fn res_to_rows(res voidptr) []Row {
} }
rows << row rows << row
} }
C.PQclear(res) C.PQclear(res)
return rows return rows
} }
@ -139,13 +142,7 @@ pub fn (db DB) q_strings(query string) ?[]Row {
// row set on success // row set on success
pub fn (db DB) exec(query string) ?[]Row { pub fn (db DB) exec(query string) ?[]Row {
res := C.PQexec(db.conn, query.str) res := C.PQexec(db.conn, query.str)
e := unsafe {C.PQerrorMessage(db.conn).vstring()} return db.handle_error_or_result(res, 'exec')
if e != '' {
error_msg := '$e'
C.PQclear(res)
return error(error_msg)
}
return res_to_rows(res)
} }
fn rows_first_or_empty(rows []Row) ?Row { fn rows_first_or_empty(rows []Row) ?Row {
@ -165,41 +162,30 @@ pub fn (db DB) exec_one(query string) ?Row {
return row return row
} }
// The entire function can be considered unsafe because of the malloc and the // exec_param_many executes a query with the provided parameters
// free. This prevents warnings and doesn't seem to affect behavior. pub fn (db DB) exec_param_many(query string, params []string) ?[]Row {
pub fn (db DB) exec_param_many(query string, params []string) []Row { mut param_vals := []charptr{ len: params.len }
unsafe {
mut param_vals := &byteptr(malloc(params.len * 8))
for i in 0 .. params.len { for i in 0 .. params.len {
param_vals[i] = params[i].str param_vals[i] = params[i].str
} }
res := C.PQexecParams(db.conn, query.str, params.len, 0, param_vals, 0, 0, 0)
free(param_vals) res := C.PQexecParams(db.conn, query.str, params.len, 0, param_vals.data, 0, 0, 0)
return db.handle_error_or_result(res, 'exec_param_many') return db.handle_error_or_result(res, 'exec_param_many')
} }
pub fn (db DB) exec_param2(query string, param string, param2 string) ?[]Row {
return db.exec_param_many(query, [param, param2])
} }
pub fn (db DB) exec_param2(query string, param string, param2 string) []Row { pub fn (db DB) exec_param(query string, param string) ?[]Row {
mut param_vals := [2]byteptr{} return db.exec_param_many(query, [param])
param_vals[0] = param.str
param_vals[1] = param2.str
res := C.PQexecParams(db.conn, query.str, 2, 0, param_vals, 0, 0, 0)
return db.handle_error_or_result(res, 'exec_param2')
} }
pub fn (db DB) exec_param(query string, param string) []Row { fn (db DB) handle_error_or_result(res voidptr, elabel string) ?[]Row {
mut param_vals := [1]byteptr{}
param_vals[0] = param.str
res := C.PQexecParams(db.conn, query.str, 1, 0, param_vals, 0, 0, 0)
return db.handle_error_or_result(res, 'exec_param')
}
fn (db DB) handle_error_or_result(res voidptr, elabel string) []Row {
e := unsafe {C.PQerrorMessage(db.conn).vstring()} e := unsafe {C.PQerrorMessage(db.conn).vstring()}
if e != '' { if e != '' {
println('pg $elabel error:') C.PQclear(res)
println(e) return error('pg $elabel error:\n$e')
return res_to_rows(res)
} }
return res_to_rows(res) return res_to_rows(res)
} }

View File

@ -134,6 +134,8 @@ pub fn (db DB) exec(query string) ([]Row, int) {
} }
rows << row rows << row
} }
C.sqlite3_finalize(stmt)
return rows, res return rows, res
} }