From 56de3f5f9768396525669af327fd00d36e621ada Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Sun, 24 Apr 2016 18:48:23 +0100 Subject: Use prepared statements for bulk selects --- libpqpp/pq-bulkselectcommand.cpp | 5 ++--- libpqpp/pq-bulkselectcommand.h | 5 ++--- libpqpp/pq-modifycommand.cpp | 22 +--------------------- libpqpp/pq-modifycommand.h | 8 ++------ libpqpp/pq-prepared.cpp | 29 +++++++++++++++++++++++++++++ libpqpp/pq-prepared.h | 18 ++++++++++++++++++ 6 files changed, 54 insertions(+), 33 deletions(-) create mode 100644 libpqpp/pq-prepared.cpp create mode 100644 libpqpp/pq-prepared.h diff --git a/libpqpp/pq-bulkselectcommand.cpp b/libpqpp/pq-bulkselectcommand.cpp index 27674f5..8b669f4 100644 --- a/libpqpp/pq-bulkselectcommand.cpp +++ b/libpqpp/pq-bulkselectcommand.cpp @@ -6,10 +6,9 @@ PQ::BulkSelectCommand::BulkSelectCommand(Connection * conn, const std::string & sql, unsigned int no) : DB::Command(sql), DB::SelectCommand(sql), - PQ::Command(conn, sql, no), + PQ::PreparedStatement(conn, sql, no), executed(false) { - prepareSql(preparedSql, sql); } PQ::BulkSelectCommand::~BulkSelectCommand() @@ -24,7 +23,7 @@ PQ::BulkSelectCommand::execute() { if (!executed) { execRes = c->checkResult( - PQexecParams(c->conn, preparedSql.c_str(), values.size(), NULL, &values.front(), &lengths.front(), NULL, 0), + PQexecPrepared(c->conn, prepare(), values.size(), &values.front(), &lengths.front(), NULL, 0), PGRES_TUPLES_OK); nTuples = PQntuples(execRes); tuple = -1; diff --git a/libpqpp/pq-bulkselectcommand.h b/libpqpp/pq-bulkselectcommand.h index aeda42d..58b01aa 100644 --- a/libpqpp/pq-bulkselectcommand.h +++ b/libpqpp/pq-bulkselectcommand.h @@ -3,14 +3,14 @@ #include #include "pq-selectbase.h" -#include "pq-command.h" +#include "pq-prepared.h" #include #include namespace PQ { class Connection; class Column; - class BulkSelectCommand : public DB::SelectCommand, public SelectBase, public Command { + class BulkSelectCommand : public DB::SelectCommand, public SelectBase, public PreparedStatement { public: BulkSelectCommand(Connection *, const std::string & sql, unsigned int no); virtual ~BulkSelectCommand(); @@ -20,7 +20,6 @@ namespace PQ { private: mutable bool executed; - std::string preparedSql; }; } diff --git a/libpqpp/pq-modifycommand.cpp b/libpqpp/pq-modifycommand.cpp index caad5c6..4cc31d2 100644 --- a/libpqpp/pq-modifycommand.cpp +++ b/libpqpp/pq-modifycommand.cpp @@ -6,8 +6,7 @@ PQ::ModifyCommand::ModifyCommand(Connection * conn, const std::string & sql, unsigned int no) : DB::Command(sql), DB::ModifyCommand(sql), - PQ::Command(conn, sql, no), - pstmt(nullptr) + PQ::PreparedStatement(conn, sql, no) { } @@ -15,25 +14,6 @@ PQ::ModifyCommand::~ModifyCommand() { } -const char * -PQ::ModifyCommand::prepare() const -{ - if (pstmt) { - return pstmt; - } - auto hash(std::hash()(sql)); - auto i = c->preparedStatements.find(hash); - if (i != c->preparedStatements.end()) { - return (pstmt = i->second.c_str()); - } - std::string psql; - psql.reserve(sql.length() + 20); - prepareSql(psql, sql); - c->checkResultFree(PQprepare( - c->conn, stmntName.c_str(), psql.c_str(), values.size(), NULL), PGRES_COMMAND_OK); - return (pstmt = c->preparedStatements.insert({hash, stmntName}).first->second.c_str()); -} - unsigned int PQ::ModifyCommand::execute(bool anc) { diff --git a/libpqpp/pq-modifycommand.h b/libpqpp/pq-modifycommand.h index 79593a1..ef50261 100644 --- a/libpqpp/pq-modifycommand.h +++ b/libpqpp/pq-modifycommand.h @@ -2,20 +2,16 @@ #define PQ_MODIFYCOMMAND_H #include -#include "pq-command.h" +#include "pq-prepared.h" #include "pq-connection.h" namespace PQ { - class ModifyCommand : public DB::ModifyCommand, public Command { + class ModifyCommand : public DB::ModifyCommand, public PreparedStatement { public: ModifyCommand(Connection *, const std::string & sql, unsigned int no); virtual ~ModifyCommand(); unsigned int execute(bool) override; - - private: - const char * prepare() const; - mutable const char * pstmt; }; } diff --git a/libpqpp/pq-prepared.cpp b/libpqpp/pq-prepared.cpp new file mode 100644 index 0000000..4cd4540 --- /dev/null +++ b/libpqpp/pq-prepared.cpp @@ -0,0 +1,29 @@ +#include "pq-prepared.h" +#include "pq-connection.h" + +PQ::PreparedStatement::PreparedStatement(Connection * c, const std::string & sql, unsigned int no) : + DB::Command(sql), + Command(c, sql, no), + pstmt(nullptr) +{ +} + +const char * +PQ::PreparedStatement::prepare() const +{ + if (pstmt) { + return pstmt; + } + auto hash(std::hash()(sql)); + auto i = c->preparedStatements.find(hash); + if (i != c->preparedStatements.end()) { + return (pstmt = i->second.c_str()); + } + std::string psql; + psql.reserve(sql.length() + 20); + prepareSql(psql, sql); + c->checkResultFree(PQprepare( + c->conn, stmntName.c_str(), psql.c_str(), values.size(), NULL), PGRES_COMMAND_OK); + return (pstmt = c->preparedStatements.insert({hash, stmntName}).first->second.c_str()); +} + diff --git a/libpqpp/pq-prepared.h b/libpqpp/pq-prepared.h new file mode 100644 index 0000000..1f6e028 --- /dev/null +++ b/libpqpp/pq-prepared.h @@ -0,0 +1,18 @@ +#ifndef stuff +#define stuff + +#include "pq-command.h" + +namespace PQ { + class PreparedStatement : public Command { + protected: + PreparedStatement(Connection *, const std::string &, unsigned int); + virtual ~PreparedStatement() = default; + + const char * prepare() const; + mutable const char * pstmt; + }; +} + +#endif + -- cgit v1.2.3