summaryrefslogtreecommitdiff
path: root/lib/input/mysqlRecordSet.cpp
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2021-05-31 13:18:17 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2021-05-31 13:18:17 +0100
commit63b2ca0dbdae190941d60a55c9cff99d4a75a0e1 (patch)
treed3766bcbc98fb5fb0fb2d8dddf2f194bedcb0325 /lib/input/mysqlRecordSet.cpp
parentMap std::size_t to a sensible header (diff)
downloadmygrate-63b2ca0dbdae190941d60a55c9cff99d4a75a0e1.tar.bz2
mygrate-63b2ca0dbdae190941d60a55c9cff99d4a75a0e1.tar.xz
mygrate-63b2ca0dbdae190941d60a55c9cff99d4a75a0e1.zip
Initial commit of prepstmt, selects, record sets
This is full of holes, but all the basics are covered.
Diffstat (limited to 'lib/input/mysqlRecordSet.cpp')
-rw-r--r--lib/input/mysqlRecordSet.cpp99
1 files changed, 99 insertions, 0 deletions
diff --git a/lib/input/mysqlRecordSet.cpp b/lib/input/mysqlRecordSet.cpp
new file mode 100644
index 0000000..51be15f
--- /dev/null
+++ b/lib/input/mysqlRecordSet.cpp
@@ -0,0 +1,99 @@
+#include "mysqlRecordSet.h"
+#include "mysqlBindings.h"
+#include "mysqlStmt.h"
+#include <cstdint>
+#include <dbTypes.h>
+#include <helpers.h>
+#include <stdexcept>
+#include <string_view>
+#include <utility>
+// IWYU pragma: no_include <ext/alloc_traits.h>
+
+namespace MyGrate::Input {
+ MySQLRecordSet::MySQLRecordSet(StmtPtr s) :
+ stmt {std::move(s)}, stmtres {nullptr, nullptr}, fields(mysql_stmt_field_count(stmt.get())),
+ extras(fields.size())
+ {
+ auto getBind = [](const MYSQL_FIELD & f, MYSQL_BIND & b) -> std::unique_ptr<ResultData> {
+ switch (f.type) {
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_NEWDECIMAL:
+ case MYSQL_TYPE_DOUBLE:
+ return std::make_unique<ResultDataT<double>>(b, f);
+ case MYSQL_TYPE_FLOAT:
+ return std::make_unique<ResultDataT<float>>(b, f);
+ case MYSQL_TYPE_TINY:
+ return std::make_unique<ResultDataT<int8_t>>(b, f);
+ case MYSQL_TYPE_SHORT:
+ case MYSQL_TYPE_YEAR:
+ return std::make_unique<ResultDataT<int16_t>>(b, f);
+ case MYSQL_TYPE_LONG:
+ case MYSQL_TYPE_INT24:
+ return std::make_unique<ResultDataT<int32_t>>(b, f);
+ case MYSQL_TYPE_LONGLONG:
+ return std::make_unique<ResultDataT<int64_t>>(b, f);
+ case MYSQL_TYPE_NULL:
+ return std::make_unique<ResultDataT<std::nullptr_t>>(b, f);
+ case MYSQL_TYPE_TIMESTAMP:
+ case MYSQL_TYPE_TIMESTAMP2:
+ case MYSQL_TYPE_DATETIME:
+ case MYSQL_TYPE_DATETIME2:
+ return std::make_unique<ResultDataTime<DateTime>>(b, f);
+ case MYSQL_TYPE_TIME:
+ case MYSQL_TYPE_TIME2:
+ return std::make_unique<ResultDataTime<Time>>(b, f);
+ case MYSQL_TYPE_DATE:
+ case MYSQL_TYPE_NEWDATE:
+ return std::make_unique<ResultDataTime<Date>>(b, f);
+ case MYSQL_TYPE_VARCHAR:
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_JSON:
+ case MYSQL_TYPE_ENUM:
+ return std::make_unique<ResultDataT<std::string_view>>(b, f);
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_BLOB:
+ return std::make_unique<ResultDataT<Blob>>(b, f);
+ case MAX_NO_FIELD_TYPES:
+ case MYSQL_TYPE_BIT:
+ case MYSQL_TYPE_SET:
+ case MYSQL_TYPE_GEOMETRY:;
+ }
+ throw std::runtime_error("Unsupported column type");
+ };
+ ResPtr meta {mysql_stmt_result_metadata(stmt.get()), mysql_free_result};
+ const auto fieldDefs = mysql_fetch_fields(meta.get());
+ verify<std::runtime_error>(fieldDefs, "Fetch fields");
+ for (std::size_t i = 0; i < fields.size(); i += 1) {
+ extras[i] = getBind(fieldDefs[i], fields[i]);
+ }
+ verify<std::runtime_error>(!mysql_stmt_bind_result(stmt.get(), fields.data()), "Store result error");
+ verify<std::runtime_error>(!mysql_stmt_store_result(stmt.get()), "Store result error");
+ stmtres = {stmt.get(), mysql_stmt_free_result};
+ verify<std::runtime_error>(!mysql_stmt_fetch(stmt.get()), "Fetch");
+ }
+
+ std::size_t
+ MySQLRecordSet::rows() const
+ {
+ return mysql_stmt_num_rows(stmt.get());
+ }
+
+ std::size_t
+ MySQLRecordSet::columns() const
+ {
+ return fields.size();
+ }
+
+ DbValue
+ MySQLRecordSet::at(std::size_t row, std::size_t col) const
+ {
+ mysql_stmt_data_seek(stmt.get(), row);
+ if (extras[col]->null) {
+ return nullptr;
+ }
+ return extras[col]->getValue();
+ }
+}