Skip to content

Commit

Permalink
Release PGresult when an exception is thrown
Browse files Browse the repository at this point in the history
Fix involves:
* Call PQclear in throw_postgresql_soci_error
* Change throw_postgresql_soci_error to take pointer by reference to
effectively reset result
* PostgreSQL tests pass
* Close #86
Rename res to result for consistency.

(std::unique_ptr would be bless for correct and simple RAII across SOCI)
  • Loading branch information
mloskot committed Mar 1, 2013
1 parent e1dcfd4 commit de0ed49
Show file tree
Hide file tree
Showing 4 changed files with 20 additions and 16 deletions.
14 changes: 9 additions & 5 deletions src/backends/postgresql/error.cpp
Expand Up @@ -28,11 +28,13 @@ std::string postgresql_soci_error::sqlstate() const
return std::string(sqlstate_, 5);
}

void soci::details::postgresql::get_error_details(PGresult *res,
void soci::details::postgresql::get_error_details(PGresult *result,
std::string &msg, std::string &sqlstate)
{
msg = PQresultErrorMessage(res);
const char *sqlst = PQresultErrorField(res, PG_DIAG_SQLSTATE);
assert(result);

msg = PQresultErrorMessage(result);
const char *sqlst = PQresultErrorField(result, PG_DIAG_SQLSTATE);
const char* blank_sql_state = " ";
if (!sqlst)
{
Expand All @@ -42,11 +44,13 @@ void soci::details::postgresql::get_error_details(PGresult *res,
sqlstate.assign(sqlst, 5);
}

void soci::details::postgresql::throw_postgresql_soci_error(PGresult *res)
void soci::details::postgresql::throw_postgresql_soci_error(PGresult*& result)
{
std::string msg;
std::string sqlstate;

get_error_details(res, msg, sqlstate);
get_error_details(result, msg, sqlstate);
PQclear(result);
result = NULL;
throw postgresql_soci_error(msg, sqlstate.c_str());
}
4 changes: 2 additions & 2 deletions src/backends/postgresql/error.h
Expand Up @@ -19,9 +19,9 @@ namespace details
namespace postgresql
{

void throw_postgresql_soci_error(PGresult *res);
void throw_postgresql_soci_error(PGresult*& res);

void get_error_details(PGresult *res, std::string &msg, std::string &sqlstate);
void get_error_details(PGresult* res, std::string &msg, std::string &sqlstate);

} // namespace postgresql

Expand Down
2 changes: 1 addition & 1 deletion src/backends/postgresql/session.cpp
Expand Up @@ -59,7 +59,6 @@ namespace // unnamed
void hard_exec(PGconn * conn, char const * query, char const * errMsg)
{
PGresult* result = PQexec(conn, query);

if (0 == result)
{
throw soci_error(errMsg);
Expand All @@ -68,6 +67,7 @@ void hard_exec(PGconn * conn, char const * query, char const * errMsg)
ExecStatusType const status = PQresultStatus(result);
if (PGRES_COMMAND_OK != status)
{
// releases result with PQclear
throw_postgresql_soci_error(result);
}

Expand Down
16 changes: 8 additions & 8 deletions src/backends/postgresql/statement.cpp
Expand Up @@ -162,18 +162,19 @@ void postgresql_statement_backend::prepare(std::string const & query,
{
statementName_ = session_.get_next_statement_name();

PGresult * res = PQprepare(session_.conn_, statementName_.c_str(),
PGresult* result = PQprepare(session_.conn_, statementName_.c_str(),
query_.c_str(), static_cast<int>(names_.size()), NULL);
if (res == NULL)
if (result == NULL)
{
throw soci_error("Cannot prepare statement.");
}
ExecStatusType status = PQresultStatus(res);
ExecStatusType status = PQresultStatus(result);
if (status != PGRES_COMMAND_OK)
{
throw_postgresql_soci_error(res);
// releases result with PQclear
throw_postgresql_soci_error(result);
}
PQclear(res);
PQclear(result);
}

stType_ = stType;
Expand Down Expand Up @@ -280,9 +281,7 @@ postgresql_statement_backend::execute(int number)
result_ = PQexecParams(session_.conn_, query_.c_str(),
static_cast<int>(paramValues.size()),
NULL, &paramValues[0], NULL, NULL, 0);

#else

if (stType_ == st_repeatable_query)
{
// this query was separately prepared
Expand Down Expand Up @@ -318,6 +317,7 @@ postgresql_statement_backend::execute(int number)
ExecStatusType status = PQresultStatus(result_);
if (status != PGRES_COMMAND_OK)
{
// releases result_ with PQclear
throw_postgresql_soci_error(result_);
}
PQclear(result_);
Expand All @@ -342,7 +342,6 @@ postgresql_statement_backend::execute(int number)

result_ = PQexec(session_.conn_, query_.c_str());
#else

if (stType_ == st_repeatable_query)
{
// this query was separately prepared
Expand Down Expand Up @@ -404,6 +403,7 @@ postgresql_statement_backend::execute(int number)
}
else
{
// releases result_ with PQclear
throw_postgresql_soci_error(result_);

// dummy, never reach
Expand Down

0 comments on commit de0ed49

Please sign in to comment.