diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2021-05-24 01:01:30 +0100 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2021-05-24 01:01:30 +0100 |
commit | 15c1e5566f7ad8448985ca6e52805ceb4ec389a8 (patch) | |
tree | 14908b221d01cca00975da84656adcea57898620 /lib/output | |
parent | Minor tidy up of replStream (diff) | |
download | mygrate-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')
-rw-r--r-- | lib/output/pq/pqConn.cpp | 70 | ||||
-rw-r--r-- | lib/output/pq/pqConn.h | 8 |
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; |