summaryrefslogtreecommitdiff
path: root/lib/row.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/row.cpp')
-rw-r--r--lib/row.cpp101
1 files changed, 101 insertions, 0 deletions
diff --git a/lib/row.cpp b/lib/row.cpp
new file mode 100644
index 0000000..d59cdba
--- /dev/null
+++ b/lib/row.cpp
@@ -0,0 +1,101 @@
+#include "row.h"
+#include <stdexcept>
+#include <string>
+
+namespace MyGrate {
+ Row::Row(const st_mariadb_rpl_rows_event & r, const st_mariadb_rpl_table_map_event & t) : row {r}, tm {t} { }
+
+ void
+ Row::forEachField(const std::function<void(MySQL::FieldValue)> & cb)
+ {
+ MyGrate::RawDataReader md {tm.metadata};
+ MyGrate::RawDataReader data {row.row_data, row.row_data_size};
+ const size_t flagBytes {(tm.column_count + 7) / 8};
+ MyGrate::BitSet nullFlags {data.viewValue<std::span<const std::byte>>(flagBytes)};
+ MyGrate::BitSet columnFlags {{reinterpret_cast<const std::byte *>(row.column_bitmap), flagBytes}};
+ auto nullIter {nullFlags.begin()};
+ auto colIter {columnFlags.begin()};
+ for (auto c {0U}; c < tm.column_count; c++) {
+ if (*colIter) {
+ const enum_field_types type {(enum_field_types)(unsigned char)tm.column_types.str[c]};
+ const auto null {*nullIter};
+ if (null) {
+ switch (type) {
+ case MYSQL_TYPE_BIT:
+ case MYSQL_TYPE_ENUM:
+ case MYSQL_TYPE_SET:
+ case MYSQL_TYPE_NEWDECIMAL:
+ case MYSQL_TYPE_DECIMAL:
+ case MYSQL_TYPE_VARCHAR:
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_STRING:
+ md.discard(2);
+ break;
+ case MYSQL_TYPE_TINY_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_FLOAT:
+ case MYSQL_TYPE_DOUBLE:
+ case MYSQL_TYPE_TIMESTAMP2:
+ case MYSQL_TYPE_DATETIME2:
+ case MYSQL_TYPE_TIME2:
+ md.discard(1);
+ break;
+ default:;
+ }
+ cb(nullptr);
+ }
+ else {
+ switch (type) {
+#define TYPE_CALLBACK(T) \
+ case T: \
+ cb(MySQL::Type<T>::read(md, data)); \
+ break
+ TYPE_CALLBACK(MYSQL_TYPE_DECIMAL);
+ TYPE_CALLBACK(MYSQL_TYPE_TINY);
+ TYPE_CALLBACK(MYSQL_TYPE_SHORT);
+ TYPE_CALLBACK(MYSQL_TYPE_LONG);
+ TYPE_CALLBACK(MYSQL_TYPE_FLOAT);
+ TYPE_CALLBACK(MYSQL_TYPE_DOUBLE);
+ TYPE_CALLBACK(MYSQL_TYPE_NULL);
+ TYPE_CALLBACK(MYSQL_TYPE_TIMESTAMP);
+ TYPE_CALLBACK(MYSQL_TYPE_LONGLONG);
+ TYPE_CALLBACK(MYSQL_TYPE_INT24);
+ TYPE_CALLBACK(MYSQL_TYPE_DATE);
+ TYPE_CALLBACK(MYSQL_TYPE_TIME);
+ TYPE_CALLBACK(MYSQL_TYPE_DATETIME);
+ TYPE_CALLBACK(MYSQL_TYPE_YEAR);
+ TYPE_CALLBACK(MYSQL_TYPE_NEWDATE);
+ TYPE_CALLBACK(MYSQL_TYPE_BIT);
+ TYPE_CALLBACK(MYSQL_TYPE_TIMESTAMP2);
+ TYPE_CALLBACK(MYSQL_TYPE_TIME2);
+ TYPE_CALLBACK(MYSQL_TYPE_JSON);
+ TYPE_CALLBACK(MYSQL_TYPE_NEWDECIMAL);
+ TYPE_CALLBACK(MYSQL_TYPE_ENUM);
+ TYPE_CALLBACK(MYSQL_TYPE_SET);
+ TYPE_CALLBACK(MYSQL_TYPE_TINY_BLOB);
+ TYPE_CALLBACK(MYSQL_TYPE_MEDIUM_BLOB);
+ TYPE_CALLBACK(MYSQL_TYPE_LONG_BLOB);
+ TYPE_CALLBACK(MYSQL_TYPE_BLOB);
+ TYPE_CALLBACK(MYSQL_TYPE_GEOMETRY);
+ TYPE_CALLBACK(MYSQL_TYPE_VAR_STRING);
+ TYPE_CALLBACK(MYSQL_TYPE_VARCHAR);
+ TYPE_CALLBACK(MYSQL_TYPE_DATETIME2);
+ TYPE_CALLBACK(MYSQL_TYPE_STRING);
+#undef TYPE_CALLBACK
+ case MAX_NO_FIELD_TYPES:
+ // This is why you don't the end of the enum as member!
+#ifdef NDEBUG
+ [[fallthrough]];
+ default:
+#endif
+ throw std::logic_error("Unknown type: " + std::to_string(type));
+ }
+ }
+ ++nullIter;
+ }
+ ++colIter;
+ }
+ }
+}