diff options
Diffstat (limited to 'lib/input')
-rw-r--r-- | lib/input/mysqlConn.cpp | 78 | ||||
-rw-r--r-- | lib/input/mysqlConn.h | 8 |
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; }; } |