From f9fc8240229cd1f059bfc56eb027aec11fec6b4c Mon Sep 17 00:00:00 2001
From: Dan Goodliffe <dan@randomdan.homeip.net>
Date: Wed, 4 Jan 2017 02:00:04 +0000
Subject: C++ify the SQL preparer and skip it if no variables are being bound

---
 libpqpp/pq-command.cpp             | 20 ++++++++++++--------
 libpqpp/pq-command.h               |  2 +-
 libpqpp/pq-cursorselectcommand.cpp | 11 +++++++----
 libpqpp/pq-prepared.cpp            |  5 ++---
 4 files changed, 22 insertions(+), 16 deletions(-)

(limited to 'libpqpp')

diff --git a/libpqpp/pq-command.cpp b/libpqpp/pq-command.cpp
index 84eaa43..af203cc 100644
--- a/libpqpp/pq-command.cpp
+++ b/libpqpp/pq-command.cpp
@@ -25,22 +25,26 @@ PQ::Command::~Command()
 	}
 }
 
+AdHocFormatter(PQCommandParamName, "$%?");
 void
-PQ::Command::prepareSql(std::string & psql, const std::string & sql)
+PQ::Command::prepareSql(std::stringstream & psql, const std::string & sql) const
 {
-	char buf[10];
+	if (values.empty()) {
+		psql << sql;
+		return;
+	}
 	int p = 1;
 	bool inquote = false;
-	for(std::string::const_iterator i = sql.begin(); i != sql.end(); ++i) {
-		if (*i == '?' && !inquote) {
-			psql.append(buf, snprintf(buf, 10, "$%d", p++));
+	for (const auto & i : sql) {
+		if (i == '?' && !inquote) {
+			PQCommandParamName::write(psql, p++);
 		}
-		else if (*i == '\'') {
+		else if (i == '\'') {
 			inquote = !inquote;
-			psql += *i;
+			psql << i;
 		}
 		else {
-			psql += *i;
+			psql << i;
 		}
 	}
 }
diff --git a/libpqpp/pq-command.h b/libpqpp/pq-command.h
index 8af2d07..2c0bf14 100644
--- a/libpqpp/pq-command.h
+++ b/libpqpp/pq-command.h
@@ -31,7 +31,7 @@ namespace PQ {
 
 			void bindNull(unsigned int) override;
 		protected:
-			static void prepareSql(std::string & psql, const std::string & sql);
+			void prepareSql(std::stringstream & psql, const std::string & sql) const;
 			const std::string stmntName;
 			Connection * const c;
 
diff --git a/libpqpp/pq-cursorselectcommand.cpp b/libpqpp/pq-cursorselectcommand.cpp
index 4ee6e80..ac4b825 100644
--- a/libpqpp/pq-cursorselectcommand.cpp
+++ b/libpqpp/pq-cursorselectcommand.cpp
@@ -3,7 +3,7 @@
 #include "pq-error.h"
 #include <compileTimeFormatter.h>
 
-AdHocFormatter(PQCursorSelectDeclare, "DECLARE %? CURSOR FOR %?");
+AdHocFormatter(PQCursorSelectDeclare, "DECLARE %? CURSOR FOR ");
 AdHocFormatter(PQCursorSelectFetch, "FETCH %? IN %?");
 AdHocFormatter(PQCursorSelectClose, "CLOSE %?");
 
@@ -14,7 +14,6 @@ PQ::CursorSelectCommand::CursorSelectCommand(Connection * conn, const std::strin
 	executed(false),
 	txOpened(false),
 	fTuples(35),
-	s_declare(mkdeclare()),
 	s_fetch(PQCursorSelectFetch::get(fTuples, stmntName)),
 	s_close(PQCursorSelectClose::get(stmntName))
 {
@@ -33,9 +32,10 @@ PQ::CursorSelectCommand::~CursorSelectCommand()
 std::string
 PQ::CursorSelectCommand::mkdeclare() const
 {
-	std::string psql;
+	std::stringstream psql;
+	PQCursorSelectDeclare::write(psql, stmntName);
 	prepareSql(psql, sql);
-	return PQCursorSelectDeclare::get(stmntName, psql);
+	return psql.str();
 }
 
 void
@@ -46,6 +46,9 @@ PQ::CursorSelectCommand::execute()
 			c->beginTx();
 			txOpened = true;
 		}
+		if (s_declare.empty()) {
+			s_declare = mkdeclare();
+		}
 		c->checkResultFree(
 				PQexecParams(c->conn, s_declare.c_str(), values.size(), NULL, &values.front(), &lengths.front(), NULL, 0),
 				PGRES_COMMAND_OK);
diff --git a/libpqpp/pq-prepared.cpp b/libpqpp/pq-prepared.cpp
index bdf2a7d..8e6cea5 100644
--- a/libpqpp/pq-prepared.cpp
+++ b/libpqpp/pq-prepared.cpp
@@ -19,11 +19,10 @@ PQ::PreparedStatement::prepare() const
 	if (i != c->preparedStatements.end()) {
 		return (pstmt = i->second.c_str());
 	}
-	std::string psql;
-	psql.reserve(sql.length() + 20);
+	std::stringstream psql;
 	prepareSql(psql, sql);
 	c->checkResultFree(PQprepare(
-				c->conn, stmntName.c_str(), psql.c_str(), values.size(), NULL), PGRES_COMMAND_OK);
+				c->conn, stmntName.c_str(), psql.str().c_str(), values.size(), NULL), PGRES_COMMAND_OK);
 	return (pstmt = c->preparedStatements.insert({hash, stmntName}).first->second.c_str());
 }
 
-- 
cgit v1.2.3