summaryrefslogtreecommitdiff
path: root/lib/output
diff options
context:
space:
mode:
authorDan Goodliffe <dan@randomdan.homeip.net>2021-06-27 18:51:59 +0100
committerDan Goodliffe <dan@randomdan.homeip.net>2021-06-27 18:51:59 +0100
commit01ccd4e00d0990bd191ccc07a22895a68df65634 (patch)
tree49fe02a9a72ffa7d4d410231d2b7392f635cc357 /lib/output
parentGeneral purpose optional stream<< (diff)
downloadmygrate-01ccd4e00d0990bd191ccc07a22895a68df65634.tar.bz2
mygrate-01ccd4e00d0990bd191ccc07a22895a68df65634.tar.xz
mygrate-01ccd4e00d0990bd191ccc07a22895a68df65634.zip
Basic type mapper
Diffstat (limited to 'lib/output')
-rw-r--r--lib/output/pq/typeMapper.cpp72
-rw-r--r--lib/output/pq/typeMapper.h48
2 files changed, 120 insertions, 0 deletions
diff --git a/lib/output/pq/typeMapper.cpp b/lib/output/pq/typeMapper.cpp
new file mode 100644
index 0000000..5583319
--- /dev/null
+++ b/lib/output/pq/typeMapper.cpp
@@ -0,0 +1,72 @@
+#include "typeMapper.h"
+#include <compileTimeFormatter.h>
+
+namespace MyGrate::Output::Pq {
+ TypeMapper::RegexMapper::RegexMapper(std::optional<ObsRegex> t, std::optional<ObsRegex> c, std::string tt) :
+ typeMatch {std::move(t)}, columnMatch {std::move(c)}, targetType {std::move(tt)}
+ {
+ }
+
+ std::optional<std::string_view>
+ TypeMapper::RegexMapper::map(std::string_view typeName, std::string_view columnName) const
+ {
+ if ((!typeMatch || std::regex_match(typeName.begin(), typeName.end(), *typeMatch))
+ && (!columnMatch || std::regex_match(columnName.begin(), columnName.end(), *columnMatch))) {
+ if (targetType.empty()) {
+ return {typeName};
+ }
+ return {targetType};
+ }
+ return {};
+ }
+
+ TypeMapper::TypeMapper()
+ {
+ const auto add = [this](auto r, auto t) {
+ mappings.emplace_back(std::make_unique<RegexMapper>(r, std::nullopt, t));
+ };
+ // https://dev.mysql.com/doc/refman/8.0/en/numeric-types.html
+ add(R"(bit\(\d+\))"_r, "");
+ add(R"(tinyint\(1\)( (un)?signed)?)"_r, "boolean");
+ add(R"((tiny|small)int(\(\d+\))?( (un)?signed)?)"_r, "smallint");
+ add(R"((medium)?int(\(\d+\))?( (un)?signed)?)"_r, "int");
+ add(R"(bigint(\(\d+\))?( (un)?signed)?)"_r, "bigint");
+ add(R"((numeric|decimal)(\(\d+(,\d+)?\))?)"_r, "");
+ add(R"(float(\(\d+,\d+\))?)"_r, "float");
+ add(R"((real|double( precision)?)(\(\d+,\d+\))?)"_r, "double");
+ // https://dev.mysql.com/doc/refman/8.0/en/date-and-time-types.html
+ add(R"(date)"_r, "date");
+ add(R"(datetime)"_r, "timestamp without time zone");
+ add(R"(datetime(\(\d+\))?)"_r, "timestamp without time zone"); // drops precision
+ add(R"(timestamp)"_r, "timestamp without time zone");
+ add(R"(timestamp(\(\d+\))?)"_r, "timestamp without time zone"); // drops precision
+ add(R"(time)"_r, "time without time zone");
+ add(R"(time(\(\d+\))?)"_r, "time without time zone"); // drops precision
+ add(R"(year)"_r, "smallint");
+ // https://dev.mysql.com/doc/refman/8.0/en/string-types.html
+ add(R"((var)?binary(\(\d+\))?)"_r, "bytea");
+ add(R"((var)?char(\(\d+\))?)"_r, "");
+ add(R"((tiny||medium|long)blob(\(\d+\))?)"_r, "bytea");
+ add(R"((tiny||medium|long)text(\(\d+\))?)"_r, "text");
+ add(R"(enum(.*))"_r, "text"); // not really
+ // set
+ // https://dev.mysql.com/doc/refman/8.0/en/json.html
+ add(R"(json)"_r, "json");
+ }
+
+ std::string_view
+ TypeMapper::map(std::string_view t, std::string_view n) const
+ {
+ for (const auto & m : mappings) {
+ if (const auto rt {m->map(t, n)}) {
+ return *rt;
+ }
+ }
+ throw std::runtime_error(scprintf<"No mapping for %? (%?)">(n, t));
+ }
+
+ TypeMapper::ObsRegex operator""_r(const char * input, std::size_t)
+ {
+ return MyGrate::Output::Pq::TypeMapper::ObsRegex {input, std::regex::icase};
+ }
+}
diff --git a/lib/output/pq/typeMapper.h b/lib/output/pq/typeMapper.h
new file mode 100644
index 0000000..7005e4f
--- /dev/null
+++ b/lib/output/pq/typeMapper.h
@@ -0,0 +1,48 @@
+#ifndef MYGRATE_OUTPUT_PQ_TYPEMAPPER_H
+#define MYGRATE_OUTPUT_PQ_TYPEMAPPER_H
+
+#include <optional>
+#include <regex>
+#include <string>
+#include <string_view>
+#include <vector>
+
+namespace MyGrate::Output::Pq {
+ class TypeMapper {
+ public:
+ class ObsRegex : public std::regex {
+ public:
+ explicit ObsRegex(const std::string & src, std::regex_constants::syntax_option_type sot = {}) :
+ std::regex {src, sot}, src {src}
+ {
+ }
+ const std::string src;
+ };
+
+ struct Mapping {
+ virtual std::optional<std::string_view> map(std::string_view t, std::string_view n) const = 0;
+ };
+ using MappingPtr = std::unique_ptr<Mapping>;
+
+ struct RegexMapper : public Mapping {
+ RegexMapper(std::optional<ObsRegex>, std::optional<ObsRegex>, std::string);
+
+ std::optional<std::string_view> map(std::string_view t, std::string_view n) const override;
+
+ std::optional<ObsRegex> typeMatch;
+ std::optional<ObsRegex> columnMatch;
+ std::string targetType;
+ };
+
+ TypeMapper();
+
+ std::string_view map(std::string_view t, std::string_view n) const;
+
+ private:
+ std::vector<MappingPtr> mappings;
+ };
+
+ TypeMapper::ObsRegex operator""_r(const char * input, std::size_t);
+}
+
+#endif