Fix prepared statements for PostgreSQL driver.
libpq requires zero-terminated strings for text arguments.
This commit is contained in:
@ -34,7 +34,7 @@
|
||||
#include "sb_rand.h"
|
||||
|
||||
/* Maximum length of text representation of bind parameters */
|
||||
#define MAX_PARAM_LENGTH 256
|
||||
#define MAX_PARAM_LENGTH 256UL
|
||||
|
||||
/* PostgreSQL driver arguments */
|
||||
|
||||
@ -359,6 +359,11 @@ int pgsql_drv_prepare(db_stmt_t *stmt, const char *query, size_t len)
|
||||
if (PQresultStatus(pgres) != PGRES_COMMAND_OK)
|
||||
{
|
||||
log_text(LOG_FATAL, "PQprepare() failed: %s", PQerrorMessage(con));
|
||||
|
||||
free(stmt->query);
|
||||
free(pgstmt->name);
|
||||
free(pgstmt);
|
||||
|
||||
return 1;
|
||||
}
|
||||
pgstmt->prepared = 1;
|
||||
@ -440,9 +445,8 @@ int pgsql_drv_bind_param(db_stmt_t *stmt, db_bind_t *params, size_t len)
|
||||
if (pgstmt->pvalues[i] != NULL)
|
||||
{
|
||||
free(pgstmt->pvalues[i]);
|
||||
pgstmt->pvalues[i] = NULL;
|
||||
}
|
||||
|
||||
|
||||
pgstmt->pvalues[i] = (char *)malloc(MAX_PARAM_LENGTH);
|
||||
if (pgstmt->pvalues[i] == NULL)
|
||||
return 1;
|
||||
@ -547,6 +551,7 @@ db_error_t pgsql_drv_execute(db_stmt_t *stmt, db_result_t *rs)
|
||||
char need_realloc;
|
||||
int n;
|
||||
db_error_t rc;
|
||||
unsigned long len;
|
||||
|
||||
if (!stmt->emulated)
|
||||
{
|
||||
@ -567,8 +572,14 @@ db_error_t pgsql_drv_execute(db_stmt_t *stmt, db_result_t *rs)
|
||||
switch (stmt->bound_param[i].type) {
|
||||
case DB_TYPE_CHAR:
|
||||
case DB_TYPE_VARCHAR:
|
||||
strncpy(pgstmt->pvalues[i], stmt->bound_param[i].buffer,
|
||||
MAX_PARAM_LENGTH);
|
||||
|
||||
len = stmt->bound_param[i].data_len[0];
|
||||
|
||||
memcpy(pgstmt->pvalues[i], stmt->bound_param[i].buffer,
|
||||
SB_MIN(MAX_PARAM_LENGTH, len));
|
||||
/* PostgreSQL requires a zero-terminated string */
|
||||
pgstmt->pvalues[i][len] = '\0';
|
||||
|
||||
break;
|
||||
default:
|
||||
db_print_value(stmt->bound_param + i, pgstmt->pvalues[i],
|
||||
|
||||
@ -392,7 +392,7 @@ function statement_methods.bind_param(self, ...)
|
||||
for i, param in ipairs({...}) do
|
||||
binds[i-1].type = param.type
|
||||
binds[i-1].buffer = param.buffer
|
||||
binds[i-1].data_len = param.datalen
|
||||
binds[i-1].data_len = param.data_len
|
||||
binds[i-1].max_len = param.max_len
|
||||
binds[i-1].is_null = param.is_null
|
||||
end
|
||||
|
||||
@ -60,6 +60,10 @@ function event()
|
||||
con:query("DROP TABLE t2")
|
||||
con:query("ALTER TABLE t ADD COLUMN b CHAR(10)")
|
||||
|
||||
e, m = pcall(con.prepare, con, "SELECT * FROM nonexisting")
|
||||
print(m)
|
||||
print('--')
|
||||
|
||||
local stmt = con:prepare("UPDATE t SET a = a + ?, b = ?")
|
||||
local a = stmt:bind_create(sysbench.sql.type.INT)
|
||||
local b = stmt:bind_create(sysbench.sql.type.CHAR, 10)
|
||||
|
||||
@ -37,6 +37,9 @@ SQL Lua API + MySQL tests
|
||||
--
|
||||
nil 2
|
||||
--
|
||||
FATAL: mysql_stmt_prepare() failed
|
||||
FATAL: MySQL error: 1146 "Table 'sbtest.nonexisting' doesn't exist"
|
||||
SQL API error
|
||||
<sql_param>
|
||||
<sql_param>
|
||||
Unsupported argument type: 8
|
||||
|
||||
@ -37,6 +37,12 @@ SQL Lua API + PostgreSQL tests
|
||||
--
|
||||
bar nil
|
||||
--
|
||||
FATAL: PQprepare() failed: ERROR: relation "nonexisting" does not exist
|
||||
LINE 1: SELECT * FROM nonexisting
|
||||
^
|
||||
|
||||
SQL API error
|
||||
--
|
||||
<sql_param>
|
||||
<sql_param>
|
||||
Unsupported argument type: 8
|
||||
|
||||
Reference in New Issue
Block a user