summaryrefslogtreecommitdiff
path: root/lib/output/pq
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2021-05-24 01:01:30 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2021-05-24 01:01:30 +0100
commit15c1e5566f7ad8448985ca6e52805ceb4ec389a8 (patch)
tree14908b221d01cca00975da84656adcea57898620 /lib/output/pq
parentMinor tidy up of replStream (diff)
downloadmygrate-15c1e5566f7ad8448985ca6e52805ceb4ec389a8.tar.bz2
mygrate-15c1e5566f7ad8448985ca6e52805ceb4ec389a8.tar.xz
mygrate-15c1e5566f7ad8448985ca6e52805ceb4ec389a8.zip
Basic support for queries with bound parameters
Bit of a reshuffle to make the types not DB specific, add some basic tests over query execution, no selects yet and no validation anything is actually right.
Diffstat (limited to 'lib/output/pq')
-rw-r--r--lib/output/pq/pqConn.cpp70
-rw-r--r--lib/output/pq/pqConn.h8
2 files changed, 77 insertions, 1 deletions
diff --git a/lib/output/pq/pqConn.cpp b/lib/output/pq/pqConn.cpp
index 78cdc06..4f55ba8 100644
--- a/lib/output/pq/pqConn.cpp
+++ b/lib/output/pq/pqConn.cpp
@@ -1,8 +1,17 @@
#include "pqConn.h"
+#include <dbTypes.h>
#include <helpers.h>
+#include <libpq-fe.h>
+#include <memory>
+#include <sstream>
#include <stdexcept>
+#include <string>
+#include <variant>
+#include <vector>
namespace MyGrate::Output::Pq {
+ using ResPtr = std::unique_ptr<PGresult, decltype(&PQclear)>;
+
PqConn::PqConn(const char * const str) : conn {PQconnectdb(str)}
{
verify<std::runtime_error>(PQstatus(conn) == CONNECTION_OK, "Connection failure");
@@ -15,6 +24,67 @@ namespace MyGrate::Output::Pq {
}
void
+ PqConn::query(const char * const q)
+ {
+ ResPtr res {PQexec(conn, q), &PQclear};
+ verify<std::runtime_error>(PQresultStatus(res.get()) == PGRES_COMMAND_OK, q);
+ }
+
+ struct Bindings {
+ // NOLINTNEXTLINE(hicpp-explicit-conversions)
+ explicit Bindings(const std::initializer_list<DbValue> & vs)
+ {
+ bufs.reserve(vs.size());
+ values.reserve(vs.size());
+ lengths.reserve(vs.size());
+ for (const auto & v : vs) {
+ std::visit(*this, v);
+ }
+ }
+ template<Stringable T>
+ void
+ operator()(const T & v)
+ {
+ bufs.emplace_back(std::to_string(v));
+ const auto & vw {bufs.back()};
+ values.emplace_back(vw.data());
+ lengths.emplace_back(vw.length());
+ }
+ template<Viewable T>
+ void
+ operator()(const T & v)
+ {
+ values.emplace_back(v.data());
+ lengths.emplace_back(v.size());
+ }
+ template<typename T>
+ void
+ operator()(const T &)
+ {
+ throw std::runtime_error("Not implemented");
+ }
+ void
+ operator()(const std::nullptr_t &)
+ {
+ values.emplace_back(nullptr);
+ lengths.emplace_back(0);
+ }
+
+ std::vector<std::string> bufs;
+ std::vector<const char *> values;
+ std::vector<int> lengths;
+ };
+
+ void
+ PqConn::query(const char * const q, const std::initializer_list<DbValue> & vs)
+ {
+ Bindings b {vs};
+ ResPtr res {PQexecParams(conn, q, (int)vs.size(), nullptr, b.values.data(), b.lengths.data(), nullptr, 0),
+ &PQclear};
+ verify<std::runtime_error>(PQresultStatus(res.get()) == PGRES_COMMAND_OK, q);
+ }
+
+ void
PqConn::notice_processor(void * p, const char * n)
{
return static_cast<PqConn *>(p)->notice_processor(n);
diff --git a/lib/output/pq/pqConn.h b/lib/output/pq/pqConn.h
index bcf30b6..613af6f 100644
--- a/lib/output/pq/pqConn.h
+++ b/lib/output/pq/pqConn.h
@@ -1,14 +1,20 @@
#ifndef MYGRATE_OUTPUT_PQ_PQCONN_H
#define MYGRATE_OUTPUT_PQ_PQCONN_H
+#include <dbConn.h>
+#include <dbTypes.h>
+#include <initializer_list>
#include <libpq-fe.h>
namespace MyGrate::Output::Pq {
- class PqConn {
+ class PqConn : public DbConn {
public:
explicit PqConn(const char * const str);
virtual ~PqConn();
+ void query(const char * const) override;
+ void query(const char * const, const std::initializer_list<DbValue> &) override;
+
private:
static void notice_processor(void *, const char *);
virtual void notice_processor(const char *) const;