diff options
author | Dan Goodliffe <dan@randomdan.homeip.net> | 2021-06-27 18:51:59 +0100 |
---|---|---|
committer | Dan Goodliffe <dan@randomdan.homeip.net> | 2021-06-27 18:51:59 +0100 |
commit | 01ccd4e00d0990bd191ccc07a22895a68df65634 (patch) | |
tree | 49fe02a9a72ffa7d4d410231d2b7392f635cc357 /lib | |
parent | General purpose optional stream<< (diff) | |
download | mygrate-01ccd4e00d0990bd191ccc07a22895a68df65634.tar.bz2 mygrate-01ccd4e00d0990bd191ccc07a22895a68df65634.tar.xz mygrate-01ccd4e00d0990bd191ccc07a22895a68df65634.zip |
Basic type mapper
Diffstat (limited to 'lib')
-rw-r--r-- | lib/output/pq/typeMapper.cpp | 72 | ||||
-rw-r--r-- | lib/output/pq/typeMapper.h | 48 |
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 |