summaryrefslogtreecommitdiff
path: root/lib/input
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/input
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/input')
-rw-r--r--lib/input/mysqlConn.cpp78
-rw-r--r--lib/input/mysqlConn.h8
2 files changed, 84 insertions, 2 deletions
diff --git a/lib/input/mysqlConn.cpp b/lib/input/mysqlConn.cpp
index 3a2c9f4..179f9d5 100644
--- a/lib/input/mysqlConn.cpp
+++ b/lib/input/mysqlConn.cpp
@@ -1,9 +1,18 @@
#include "mysqlConn.h"
#include "helpers.h"
+#include <cstddef>
+#include <cstring>
+#include <dbTypes.h>
+#include <memory>
#include <mysql.h>
+#include <mysql_types.h>
#include <stdexcept>
+#include <variant>
+#include <vector>
namespace MyGrate::Input {
+ using StmtPtr = std::unique_ptr<MYSQL_STMT, decltype(&mysql_stmt_close)>;
+
MySQLConn::MySQLConn(
const char * const host, const char * const user, const char * const pass, unsigned short port) :
st_mysql {}
@@ -26,4 +35,73 @@ namespace MyGrate::Input {
{
verify<std::runtime_error>(!mysql_query(this, q), q);
}
+
+ struct Bindings {
+ // NOLINTNEXTLINE(hicpp-explicit-conversions)
+ explicit Bindings(const std::initializer_list<DbValue> & vs)
+ {
+ binds.reserve(vs.size());
+ extras.reserve(vs.size());
+ for (const auto & v : vs) {
+ std::visit(*this, v);
+ }
+ }
+ template<std::integral T>
+ void
+ operator()(const T & v)
+ {
+ auto & b = binds.emplace_back();
+ b.buffer_type = MySQL::CType<T>::type;
+ b.buffer = const_cast<T *>(&v);
+ b.is_unsigned = std::unsigned_integral<T>;
+ }
+ template<std::floating_point T>
+ void
+ operator()(const T & v)
+ {
+ auto & b = binds.emplace_back();
+ b.buffer_type = MySQL::CType<T>::type;
+ b.buffer = const_cast<T *>(&v);
+ }
+ template<Viewable T>
+ void
+ operator()(const T & v)
+ {
+ auto & b = binds.emplace_back();
+ b.buffer_type = MySQL::CType<T>::type;
+ b.buffer = const_cast<typename T::value_type *>(v.data());
+ b.length = &extras.emplace_back(v.size(), 0).len;
+ }
+ void
+ operator()(const std::nullptr_t &)
+ {
+ auto & b = binds.emplace_back();
+ b.buffer = nullptr;
+ b.is_null = &extras.emplace_back(0, 1).null;
+ }
+ template<typename T>
+ void
+ operator()(const T &)
+ {
+ throw std::runtime_error("Not implemented");
+ }
+ struct extra {
+ explicit extra(unsigned long l, my_bool n = 0) : len {l}, null {n} { }
+ unsigned long len;
+ my_bool null;
+ };
+ std::vector<MYSQL_BIND> binds;
+ std::vector<extra> extras;
+ };
+
+ void
+ MySQLConn::query(const char * const q, const std::initializer_list<DbValue> & vs)
+ {
+ StmtPtr stmt {mysql_stmt_init(this), &mysql_stmt_close};
+ verify<std::runtime_error>(!mysql_stmt_prepare(stmt.get(), q, strlen(q)), q);
+ verify<std::logic_error>(mysql_stmt_param_count(stmt.get()) == vs.size(), "Param count mismatch");
+ Bindings b {vs};
+ verify<std::runtime_error>(!mysql_stmt_bind_param(stmt.get(), b.binds.data()), "Param count mismatch");
+ verify<std::runtime_error>(!mysql_stmt_execute(stmt.get()), q);
+ }
}
diff --git a/lib/input/mysqlConn.h b/lib/input/mysqlConn.h
index 2f57f33..9e4ec25 100644
--- a/lib/input/mysqlConn.h
+++ b/lib/input/mysqlConn.h
@@ -1,15 +1,19 @@
#ifndef MYGRATE_INPUT_MYSQLCONN_H
#define MYGRATE_INPUT_MYSQLCONN_H
+#include <dbConn.h>
+#include <dbTypes.h>
+#include <initializer_list>
#include <mysql.h>
namespace MyGrate::Input {
- class MySQLConn : public MYSQL {
+ class MySQLConn : public MYSQL, public DbConn {
public:
MySQLConn(const char * const host, const char * const user, const char * const pass, unsigned short port);
~MySQLConn();
- void query(const char * const);
+ void query(const char * const) override;
+ void query(const char * const q, const std::initializer_list<DbValue> &) override;
};
}