summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2017-01-06 02:11:57 +0000
committerDan Goodliffe <dan@randomdan.homeip.net>2017-01-08 19:33:31 +0000
commite9ecbccaa6547cb067653e7240947a76cc60d8ed (patch)
tree99531b2014984151cf2f3dfc7bdc8ca5e234a600
parentFix bug where prepared statement cache wasn't cleared on connection reset lea... (diff)
downloadlibdbpp-postgresql-e9ecbccaa6547cb067653e7240947a76cc60d8ed.tar.bz2
libdbpp-postgresql-e9ecbccaa6547cb067653e7240947a76cc60d8ed.tar.xz
libdbpp-postgresql-e9ecbccaa6547cb067653e7240947a76cc60d8ed.zip
Use SQL hash for prepared statement names, increases reuse and avoids random reuse
-rw-r--r--libpqpp/pq-bulkselectcommand.cpp4
-rw-r--r--libpqpp/pq-bulkselectcommand.h2
-rw-r--r--libpqpp/pq-command.cpp7
-rw-r--r--libpqpp/pq-command.h4
-rw-r--r--libpqpp/pq-connection.cpp13
-rw-r--r--libpqpp/pq-connection.h2
-rw-r--r--libpqpp/pq-cursorselectcommand.cpp4
-rw-r--r--libpqpp/pq-cursorselectcommand.h2
-rw-r--r--libpqpp/pq-modifycommand.cpp4
-rw-r--r--libpqpp/pq-modifycommand.h2
-rw-r--r--libpqpp/pq-prepared.cpp5
-rw-r--r--libpqpp/pq-prepared.h4
12 files changed, 26 insertions, 27 deletions
diff --git a/libpqpp/pq-bulkselectcommand.cpp b/libpqpp/pq-bulkselectcommand.cpp
index d745e64..503d535 100644
--- a/libpqpp/pq-bulkselectcommand.cpp
+++ b/libpqpp/pq-bulkselectcommand.cpp
@@ -3,10 +3,10 @@
#include "pq-column.h"
#include "pq-error.h"
-PQ::BulkSelectCommand::BulkSelectCommand(Connection * conn, const std::string & sql, unsigned int no, const DB::CommandOptions * opts) :
+PQ::BulkSelectCommand::BulkSelectCommand(Connection * conn, const std::string & sql, const DB::CommandOptions * opts) :
DB::Command(sql),
PQ::SelectBase(sql),
- PQ::PreparedStatement(conn, sql, no, opts),
+ PQ::PreparedStatement(conn, sql, opts),
executed(false)
{
}
diff --git a/libpqpp/pq-bulkselectcommand.h b/libpqpp/pq-bulkselectcommand.h
index a54a5a4..9b76c4d 100644
--- a/libpqpp/pq-bulkselectcommand.h
+++ b/libpqpp/pq-bulkselectcommand.h
@@ -11,7 +11,7 @@ namespace PQ {
class Column;
class BulkSelectCommand : public SelectBase, public PreparedStatement {
public:
- BulkSelectCommand(Connection *, const std::string & sql, unsigned int no, const DB::CommandOptions *);
+ BulkSelectCommand(Connection *, const std::string & sql, const DB::CommandOptions *);
bool fetch() override;
void execute() override;
diff --git a/libpqpp/pq-command.cpp b/libpqpp/pq-command.cpp
index a6259df..5ff83f0 100644
--- a/libpqpp/pq-command.cpp
+++ b/libpqpp/pq-command.cpp
@@ -5,10 +5,11 @@
#include <compileTimeFormatter.h>
#include <boost/date_time/posix_time/posix_time.hpp>
-AdHocFormatter(PQCommondStatement, "pStatement_%?_%?");
-PQ::Command::Command(Connection * conn, const std::string & sql, unsigned int no) :
+AdHocFormatter(PQCommondStatement, "pStatement_id%?");
+PQ::Command::Command(Connection * conn, const std::string & sql, const DB::CommandOptions * opts) :
DB::Command(sql),
- stmntName(PQCommondStatement::get(no, this)),
+ hash(opts && opts->hash ? *opts->hash : std::hash<std::string>()(sql)),
+ stmntName(PQCommondStatement::get(hash)),
c(conn)
{
}
diff --git a/libpqpp/pq-command.h b/libpqpp/pq-command.h
index 056706e..e054da8 100644
--- a/libpqpp/pq-command.h
+++ b/libpqpp/pq-command.h
@@ -5,6 +5,7 @@
#include <libpq-fe.h>
#include <vector>
#include <visibility.h>
+#include "pq-connection.h"
namespace PQ {
class Connection;
@@ -21,7 +22,7 @@ namespace PQ {
class Command : public virtual DB::Command {
public:
- Command(Connection *, const std::string & sql, unsigned int no);
+ Command(Connection *, const std::string & sql, const DB::CommandOptions *);
virtual ~Command() = 0;
void bindParamI(unsigned int, int) override;
@@ -44,6 +45,7 @@ namespace PQ {
void bindNull(unsigned int) override;
protected:
void prepareSql(std::stringstream & psql, const std::string & sql) const;
+ Connection::StatementHash hash;
const std::string stmntName;
Connection * const c;
diff --git a/libpqpp/pq-connection.cpp b/libpqpp/pq-connection.cpp
index 547923f..643e021 100644
--- a/libpqpp/pq-connection.cpp
+++ b/libpqpp/pq-connection.cpp
@@ -28,8 +28,7 @@ PQ::ConnectionError::ConnectionError(const PGconn * conn) :
}
PQ::Connection::Connection(const std::string & info) :
- conn(PQconnectdb(info.c_str())),
- pstmntNo(0)
+ conn(PQconnectdb(info.c_str()))
{
if (PQstatus(conn) != CONNECTION_OK) {
ConnectionError ce(conn);
@@ -102,15 +101,15 @@ PQ::Connection::newSelectCommand(const std::string & sql, const DB::CommandOptio
{
auto pqco = dynamic_cast<const CommandOptions *>(opts);
if (pqco && !pqco->useCursor) {
- return new BulkSelectCommand(this, sql, pstmntNo++, opts);
+ return new BulkSelectCommand(this, sql, opts);
}
- return new CursorSelectCommand(this, sql, pstmntNo++, pqco);
+ return new CursorSelectCommand(this, sql, pqco, opts);
}
DB::ModifyCommand *
PQ::Connection::newModifyCommand(const std::string & sql, const DB::CommandOptions * opts)
{
- return new ModifyCommand(this, sql, pstmntNo++, opts);
+ return new ModifyCommand(this, sql, opts);
}
bool
@@ -176,10 +175,12 @@ PQ::Connection::bulkUploadData(const char * data, size_t len) const
}
}
+static const std::string selectLastVal("SELECT lastval()");
+static const DB::CommandOptions selectLastValOpts(std::hash<std::string>()(selectLastVal));
int64_t
PQ::Connection::insertId()
{
- BulkSelectCommand getId(this, "SELECT lastval()", pstmntNo++, NULL);
+ BulkSelectCommand getId(this, selectLastVal, &selectLastValOpts);
int64_t id = -1;
while (getId.fetch()) {
getId[0] >> id;
diff --git a/libpqpp/pq-connection.h b/libpqpp/pq-connection.h
index 1659c13..bb102df 100644
--- a/libpqpp/pq-connection.h
+++ b/libpqpp/pq-connection.h
@@ -47,8 +47,6 @@ namespace PQ {
private:
static bool checkResultInt(PGresult * res, int expected, int alternative);
-
- mutable unsigned int pstmntNo;
};
typedef boost::shared_ptr<Connection> ConnectionPtr;
}
diff --git a/libpqpp/pq-cursorselectcommand.cpp b/libpqpp/pq-cursorselectcommand.cpp
index d130b89..d754680 100644
--- a/libpqpp/pq-cursorselectcommand.cpp
+++ b/libpqpp/pq-cursorselectcommand.cpp
@@ -7,10 +7,10 @@ AdHocFormatter(PQCursorSelectDeclare, "DECLARE %? CURSOR FOR ");
AdHocFormatter(PQCursorSelectFetch, "FETCH %? IN %?");
AdHocFormatter(PQCursorSelectClose, "CLOSE %?");
-PQ::CursorSelectCommand::CursorSelectCommand(Connection * conn, const std::string & sql, unsigned int no, const PQ::CommandOptions * pqco) :
+PQ::CursorSelectCommand::CursorSelectCommand(Connection * conn, const std::string & sql, const PQ::CommandOptions * pqco, const DB::CommandOptions * opts) :
DB::Command(sql),
PQ::SelectBase(sql),
- PQ::Command(conn, sql, no),
+ PQ::Command(conn, sql, opts),
executed(false),
txOpened(false),
fTuples(pqco ? pqco->fetchTuples : 35),
diff --git a/libpqpp/pq-cursorselectcommand.h b/libpqpp/pq-cursorselectcommand.h
index 417cff9..8182210 100644
--- a/libpqpp/pq-cursorselectcommand.h
+++ b/libpqpp/pq-cursorselectcommand.h
@@ -11,7 +11,7 @@ namespace PQ {
class Column;
class CursorSelectCommand : public SelectBase, public Command {
public:
- CursorSelectCommand(Connection *, const std::string & sql, unsigned int no, const PQ::CommandOptions *);
+ CursorSelectCommand(Connection *, const std::string & sql, const PQ::CommandOptions *, const DB::CommandOptions *);
virtual ~CursorSelectCommand();
bool fetch() override;
diff --git a/libpqpp/pq-modifycommand.cpp b/libpqpp/pq-modifycommand.cpp
index f8e4d63..7629f00 100644
--- a/libpqpp/pq-modifycommand.cpp
+++ b/libpqpp/pq-modifycommand.cpp
@@ -3,10 +3,10 @@
#include <stdlib.h>
#include "pq-connection.h"
-PQ::ModifyCommand::ModifyCommand(Connection * conn, const std::string & sql, unsigned int no, const DB::CommandOptions * opts) :
+PQ::ModifyCommand::ModifyCommand(Connection * conn, const std::string & sql, const DB::CommandOptions * opts) :
DB::Command(sql),
DB::ModifyCommand(sql),
- PQ::PreparedStatement(conn, sql, no, opts)
+ PQ::PreparedStatement(conn, sql, opts)
{
}
diff --git a/libpqpp/pq-modifycommand.h b/libpqpp/pq-modifycommand.h
index 4f0a481..18f5a8b 100644
--- a/libpqpp/pq-modifycommand.h
+++ b/libpqpp/pq-modifycommand.h
@@ -8,7 +8,7 @@
namespace PQ {
class ModifyCommand : public DB::ModifyCommand, public PreparedStatement {
public:
- ModifyCommand(Connection *, const std::string & sql, unsigned int no, const DB::CommandOptions *);
+ ModifyCommand(Connection *, const std::string & sql, const DB::CommandOptions *);
virtual ~ModifyCommand();
unsigned int execute(bool) override;
diff --git a/libpqpp/pq-prepared.cpp b/libpqpp/pq-prepared.cpp
index 8e6cea5..63a1cb5 100644
--- a/libpqpp/pq-prepared.cpp
+++ b/libpqpp/pq-prepared.cpp
@@ -1,10 +1,9 @@
#include "pq-prepared.h"
#include "pq-connection.h"
-PQ::PreparedStatement::PreparedStatement(Connection * c, const std::string & sql, unsigned int no, const DB::CommandOptions * opts) :
+PQ::PreparedStatement::PreparedStatement(Connection * c, const std::string & sql, const DB::CommandOptions * opts) :
DB::Command(sql),
- Command(c, sql, no),
- hash(opts && opts->hash ? *opts->hash : std::hash<std::string>()(sql)),
+ Command(c, sql, opts),
pstmt(nullptr)
{
}
diff --git a/libpqpp/pq-prepared.h b/libpqpp/pq-prepared.h
index 0f745c9..d70a388 100644
--- a/libpqpp/pq-prepared.h
+++ b/libpqpp/pq-prepared.h
@@ -2,16 +2,14 @@
#define stuff
#include "pq-command.h"
-#include "pq-connection.h"
namespace PQ {
class PreparedStatement : public Command {
protected:
- PreparedStatement(Connection *, const std::string &, unsigned int, const DB::CommandOptions *);
+ PreparedStatement(Connection *, const std::string &, const DB::CommandOptions *);
virtual ~PreparedStatement() = default;
const char * prepare() const;
- Connection::StatementHash hash;
mutable const char * pstmt;
};
}