summaryrefslogtreecommitdiff
path: root/lib/output/pq/pqStmt.cpp
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2021-05-31 13:18:17 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2021-05-31 13:18:17 +0100
commit63b2ca0dbdae190941d60a55c9cff99d4a75a0e1 (patch)
treed3766bcbc98fb5fb0fb2d8dddf2f194bedcb0325 /lib/output/pq/pqStmt.cpp
parentMap std::size_t to a sensible header (diff)
downloadmygrate-63b2ca0dbdae190941d60a55c9cff99d4a75a0e1.tar.bz2
mygrate-63b2ca0dbdae190941d60a55c9cff99d4a75a0e1.tar.xz
mygrate-63b2ca0dbdae190941d60a55c9cff99d4a75a0e1.zip
Initial commit of prepstmt, selects, record sets
This is full of holes, but all the basics are covered.
Diffstat (limited to 'lib/output/pq/pqStmt.cpp')
-rw-r--r--lib/output/pq/pqStmt.cpp54
1 files changed, 54 insertions, 0 deletions
diff --git a/lib/output/pq/pqStmt.cpp b/lib/output/pq/pqStmt.cpp
new file mode 100644
index 0000000..04b48c6
--- /dev/null
+++ b/lib/output/pq/pqStmt.cpp
@@ -0,0 +1,54 @@
+#include "pqStmt.h"
+#include "libpq-fe.h"
+#include "pqBindings.h"
+#include "pqConn.h"
+#include "pqRecordSet.h"
+#include <compileTimeFormatter.h>
+#include <cstdlib>
+#include <functional>
+#include <helpers.h>
+#include <map>
+#include <stdexcept>
+#include <utility>
+#include <vector>
+
+namespace MyGrate::Output::Pq {
+ PqPrepStmt::PqPrepStmt(const char * const q, std::size_t n, PqConn * c) :
+ conn {c->conn.get()}, name {prepareAsNeeded(q, n, c)}, res {nullptr, nullptr}
+ {
+ }
+
+ void
+ PqPrepStmt::execute(const std::initializer_list<DbValue> & vs)
+ {
+ Bindings b {vs};
+ res = {PQexecPrepared(conn, name.c_str(), (int)vs.size(), b.values.data(), b.lengths.data(), nullptr, 0),
+ &PQclear};
+ verify<std::runtime_error>(
+ PQresultStatus(res.get()) == PGRES_COMMAND_OK || PQresultStatus(res.get()) == PGRES_TUPLES_OK, name);
+ }
+
+ std::size_t
+ PqPrepStmt::rows() const
+ {
+ return std::strtoul(PQcmdTuples(res.get()), nullptr, 10);
+ }
+
+ RecordSetPtr
+ PqPrepStmt::recordSet()
+ {
+ return std::make_unique<PqRecordSet>(std::move(res));
+ }
+
+ std::string
+ PqPrepStmt::prepareAsNeeded(const char * const q, std::size_t n, PqConn * c)
+ {
+ if (const auto i = c->stmts.find(q); i != c->stmts.end()) {
+ return i->second;
+ }
+ auto nam {AdHoc::scprintf<"pst%0x">(c->stmts.size())};
+ ResPtr res {PQprepare(c->conn.get(), nam.c_str(), q, (int)n, nullptr), PQclear};
+ verify<std::runtime_error>(PQresultStatus(res.get()) == PGRES_COMMAND_OK, q);
+ return c->stmts.emplace(q, std::move(nam)).first->second;
+ }
+}