Fix prepared statements for PostgreSQL driver.

libpq requires zero-terminated strings for text arguments.
This commit is contained in:
Alexey Kopytov
2017-01-23 22:51:58 +03:00
parent 0e49aa1edb
commit deb4994144
5 changed files with 30 additions and 6 deletions

View File

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

View File

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

View File

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

View File

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

View File

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