From 63b2ca0dbdae190941d60a55c9cff99d4a75a0e1 Mon Sep 17 00:00:00 2001 From: Dan Goodliffe Date: Mon, 31 May 2021 13:18:17 +0100 Subject: Initial commit of prepstmt, selects, record sets This is full of holes, but all the basics are covered. --- lib/dbStmt.h | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 lib/dbStmt.h (limited to 'lib/dbStmt.h') diff --git a/lib/dbStmt.h b/lib/dbStmt.h new file mode 100644 index 0000000..3e98b34 --- /dev/null +++ b/lib/dbStmt.h @@ -0,0 +1,66 @@ +#ifndef MYGRATE_DBSTMT_H +#define MYGRATE_DBSTMT_H + +#include +#include +#include +#include +#include +#include + +namespace MyGrate { + class DbConn; + enum class ParamMode { None, DollarNum, QMark }; + + template class DbStmt { + public: + // This don't account for common table expressions, hopefully won't need those :) + static constexpr auto isSelect {S.v().starts_with("SELECT") || S.v().starts_with("SHOW") + || S.v().find("RETURNING") != std::string_view::npos}; + + // These don't account for string literals, which we'd prefer to avoid anyway :) + static constexpr auto paramCount {[]() -> std::size_t { + switch (pm) { + case ParamMode::None: + return 0LU; + case ParamMode::DollarNum: { + const auto pn = [](const char * c, const char * const e) { + std::size_t n {0}; + while (++c != e && *c >= '0' && *c <= '9') { + n = (n * 10) + (*c - '0'); + } + return n; + }; + return pn(std::max_element(S.v().begin(), S.v().end(), + [pn, e = S.v().end()](const char & a, const char & b) { + return (a == '$' ? pn(&a, e) : 0) < (b == '$' ? pn(&b, e) : 0); + }), + S.v().end()); + } + case ParamMode::QMark: + return std::count_if(S.v().begin(), S.v().end(), [](char c) { + return c == '?'; + }); + } + }()}; + + using Return = std::conditional_t; + + template + static Return + execute(DbConn * c, P &&... p) + { + static_assert(sizeof...(P) == paramCount); + auto stmt {c->prepare(S, sizeof...(P))}; + stmt->execute({std::forward(p)...}); + if constexpr (isSelect) { + return stmt->recordSet(); + } + else { + return stmt->rows(); + } + } + }; +} + +#endif -- cgit v1.2.3