summaryrefslogtreecommitdiff
path: root/libpqpp
diff options
context:
space:
mode:
Diffstat (limited to 'libpqpp')
-rw-r--r--libpqpp/pq-command.cpp92
-rw-r--r--libpqpp/pq-command.h6
-rw-r--r--libpqpp/pq-modifycommand.cpp2
-rw-r--r--libpqpp/pq-selectcommand.cpp5
-rw-r--r--libpqpp/unittests/testpq.cpp28
5 files changed, 83 insertions, 50 deletions
diff --git a/libpqpp/pq-command.cpp b/libpqpp/pq-command.cpp
index 9b336bd..790c7f7 100644
--- a/libpqpp/pq-command.cpp
+++ b/libpqpp/pq-command.cpp
@@ -14,8 +14,13 @@ PQ::Command::Command(Connection * conn, const std::string & sql, unsigned int no
PQ::Command::~Command()
{
- for (std::vector<char *>::const_iterator i = values.begin(); i != values.end(); ++i) {
- free(*i);
+ for (auto i = values.size(); i-- > 0;) {
+ if (bufs[i]) {
+ delete bufs[i];
+ }
+ else {
+ free(values[i]);
+ }
}
}
@@ -46,102 +51,99 @@ PQ::Command::paramsAtLeast(unsigned int n)
if (values.size() <= n) {
values.resize(n + 1, NULL);
lengths.resize(n + 1, 0);
- formats.resize(n + 1, 0);
+ bufs.resize(n + 1, NULL);
}
else {
- free(values[n]);
+ if (bufs[n]) {
+ delete bufs[n];
+ bufs[n] = nullptr;
+ }
+ else {
+ free(values[n]);
+ }
values[n] = NULL;
}
}
+template<typename ... T>
void
-PQ::Command::bindParamI(unsigned int n, int v)
+PQ::Command::paramSet(unsigned int n, const char * fmt, const T & ... v)
{
paramsAtLeast(n);
- lengths[n] = asprintf(&values[n], "%d", v);
- formats[n] = 0;
+ lengths[n] = asprintf(&values[n], fmt, v...);
+ delete bufs[n];
+ bufs[n] = nullptr;
}
+
void
-PQ::Command::bindParamI(unsigned int n, long int v)
+PQ::Command::paramSet(unsigned int n, const std::string & b)
{
paramsAtLeast(n);
- lengths[n] = asprintf(&values[n], "%ld", v);
- formats[n] = 0;
+ delete bufs[n];
+ bufs[n] = new std::string(b);
+ lengths[n] = b.length();
+ values[n] = const_cast<char *>(bufs[n]->data());
+}
+
+void
+PQ::Command::bindParamI(unsigned int n, int v)
+{
+ paramSet(n, "%d", v);
+}
+void
+PQ::Command::bindParamI(unsigned int n, long int v)
+{
+ paramSet(n, "%ld", v);
}
void
PQ::Command::bindParamI(unsigned int n, long long int v)
{
- paramsAtLeast(n);
- lengths[n] = asprintf(&values[n], "%lld", v);
- formats[n] = 0;
+ paramSet(n, "%lld", v);
}
void
PQ::Command::bindParamI(unsigned int n, unsigned int v)
{
- paramsAtLeast(n);
- lengths[n] = asprintf(&values[n], "%u", v);
- formats[n] = 0;
+ paramSet(n, "%u", v);
}
void
PQ::Command::bindParamI(unsigned int n, long unsigned int v)
{
- paramsAtLeast(n);
- lengths[n] = asprintf(&values[n], "%lu", v);
- formats[n] = 0;
+ paramSet(n, "%lu", v);
}
void
PQ::Command::bindParamI(unsigned int n, long long unsigned int v)
{
- paramsAtLeast(n);
- lengths[n] = asprintf(&values[n], "%llu", v);
- formats[n] = 0;
+ paramSet(n, "%llu", v);
}
void
PQ::Command::bindParamB(unsigned int n, bool v)
{
- paramsAtLeast(n);
- lengths[n] = asprintf(&values[n], "%s", v ? "true" : "false");
- formats[n] = 0;
+ paramSet(n, "%s", v ? "true" : "false");
}
void
PQ::Command::bindParamF(unsigned int n, double v)
{
- paramsAtLeast(n);
- lengths[n] = asprintf(&values[n], "%g", v);
- formats[n] = 0;
+ paramSet(n, "%g", v);
}
void
PQ::Command::bindParamF(unsigned int n, float v)
{
- paramsAtLeast(n);
- lengths[n] = asprintf(&values[n], "%g", v);
- formats[n] = 0;
+ paramSet(n, "%g", v);
}
void
PQ::Command::bindParamS(unsigned int n, const Glib::ustring & s)
{
- paramsAtLeast(n);
- values[n] = strndup(s.c_str(), s.bytes());
- formats[n] = 0;
- lengths[n] = s.bytes();
+ paramSet(n, s);
}
void
PQ::Command::bindParamT(unsigned int n, const boost::posix_time::time_duration & v)
{
- paramsAtLeast(n);
- auto buf = boost::posix_time::to_simple_string(v);
- values[n] = strdup(buf.c_str());
- formats[n] = 0;
- lengths[n] = buf.length();
+ paramSet(n, boost::posix_time::to_simple_string(v));
}
void
PQ::Command::bindParamT(unsigned int n, const boost::posix_time::ptime & v)
{
- paramsAtLeast(n);
- auto buf = boost::posix_time::to_iso_extended_string(v);
- values[n] = strdup(buf.c_str());
- formats[n] = 0;
- lengths[n] = buf.length();
+ paramSet(n, boost::posix_time::to_iso_extended_string(v));
}
void
PQ::Command::bindNull(unsigned int n)
diff --git a/libpqpp/pq-command.h b/libpqpp/pq-command.h
index ea32f61..8af2d07 100644
--- a/libpqpp/pq-command.h
+++ b/libpqpp/pq-command.h
@@ -36,12 +36,14 @@ namespace PQ {
Connection * const c;
void paramsAtLeast(unsigned int);
+ template<typename ... T>
+ void paramSet(unsigned int, const char * fmt, const T & ... t);
+ void paramSet(unsigned int, const std::string &);
std::vector<char *> values;
std::vector<int> lengths;
- std::vector<int> formats;
+ std::vector<std::string *> bufs;
};
}
#endif
-
diff --git a/libpqpp/pq-modifycommand.cpp b/libpqpp/pq-modifycommand.cpp
index e08057a..4c4ca0c 100644
--- a/libpqpp/pq-modifycommand.cpp
+++ b/libpqpp/pq-modifycommand.cpp
@@ -32,7 +32,7 @@ unsigned int
PQ::ModifyCommand::execute(bool anc)
{
prepare();
- PGresult * res = PQexecPrepared(c->conn, stmntName.c_str(), values.size(), &values.front(), &lengths.front(), &formats.front(), 0);
+ PGresult * res = PQexecPrepared(c->conn, stmntName.c_str(), values.size(), &values.front(), &lengths.front(), NULL, 0);
c->checkResult(res, PGRES_COMMAND_OK, PGRES_TUPLES_OK);
unsigned int rows = atoi(PQcmdTuples(res));
PQclear(res);
diff --git a/libpqpp/pq-selectcommand.cpp b/libpqpp/pq-selectcommand.cpp
index 55dc02c..f8f44fd 100644
--- a/libpqpp/pq-selectcommand.cpp
+++ b/libpqpp/pq-selectcommand.cpp
@@ -21,6 +21,9 @@ PQ::SelectCommand::SelectCommand(Connection * conn, const std::string & sql, uns
PQ::SelectCommand::~SelectCommand()
{
+ if (execRes) {
+ PQclear(execRes);
+ }
if (executed) {
c->checkResultFree((PQexec(c->conn, s_close.c_str())), PGRES_COMMAND_OK);
}
@@ -66,7 +69,7 @@ PQ::SelectCommand::execute()
txOpened = true;
}
execRes = c->checkResult(
- PQexecParams(c->conn, s_declare.c_str(), values.size(), NULL, &values.front(), &lengths.front(), &formats.front(), 0),
+ PQexecParams(c->conn, s_declare.c_str(), values.size(), NULL, &values.front(), &lengths.front(), NULL, 0),
PGRES_COMMAND_OK);
fetchTuples();
unsigned int nFields = PQnfields(execRes);
diff --git a/libpqpp/unittests/testpq.cpp b/libpqpp/unittests/testpq.cpp
index 96e5611..80757db 100644
--- a/libpqpp/unittests/testpq.cpp
+++ b/libpqpp/unittests/testpq.cpp
@@ -54,6 +54,31 @@ BOOST_AUTO_TEST_CASE( bindAndSend )
mod->bindParamT(4, testDateTime);
mod->bindParamT(5, testInterval);
mod->execute();
+ mod->bindParamI(0, (unsigned int)(testInt + 10));
+ mod->bindParamF(1, (float)(testDouble + 10));
+ mod->bindParamS(2, testString + " something");
+ mod->bindParamB(3, true);
+ mod->bindParamT(4, testDateTime);
+ mod->bindParamT(5, testInterval);
+ mod->execute();
+ mod->bindNull(0);
+ mod->bindParamI(1, (long long unsigned int)(testDouble + 10));
+ mod->bindParamI(2, (long long int)testInt);
+ mod->bindParamB(3, true);
+ mod->bindNull(4);
+ mod->bindNull(5);
+ mod->execute();
+ mod->bindNull(0);
+ mod->bindParamI(1, (long unsigned int)(testDouble + 10));
+ mod->bindParamI(2, (long int)testInt);
+ mod->bindParamB(3, true);
+ mod->bindParamS(4, "2016-01-01T12:34:56");
+ mod->bindNull(5);
+ mod->execute();
+ delete mod;
+ mod = rw->newModifyCommand("DELETE FROM test WHERE string = '?'");
+ BOOST_REQUIRE_THROW(mod->execute(false), DB::NoRowsAffected);
+ BOOST_REQUIRE_EQUAL(0, mod->execute(true));
delete mod;
delete rw;
}
@@ -103,8 +128,9 @@ BOOST_AUTO_TEST_CASE( bindAndSelectOther )
{
auto ro = DB::MockDatabase::openConnectionTo("pqmock");
- auto select = ro->newSelectCommand("SELECT * FROM test WHERE id != ?");
+ auto select = ro->newSelectCommand("SELECT * FROM test WHERE id != ? AND id != ?");
select->bindParamI(0, testInt);
+ select->bindParamI(1, testInt + 10);
select->execute();
int rows = 0;
while (select->fetch()) {