summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2023-10-08 16:58:13 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2023-10-08 16:58:13 +0100
commit78d8eeadcf6642eb52b3b178d6da620b0bb34289 (patch)
tree4777a94e6438b79e146754c58ad81a7b6d2a4118
parentFix virtual/override attribute use (diff)
downloadlibdbpp-postgresql-78d8eeadcf6642eb52b3b178d6da620b0bb34289.tar.bz2
libdbpp-postgresql-78d8eeadcf6642eb52b3b178d6da620b0bb34289.tar.xz
libdbpp-postgresql-78d8eeadcf6642eb52b3b178d6da620b0bb34289.zip
Use unique_ptr for execution results
-rw-r--r--libpqpp/pq-bulkselectcommand.cpp13
-rw-r--r--libpqpp/pq-bulkselectcommand.h3
-rw-r--r--libpqpp/pq-column.cpp10
-rw-r--r--libpqpp/pq-connection.cpp26
-rw-r--r--libpqpp/pq-connection.h4
-rw-r--r--libpqpp/pq-cursorselectcommand.cpp17
-rw-r--r--libpqpp/pq-helpers.h5
-rw-r--r--libpqpp/pq-modifycommand.cpp9
-rw-r--r--libpqpp/pq-prepared.cpp4
-rw-r--r--libpqpp/pq-selectbase.cpp14
-rw-r--r--libpqpp/pq-selectbase.h5
11 files changed, 44 insertions, 66 deletions
diff --git a/libpqpp/pq-bulkselectcommand.cpp b/libpqpp/pq-bulkselectcommand.cpp
index 298261e..303ed53 100644
--- a/libpqpp/pq-bulkselectcommand.cpp
+++ b/libpqpp/pq-bulkselectcommand.cpp
@@ -10,21 +10,20 @@
PQ::BulkSelectCommand::BulkSelectCommand(Connection * conn, const std::string & sql,
const PQ::CommandOptionsCPtr & pqco, const DB::CommandOptionsCPtr & opts) :
DB::Command(sql),
- PQ::SelectBase(sql, pqco), PQ::PreparedStatement(conn, sql, opts), executed(false)
+ PQ::SelectBase(sql, pqco), PQ::PreparedStatement(conn, sql, opts)
{
}
void
PQ::BulkSelectCommand::execute()
{
- if (!executed) {
+ if (!execRes) {
execRes = c->checkResult(PQexecPrepared(c->conn, prepare(), static_cast<int>(values.size()), values.data(),
lengths.data(), formats.data(), binary),
PGRES_TUPLES_OK);
- nTuples = static_cast<decltype(nTuples)>(PQntuples(execRes));
+ nTuples = static_cast<decltype(nTuples)>(PQntuples(execRes.get()));
tuple = static_cast<decltype(tuple)>(-1);
- createColumns(execRes);
- executed = true;
+ createColumns();
}
}
@@ -36,9 +35,7 @@ PQ::BulkSelectCommand::fetch()
return true;
}
else {
- PQclear(execRes);
- execRes = nullptr;
- executed = false;
+ execRes.reset();
return false;
}
}
diff --git a/libpqpp/pq-bulkselectcommand.h b/libpqpp/pq-bulkselectcommand.h
index 6e186a1..10d4fbf 100644
--- a/libpqpp/pq-bulkselectcommand.h
+++ b/libpqpp/pq-bulkselectcommand.h
@@ -17,9 +17,6 @@ namespace PQ {
bool fetch() override;
void execute() override;
-
- private:
- mutable bool executed;
};
}
diff --git a/libpqpp/pq-column.cpp b/libpqpp/pq-column.cpp
index f78863c..3ed8e20 100644
--- a/libpqpp/pq-column.cpp
+++ b/libpqpp/pq-column.cpp
@@ -12,26 +12,28 @@
#include <server/catalog/pg_type_d.h>
PQ::Column::Column(const SelectBase * s, unsigned int i) :
- DB::Column(PQfname(s->execRes, static_cast<int>(i)), i), sc(s), oid(PQftype(sc->execRes, static_cast<int>(colNo)))
+ DB::Column(PQfname(s->execRes.get(), static_cast<int>(i)), i), sc(s),
+ oid(PQftype(sc->execRes.get(), static_cast<int>(colNo)))
{
}
bool
PQ::Column::isNull() const
{
- return PQgetisnull(sc->execRes, static_cast<int>(sc->tuple), static_cast<int>(colNo));
+ return PQgetisnull(sc->execRes.get(), static_cast<int>(sc->tuple), static_cast<int>(colNo));
}
std::size_t
PQ::Column::length() const
{
- return static_cast<std::size_t>(PQgetlength(sc->execRes, static_cast<int>(sc->tuple), static_cast<int>(colNo)));
+ return static_cast<std::size_t>(
+ PQgetlength(sc->execRes.get(), static_cast<int>(sc->tuple), static_cast<int>(colNo)));
}
const char *
PQ::Column::value() const
{
- return PQgetvalue(sc->execRes, static_cast<int>(sc->tuple), static_cast<int>(colNo));
+ return PQgetvalue(sc->execRes.get(), static_cast<int>(sc->tuple), static_cast<int>(colNo));
}
void
diff --git a/libpqpp/pq-connection.cpp b/libpqpp/pq-connection.cpp
index a65d88b..dc3cf13 100644
--- a/libpqpp/pq-connection.cpp
+++ b/libpqpp/pq-connection.cpp
@@ -55,25 +55,25 @@ PQ::Connection::~Connection()
void
PQ::Connection::beginTxInt()
{
- checkResultFree(PQexec(conn, "BEGIN"), PGRES_COMMAND_OK);
+ checkResult(PQexec(conn, "BEGIN"), PGRES_COMMAND_OK);
}
void
PQ::Connection::commitTxInt()
{
- checkResultFree(PQexec(conn, "COMMIT"), PGRES_COMMAND_OK);
+ checkResult(PQexec(conn, "COMMIT"), PGRES_COMMAND_OK);
}
void
PQ::Connection::rollbackTxInt()
{
- checkResultFree(PQexec(conn, "ROLLBACK"), PGRES_COMMAND_OK);
+ checkResult(PQexec(conn, "ROLLBACK"), PGRES_COMMAND_OK);
}
void
PQ::Connection::execute(const std::string & sql, const DB::CommandOptionsCPtr &)
{
- checkResultFree(PQexec(conn, sql.c_str()), PGRES_COMMAND_OK, PGRES_TUPLES_OK);
+ checkResult(PQexec(conn, sql.c_str()), PGRES_COMMAND_OK, PGRES_TUPLES_OK);
}
DB::BulkDeleteStyle
@@ -130,24 +130,14 @@ PQ::Connection::checkResultInt(PGresult * res, int expected, int alt)
return (PQresultStatus(res) == expected) || (alt != -1 && (PQresultStatus(res) == alt));
}
-PGresult *
+PQ::ResultPtr
PQ::Connection::checkResult(PGresult * res, int expected, int alt) const
{
if (!checkResultInt(res, expected, alt)) {
PQclear(res);
throw Error(conn);
}
- return res;
-}
-
-void
-PQ::Connection::checkResultFree(PGresult * res, int expected, int alt) const
-{
- if (!checkResultInt(res, expected, alt)) {
- PQclear(res);
- throw Error(conn);
- }
- PQclear(res);
+ return ResultPtr {res};
}
AdHocFormatter(PQConnectionCopyFrom, "COPY %? FROM STDIN %?");
@@ -155,7 +145,7 @@ AdHocFormatter(PQConnectionCopyFrom, "COPY %? FROM STDIN %?");
void
PQ::Connection::beginBulkUpload(const char * table, const char * extra)
{
- checkResultFree(PQexec(conn, PQConnectionCopyFrom::get(table, extra).c_str()), PGRES_COPY_IN);
+ checkResult(PQexec(conn, PQConnectionCopyFrom::get(table, extra).c_str()), PGRES_COPY_IN);
}
void
@@ -168,7 +158,7 @@ PQ::Connection::endBulkUpload(const char * msg)
if (rc != 1) {
throw Error(conn);
}
- checkResultFree(PQgetResult(conn), PGRES_COMMAND_OK);
+ checkResult(PQgetResult(conn), PGRES_COMMAND_OK);
}
size_t
diff --git a/libpqpp/pq-connection.h b/libpqpp/pq-connection.h
index 83da2d4..af013ab 100644
--- a/libpqpp/pq-connection.h
+++ b/libpqpp/pq-connection.h
@@ -3,6 +3,7 @@
#include "command_fwd.h"
#include "pq-error.h"
+#include "pq-helpers.h"
#include <c++11Helpers.h>
#include <connection.h>
#include <cstddef>
@@ -46,8 +47,7 @@ namespace PQ {
void endBulkUpload(const char *) override;
size_t bulkUploadData(const char *, size_t) const override;
- PGresult * checkResult(PGresult * res, int expected, int alternative = -1) const;
- void checkResultFree(PGresult * res, int expected, int alternative = -1) const;
+ ResultPtr checkResult(PGresult * res, int expected, int alternative = -1) const;
PGconn * conn;
mutable PreparedStatements preparedStatements;
diff --git a/libpqpp/pq-cursorselectcommand.cpp b/libpqpp/pq-cursorselectcommand.cpp
index 8d3a7bf..bfb69d4 100644
--- a/libpqpp/pq-cursorselectcommand.cpp
+++ b/libpqpp/pq-cursorselectcommand.cpp
@@ -5,7 +5,6 @@
#include "pq-selectbase.h"
#include <compileTimeFormatter.h>
#include <libpq-fe.h>
-#include <memory>
#include <type_traits>
#include <utility>
#include <vector>
@@ -25,7 +24,7 @@ PQ::CursorSelectCommand::CursorSelectCommand(Connection * conn, const std::strin
PQ::CursorSelectCommand::~CursorSelectCommand()
{
if (executed && PQtransactionStatus(c->conn) != PQTRANS_INERROR) {
- c->checkResultFree((PQexec(c->conn, s_close.c_str())), PGRES_COMMAND_OK);
+ c->checkResult(PQexec(c->conn, s_close.c_str()), PGRES_COMMAND_OK);
}
}
@@ -45,11 +44,11 @@ PQ::CursorSelectCommand::execute()
if (s_declare.empty()) {
s_declare = mkdeclare();
}
- c->checkResultFree(PQexecParams(c->conn, s_declare.c_str(), static_cast<int>(values.size()), nullptr,
- values.data(), lengths.data(), formats.data(), binary),
+ c->checkResult(PQexecParams(c->conn, s_declare.c_str(), static_cast<int>(values.size()), nullptr, values.data(),
+ lengths.data(), formats.data(), binary),
PGRES_COMMAND_OK);
fetchTuples();
- createColumns(execRes);
+ createColumns();
executed = true;
}
}
@@ -59,7 +58,7 @@ PQ::CursorSelectCommand::fetchTuples()
{
execRes = c->checkResult(
PQexecParams(c->conn, s_fetch.c_str(), 0, nullptr, nullptr, nullptr, nullptr, binary), PGRES_TUPLES_OK);
- nTuples = static_cast<decltype(nTuples)>(PQntuples(execRes));
+ nTuples = static_cast<decltype(nTuples)>(PQntuples(execRes.get()));
tuple = static_cast<decltype(tuple)>(-1);
}
@@ -69,8 +68,7 @@ PQ::CursorSelectCommand::fetch()
execute();
if ((tuple + 1 >= nTuples) && (nTuples == fTuples)) {
// Delete the previous result set
- PQclear(execRes);
- execRes = nullptr;
+ execRes.reset();
fetchTuples();
}
if (++tuple < nTuples) {
@@ -78,8 +76,7 @@ PQ::CursorSelectCommand::fetch()
}
else {
PQclear(PQexec(c->conn, s_close.c_str()));
- PQclear(execRes);
- execRes = nullptr;
+ execRes.reset();
executed = false;
return false;
}
diff --git a/libpqpp/pq-helpers.h b/libpqpp/pq-helpers.h
index 76e5057..7861d57 100644
--- a/libpqpp/pq-helpers.h
+++ b/libpqpp/pq-helpers.h
@@ -1,6 +1,9 @@
#ifndef PQ_HELPERS_H
#define PQ_HELPERS_H
+#include "libpq-fe.h"
+#include <memory>
+
namespace PQ {
template<auto func> struct pq_deleter {
void
@@ -9,6 +12,8 @@ namespace PQ {
func(p);
}
};
+
+ using ResultPtr = std::unique_ptr<PGresult, pq_deleter<PQclear>>;
}
#endif
diff --git a/libpqpp/pq-modifycommand.cpp b/libpqpp/pq-modifycommand.cpp
index b29fda7..53c3231 100644
--- a/libpqpp/pq-modifycommand.cpp
+++ b/libpqpp/pq-modifycommand.cpp
@@ -15,11 +15,10 @@ PQ::ModifyCommand::ModifyCommand(Connection * conn, const std::string & sql, con
unsigned int
PQ::ModifyCommand::execute(bool anc)
{
- PGresult * res = PQexecPrepared(
- c->conn, prepare(), static_cast<int>(values.size()), values.data(), lengths.data(), formats.data(), 0);
- c->checkResult(res, PGRES_COMMAND_OK, PGRES_TUPLES_OK);
- auto rows = atoi(PQcmdTuples(res));
- PQclear(res);
+ const auto res = c->checkResult(PQexecPrepared(c->conn, prepare(), static_cast<int>(values.size()), values.data(),
+ lengths.data(), formats.data(), 0),
+ PGRES_COMMAND_OK, PGRES_TUPLES_OK);
+ auto rows = atoi(PQcmdTuples(res.get()));
if (rows == 0 && !anc) {
throw DB::NoRowsAffected();
}
diff --git a/libpqpp/pq-prepared.cpp b/libpqpp/pq-prepared.cpp
index bf8bd08..8678c11 100644
--- a/libpqpp/pq-prepared.cpp
+++ b/libpqpp/pq-prepared.cpp
@@ -26,8 +26,8 @@ PQ::PreparedStatement::prepare() const
}
std::stringstream psql;
prepareSql(psql, sql);
- c->checkResultFree(PQprepare(c->conn, stmntName.c_str(), std::move(psql).str().c_str(),
- static_cast<int>(values.size()), nullptr),
+ c->checkResult(PQprepare(c->conn, stmntName.c_str(), std::move(psql).str().c_str(), static_cast<int>(values.size()),
+ nullptr),
PGRES_COMMAND_OK);
return (pstmt = c->preparedStatements.insert({hash, stmntName}).first->second.c_str());
}
diff --git a/libpqpp/pq-selectbase.cpp b/libpqpp/pq-selectbase.cpp
index d884d06..00abdb9 100644
--- a/libpqpp/pq-selectbase.cpp
+++ b/libpqpp/pq-selectbase.cpp
@@ -9,22 +9,14 @@
#include <string>
PQ::SelectBase::SelectBase(const std::string & sql, const PQ::CommandOptionsCPtr & pqco) :
- DB::Command(sql), DB::SelectCommand(sql), nTuples(0), tuple(0), execRes(nullptr),
- binary(pqco ? pqco->fetchBinary : false)
+ DB::Command(sql), DB::SelectCommand(sql), nTuples(0), tuple(0), binary(pqco ? pqco->fetchBinary : false)
{
}
-PQ::SelectBase::~SelectBase()
-{
- if (execRes) {
- PQclear(execRes);
- }
-}
-
void
-PQ::SelectBase::createColumns(PGresult * execRes)
+PQ::SelectBase::createColumns()
{
- auto nFields = PQnfields(execRes);
+ auto nFields = PQnfields(execRes.get());
for (decltype(nFields) f = 0; f < nFields; f += 1) {
if (binary) {
insertColumn(std::make_unique<BinaryColumn>(this, f));
diff --git a/libpqpp/pq-selectbase.h b/libpqpp/pq-selectbase.h
index 19bef7a..9d4ff57 100644
--- a/libpqpp/pq-selectbase.h
+++ b/libpqpp/pq-selectbase.h
@@ -12,12 +12,11 @@ namespace PQ {
protected:
SelectBase(const std::string & sql, const PQ::CommandOptionsCPtr & pqco);
- ~SelectBase();
- void createColumns(PGresult *);
+ void createColumns();
unsigned int nTuples, tuple;
- PGresult * execRes;
+ ResultPtr execRes;
bool binary;
};
}